summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2015-03-11 15:16:13 -0700
committerDianne Hackborn <hackbod@google.com>2015-03-12 17:07:51 -0700
commita83ce1dd2ad3a6b71e90ff4845afc1299fe17b9d (patch)
tree2b0f1d1e65920fdbf7e3b7867070ee32776f246e
parentd6ee06a0c86d9d1556bb4b15c9aaea538e415e38 (diff)
downloadframeworks_base-a83ce1dd2ad3a6b71e90ff4845afc1299fe17b9d.zip
frameworks_base-a83ce1dd2ad3a6b71e90ff4845afc1299fe17b9d.tar.gz
frameworks_base-a83ce1dd2ad3a6b71e90ff4845afc1299fe17b9d.tar.bz2
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
-rw-r--r--Android.mk2
-rw-r--r--api/current.txt49
-rw-r--r--api/system-current.txt49
-rw-r--r--core/java/android/app/Activity.java28
-rw-r--r--core/java/android/app/ActivityManager.java6
-rw-r--r--core/java/android/app/ActivityThread.java11
-rw-r--r--core/java/android/app/AssistContent.aidl19
-rw-r--r--core/java/android/app/AssistContent.java124
-rw-r--r--core/java/android/app/AssistStructure.aidl19
-rw-r--r--core/java/android/app/AssistStructure.java (renamed from core/java/android/app/AssistData.java)169
-rw-r--r--core/java/android/app/ISearchManager.aidl2
-rw-r--r--core/java/android/app/SearchManager.java6
-rw-r--r--core/java/android/content/Intent.java17
-rw-r--r--core/java/android/os/BaseBundle.java3
-rw-r--r--core/java/android/os/Bundle.java23
-rw-r--r--core/java/android/os/PersistableBundle.java40
-rw-r--r--core/java/android/os/PooledStringReader.java50
-rw-r--r--core/java/android/os/PooledStringWriter.java76
-rw-r--r--core/java/android/view/PhoneWindow.java2
-rw-r--r--core/java/android/view/View.java8
-rw-r--r--core/java/android/view/ViewAssistStructure.java (renamed from core/java/android/view/ViewAssistData.java)9
-rw-r--r--core/java/android/widget/Switch.java13
-rw-r--r--core/java/android/widget/TextView.java11
-rw-r--r--core/java/com/android/internal/util/XmlUtils.java58
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java13
-rw-r--r--services/core/java/com/android/server/search/SearchManagerService.java5
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java123
-rw-r--r--tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistProxyActivity.java1
-rw-r--r--tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java20
-rw-r--r--tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java7
-rw-r--r--tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java29
31 files changed, 814 insertions, 178 deletions
diff --git a/Android.mk b/Android.mk
index e42a2f8..452d72c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -550,6 +550,8 @@ aidl_files := \
frameworks/base/core/java/android/service/chooser/ChooserTarget.aidl \
frameworks/base/core/java/android/speech/tts/Voice.aidl \
frameworks/base/core/java/android/app/usage/UsageEvents.aidl \
+ frameworks/base/core/java/android/app/AssistStructure.aidl \
+ frameworks/base/core/java/android/app/AssistContent.aidl \
frameworks/base/core/java/android/app/Notification.aidl \
frameworks/base/core/java/android/app/WallpaperInfo.aidl \
frameworks/base/core/java/android/app/AppOpsManager.aidl \
diff --git a/api/current.txt b/api/current.txt
index 4c24114..13e6dc0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3429,6 +3429,7 @@ package android.app {
method public void onPrepareNavigateUpTaskStack(android.app.TaskStackBuilder);
method public boolean onPrepareOptionsMenu(android.view.Menu);
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public void onProvideAssistContent(android.app.AssistContent);
method public void onProvideAssistData(android.os.Bundle);
method protected void onRestart();
method protected void onRestoreInstanceState(android.os.Bundle);
@@ -3957,20 +3958,33 @@ package android.app {
field public java.lang.String serviceDetails;
}
- public final class AssistData implements android.os.Parcelable {
+ public class AssistContent implements android.os.Parcelable {
+ ctor public AssistContent();
+ method public int describeContents();
+ method public static android.app.AssistContent getAssistContent(android.os.Bundle);
+ method public android.content.ClipData getClipData();
+ method public android.content.Intent getIntent();
+ method public void setClipData(android.content.ClipData);
+ method public void setIntent(android.content.Intent);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final java.lang.String ASSIST_KEY = "android:assist_content";
+ field public static final android.os.Parcelable.Creator<android.app.AssistContent> CREATOR;
+ }
+
+ public final class AssistStructure implements android.os.Parcelable {
method public int describeContents();
method public android.content.ComponentName getActivityComponent();
- method public static android.app.AssistData getAssistData(android.os.Bundle);
- method public void getWindowAt(int, android.app.AssistData.ViewNode);
+ method public static android.app.AssistStructure getAssistStructure(android.os.Bundle);
+ method public void getWindowAt(int, android.app.AssistStructure.ViewNode);
method public int getWindowCount();
method public void writeToParcel(android.os.Parcel, int);
- field public static final java.lang.String ASSIST_KEY = "android:assist";
- field public static final android.os.Parcelable.Creator<android.app.AssistData> CREATOR;
+ field public static final java.lang.String ASSIST_KEY = "android:assist_structure";
+ field public static final android.os.Parcelable.Creator<android.app.AssistStructure> CREATOR;
}
- public static class AssistData.ViewNode {
- ctor public AssistData.ViewNode();
- method public void getChildAt(int, android.app.AssistData.ViewNode);
+ public static class AssistStructure.ViewNode {
+ ctor public AssistStructure.ViewNode();
+ method public void getChildAt(int, android.app.AssistStructure.ViewNode);
method public int getChildCount();
method public java.lang.String getClassName();
method public java.lang.String getContentDescription();
@@ -3980,9 +3994,13 @@ package android.app {
method public int getLeft();
method public int getScrollX();
method public int getScrollY();
- method public java.lang.String getText();
+ method public java.lang.CharSequence getText();
+ method public int getTextBackgroundColor();
+ method public int getTextColor();
method public int getTextSelectionEnd();
method public int getTextSelectionStart();
+ method public float getTextSize();
+ method public int getTextStyle();
method public int getTop();
method public int getVisibility();
method public int getWidth();
@@ -3996,6 +4014,11 @@ package android.app {
method public boolean isFocused();
method public boolean isLongClickable();
method public boolean isSelected();
+ field public static final int TEXT_COLOR_UNDEFINED = 1; // 0x1
+ field public static final int TEXT_STYLE_BOLD = 1; // 0x1
+ field public static final int TEXT_STYLE_ITALIC = 2; // 0x2
+ field public static final int TEXT_STYLE_STRIKE_THRU = 8; // 0x8
+ field public static final int TEXT_STYLE_UNDERLINE = 4; // 0x4
}
public class DatePickerDialog extends android.app.AlertDialog implements android.widget.DatePicker.OnDateChangedListener android.content.DialogInterface.OnClickListener {
@@ -7920,6 +7943,7 @@ package android.content {
field public static final java.lang.String EXTRA_ASSIST_CONTEXT = "android.intent.extra.ASSIST_CONTEXT";
field public static final java.lang.String EXTRA_ASSIST_INPUT_HINT_KEYBOARD = "android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD";
field public static final java.lang.String EXTRA_ASSIST_PACKAGE = "android.intent.extra.ASSIST_PACKAGE";
+ field public static final java.lang.String EXTRA_ASSIST_UID = "android.intent.extra.ASSIST_UID";
field public static final java.lang.String EXTRA_BCC = "android.intent.extra.BCC";
field public static final java.lang.String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
field public static final java.lang.String EXTRA_CC = "android.intent.extra.CC";
@@ -34301,7 +34325,7 @@ package android.view {
method protected void onMeasure(int, int);
method protected void onOverScrolled(int, int, boolean, boolean);
method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
- method public void onProvideAssistData(android.view.ViewAssistData, android.os.Bundle);
+ method public void onProvideAssistStructure(android.view.ViewAssistStructure, android.os.Bundle);
method protected void onRestoreInstanceState(android.os.Parcelable);
method public void onRtlPropertiesChanged(int);
method protected android.os.Parcelable onSaveInstanceState();
@@ -34704,8 +34728,8 @@ package android.view {
method public static android.animation.Animator createCircularReveal(android.view.View, int, int, float, float);
}
- public abstract class ViewAssistData {
- ctor public ViewAssistData();
+ public abstract class ViewAssistStructure {
+ ctor public ViewAssistStructure();
method public abstract java.lang.CharSequence getHint();
method public abstract java.lang.CharSequence getText();
method public abstract int getTextSelectionEnd();
@@ -34713,6 +34737,7 @@ package android.view {
method public abstract void setHint(java.lang.CharSequence);
method public abstract void setText(java.lang.CharSequence);
method public abstract void setText(java.lang.CharSequence, int, int);
+ method public abstract void setTextPaint(android.text.TextPaint);
}
public class ViewConfiguration {
diff --git a/api/system-current.txt b/api/system-current.txt
index d641bd9..0e1ccb1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3512,6 +3512,7 @@ package android.app {
method public void onPrepareNavigateUpTaskStack(android.app.TaskStackBuilder);
method public boolean onPrepareOptionsMenu(android.view.Menu);
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public void onProvideAssistContent(android.app.AssistContent);
method public void onProvideAssistData(android.os.Bundle);
method protected void onRestart();
method protected void onRestoreInstanceState(android.os.Bundle);
@@ -4047,20 +4048,33 @@ package android.app {
field public java.lang.String serviceDetails;
}
- public final class AssistData implements android.os.Parcelable {
+ public class AssistContent implements android.os.Parcelable {
+ ctor public AssistContent();
+ method public int describeContents();
+ method public static android.app.AssistContent getAssistContent(android.os.Bundle);
+ method public android.content.ClipData getClipData();
+ method public android.content.Intent getIntent();
+ method public void setClipData(android.content.ClipData);
+ method public void setIntent(android.content.Intent);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final java.lang.String ASSIST_KEY = "android:assist_content";
+ field public static final android.os.Parcelable.Creator<android.app.AssistContent> CREATOR;
+ }
+
+ public final class AssistStructure implements android.os.Parcelable {
method public int describeContents();
method public android.content.ComponentName getActivityComponent();
- method public static android.app.AssistData getAssistData(android.os.Bundle);
- method public void getWindowAt(int, android.app.AssistData.ViewNode);
+ method public static android.app.AssistStructure getAssistStructure(android.os.Bundle);
+ method public void getWindowAt(int, android.app.AssistStructure.ViewNode);
method public int getWindowCount();
method public void writeToParcel(android.os.Parcel, int);
- field public static final java.lang.String ASSIST_KEY = "android:assist";
- field public static final android.os.Parcelable.Creator<android.app.AssistData> CREATOR;
+ field public static final java.lang.String ASSIST_KEY = "android:assist_structure";
+ field public static final android.os.Parcelable.Creator<android.app.AssistStructure> CREATOR;
}
- public static class AssistData.ViewNode {
- ctor public AssistData.ViewNode();
- method public void getChildAt(int, android.app.AssistData.ViewNode);
+ public static class AssistStructure.ViewNode {
+ ctor public AssistStructure.ViewNode();
+ method public void getChildAt(int, android.app.AssistStructure.ViewNode);
method public int getChildCount();
method public java.lang.String getClassName();
method public java.lang.String getContentDescription();
@@ -4070,9 +4084,13 @@ package android.app {
method public int getLeft();
method public int getScrollX();
method public int getScrollY();
- method public java.lang.String getText();
+ method public java.lang.CharSequence getText();
+ method public int getTextBackgroundColor();
+ method public int getTextColor();
method public int getTextSelectionEnd();
method public int getTextSelectionStart();
+ method public float getTextSize();
+ method public int getTextStyle();
method public int getTop();
method public int getVisibility();
method public int getWidth();
@@ -4086,6 +4104,11 @@ package android.app {
method public boolean isFocused();
method public boolean isLongClickable();
method public boolean isSelected();
+ field public static final int TEXT_COLOR_UNDEFINED = 1; // 0x1
+ field public static final int TEXT_STYLE_BOLD = 1; // 0x1
+ field public static final int TEXT_STYLE_ITALIC = 2; // 0x2
+ field public static final int TEXT_STYLE_STRIKE_THRU = 8; // 0x8
+ field public static final int TEXT_STYLE_UNDERLINE = 4; // 0x4
}
public class DatePickerDialog extends android.app.AlertDialog implements android.widget.DatePicker.OnDateChangedListener android.content.DialogInterface.OnClickListener {
@@ -8134,6 +8157,7 @@ package android.content {
field public static final java.lang.String EXTRA_ASSIST_CONTEXT = "android.intent.extra.ASSIST_CONTEXT";
field public static final java.lang.String EXTRA_ASSIST_INPUT_HINT_KEYBOARD = "android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD";
field public static final java.lang.String EXTRA_ASSIST_PACKAGE = "android.intent.extra.ASSIST_PACKAGE";
+ field public static final java.lang.String EXTRA_ASSIST_UID = "android.intent.extra.ASSIST_UID";
field public static final java.lang.String EXTRA_BCC = "android.intent.extra.BCC";
field public static final java.lang.String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
field public static final java.lang.String EXTRA_CC = "android.intent.extra.CC";
@@ -36469,7 +36493,7 @@ package android.view {
method protected void onMeasure(int, int);
method protected void onOverScrolled(int, int, boolean, boolean);
method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
- method public void onProvideAssistData(android.view.ViewAssistData, android.os.Bundle);
+ method public void onProvideAssistStructure(android.view.ViewAssistStructure, android.os.Bundle);
method protected void onRestoreInstanceState(android.os.Parcelable);
method public void onRtlPropertiesChanged(int);
method protected android.os.Parcelable onSaveInstanceState();
@@ -36872,8 +36896,8 @@ package android.view {
method public static android.animation.Animator createCircularReveal(android.view.View, int, int, float, float);
}
- public abstract class ViewAssistData {
- ctor public ViewAssistData();
+ public abstract class ViewAssistStructure {
+ ctor public ViewAssistStructure();
method public abstract java.lang.CharSequence getHint();
method public abstract java.lang.CharSequence getText();
method public abstract int getTextSelectionEnd();
@@ -36881,6 +36905,7 @@ package android.view {
method public abstract void setHint(java.lang.CharSequence);
method public abstract void setText(java.lang.CharSequence);
method public abstract void setText(java.lang.CharSequence, int, int);
+ method public abstract void setTextPaint(android.text.TextPaint);
}
public class ViewConfiguration {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 9f8befe..02f33b4 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1547,17 +1547,35 @@ public class Activity extends ContextThemeWrapper
* {@link Intent#ACTION_ASSIST} Intent with all of the context of the current
* application. You can override this method to place into the bundle anything
* you would like to appear in the {@link Intent#EXTRA_ASSIST_CONTEXT} part
- * of the assist Intent. The default implementation automatically generates a
- * {@link AssistData} from your activity and places it in to the Bundle; if you
- * don't want your UI reported to the assistant, don't call this default
- * implementation.
+ * of the assist Intent.
*
* <p>This function will be called after any global assist callbacks that had
* been registered with {@link Application#registerOnProvideAssistDataListener
* Application.registerOnProvideAssistDataListener}.
*/
public void onProvideAssistData(Bundle data) {
- data.putParcelable(AssistData.ASSIST_KEY, new AssistData(this));
+ }
+
+ /**
+ * This is called when the user is requesting an assist, to provide references
+ * to content related to the current activity. Before being called, the
+ * {@code outContent} Intent is filled with the base Intent of the activity (the Intent
+ * returned by {@link #getIntent()}). The Intent's extras are stripped of any types
+ * that are not valid for {@link PersistableBundle} or non-framework Parcelables, and
+ * the flags {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION} and
+ * {@link Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION} are cleared from the Intent.
+ *
+ * <p>Custom implementation may adjust the content intent to better reflect the top-level
+ * context of the activity, and fill in its ClipData with additional content of
+ * interest that the user is currently viewing. For example, an image gallery application
+ * that has launched in to an activity allowing the user to swipe through pictures should
+ * modify the intent to reference the current image they are looking it; such an
+ * application when showing a list of pictures should add a ClipData that has
+ * references to all of the pictures currently visible on screen.</p>
+ *
+ * @param outContent The assist content to return.
+ */
+ public void onProvideAssistContent(AssistContent outContent) {
}
/**
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index c525ef2..29b024ac 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -309,6 +309,12 @@ public class ActivityManager {
/** @hide Process is being cached for later use and is empty. */
public static final int PROCESS_STATE_CACHED_EMPTY = 13;
+ /** @hide requestType for assist context: only basic information. */
+ public static final int ASSIST_CONTEXT_BASIC = 0;
+
+ /** @hide requestType for assist context: generate full AssistStructure. */
+ public static final int ASSIST_CONTEXT_FULL = 1;
+
/**
* Lock task mode is not active.
*/
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 97793c5..7b8ec74 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2519,6 +2519,17 @@ public final class ActivityThread {
if (r != null) {
r.activity.getApplication().dispatchOnProvideAssistData(r.activity, data);
r.activity.onProvideAssistData(data);
+ if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL) {
+ data.putParcelable(AssistStructure.ASSIST_KEY, new AssistStructure(r.activity));
+ AssistContent content = new AssistContent();
+ Intent intent = new Intent(r.activity.getIntent());
+ intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION));
+ intent.removeUnsafeExtras();
+ content.setIntent(intent);
+ r.activity.onProvideAssistContent(content);
+ data.putParcelable(AssistContent.ASSIST_KEY, content);
+ }
}
if (data.isEmpty()) {
data = null;
diff --git a/core/java/android/app/AssistContent.aidl b/core/java/android/app/AssistContent.aidl
new file mode 100644
index 0000000..a6321bf
--- /dev/null
+++ b/core/java/android/app/AssistContent.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.app;
+
+parcelable AssistContent;
diff --git a/core/java/android/app/AssistContent.java b/core/java/android/app/AssistContent.java
new file mode 100644
index 0000000..ace4af7
--- /dev/null
+++ b/core/java/android/app/AssistContent.java
@@ -0,0 +1,124 @@
+/*
+ * 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.app;
+
+import android.content.ClipData;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Holds information about the content an application is viewing, to hand to an
+ * assistant at the user's request. This is filled in by
+ * {@link Activity#onProvideAssistContent Activity.onProvideAssistContent}.
+ */
+public class AssistContent implements Parcelable {
+ private Intent mIntent;
+ private ClipData mClipData;
+
+ /**
+ * Key name this data structure is stored in the Bundle generated by
+ * {@link Activity#onProvideAssistData}.
+ */
+ public static final String ASSIST_KEY = "android:assist_content";
+
+ /**
+ * Retrieve the framework-generated AssistContent that is stored within
+ * the Bundle filled in by {@link Activity#onProvideAssistContent}.
+ */
+ public static AssistContent getAssistContent(Bundle assistBundle) {
+ return assistBundle.getParcelable(ASSIST_KEY);
+ }
+
+ public AssistContent() {
+ }
+
+ /**
+ * Sets the Intent associated with the content, describing the current top-level context of
+ * the activity. If this contains a reference to a piece of data related to the activity,
+ * be sure to set {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} so the accessibilty
+ * service can access it.
+ */
+ public void setIntent(Intent intent) {
+ mIntent = intent;
+ }
+
+ /**
+ * Return the current {@link #setIntent}, which you can modify in-place.
+ */
+ public Intent getIntent() {
+ return mIntent;
+ }
+
+ /**
+ * Optional additional content items that are involved with
+ * the current UI. Access to this content will be granted to the assistant as if you
+ * are sending it through an Intent with {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}.
+ */
+ public void setClipData(ClipData clip) {
+ mClipData = clip;
+ }
+
+ /**
+ * Return the current {@link #setClipData}, which you can modify in-place.
+ */
+ public ClipData getClipData() {
+ return mClipData;
+ }
+
+ AssistContent(Parcel in) {
+ if (in.readInt() != 0) {
+ mIntent = Intent.CREATOR.createFromParcel(in);
+ }
+ if (in.readInt() != 0) {
+ mClipData = ClipData.CREATOR.createFromParcel(in);
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (mIntent != null) {
+ dest.writeInt(1);
+ mIntent.writeToParcel(dest, flags);
+ } else {
+ dest.writeInt(0);
+ }
+ if (mClipData != null) {
+ dest.writeInt(1);
+ mClipData.writeToParcel(dest, flags);
+ } else {
+ dest.writeInt(0);
+ }
+ }
+
+ public static final Parcelable.Creator<AssistContent> CREATOR
+ = new Parcelable.Creator<AssistContent>() {
+ public AssistContent createFromParcel(Parcel in) {
+ return new AssistContent(in);
+ }
+
+ public AssistContent[] newArray(int size) {
+ return new AssistContent[size];
+ }
+ };
+}
diff --git a/core/java/android/app/AssistStructure.aidl b/core/java/android/app/AssistStructure.aidl
new file mode 100644
index 0000000..07fb2453
--- /dev/null
+++ b/core/java/android/app/AssistStructure.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.app;
+
+parcelable AssistStructure;
diff --git a/core/java/android/app/AssistData.java b/core/java/android/app/AssistStructure.java
index 7b5eb6d..25153fc 100644
--- a/core/java/android/app/AssistData.java
+++ b/core/java/android/app/AssistStructure.java
@@ -17,13 +17,19 @@
package android.app;
import android.content.ComponentName;
+import android.graphics.Paint;
import android.graphics.Rect;
+import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.PooledStringReader;
+import android.os.PooledStringWriter;
+import android.text.TextPaint;
+import android.text.TextUtils;
import android.util.Log;
import android.view.View;
-import android.view.ViewAssistData;
+import android.view.ViewAssistStructure;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
import android.view.WindowManagerGlobal;
@@ -34,28 +40,32 @@ import java.util.ArrayList;
/**
* Assist data automatically created by the platform's implementation
* of {@link Activity#onProvideAssistData}. Retrieve it from the assist
- * data with {@link #getAssistData(android.os.Bundle)}.
+ * data with {@link #getAssistStructure(android.os.Bundle)}.
*/
-final public class AssistData implements Parcelable {
- static final String TAG = "AssistData";
+final public class AssistStructure implements Parcelable {
+ static final String TAG = "AssistStructure";
/**
* Key name this data structure is stored in the Bundle generated by
* {@link Activity#onProvideAssistData}.
*/
- public static final String ASSIST_KEY = "android:assist";
+ public static final String ASSIST_KEY = "android:assist_structure";
final ComponentName mActivityComponent;
final ArrayList<ViewNodeImpl> mRootViews = new ArrayList<>();
- ViewAssistDataImpl mTmpViewAssistDataImpl = new ViewAssistDataImpl();
+ ViewAssistStructureImpl mTmpViewAssistStructureImpl = new ViewAssistStructureImpl();
Bundle mTmpExtras = new Bundle();
- final static class ViewAssistDataImpl extends ViewAssistData {
+ final static class ViewAssistStructureImpl extends ViewAssistStructure {
CharSequence mText;
int mTextSelectionStart = -1;
int mTextSelectionEnd = -1;
+ int mTextColor = ViewNode.TEXT_COLOR_UNDEFINED;
+ int mTextBackgroundColor = ViewNode.TEXT_COLOR_UNDEFINED;
+ float mTextSize = 0;
+ int mTextStyle = 0;
CharSequence mHint;
@Override
@@ -72,6 +82,33 @@ final public class AssistData implements Parcelable {
}
@Override
+ public void setTextPaint(TextPaint paint) {
+ mTextColor = paint.getColor();
+ mTextBackgroundColor = paint.bgColor;
+ mTextSize = paint.getTextSize();
+ mTextStyle = 0;
+ Typeface tf = paint.getTypeface();
+ if (tf != null) {
+ if (tf.isBold()) {
+ mTextStyle |= ViewNode.TEXT_STYLE_BOLD;
+ }
+ if (tf.isItalic()) {
+ mTextStyle |= ViewNode.TEXT_STYLE_ITALIC;
+ }
+ }
+ int pflags = paint.getFlags();
+ if ((pflags& Paint.FAKE_BOLD_TEXT_FLAG) != 0) {
+ mTextStyle |= ViewNode.TEXT_STYLE_BOLD;
+ }
+ if ((pflags& Paint.UNDERLINE_TEXT_FLAG) != 0) {
+ mTextStyle |= ViewNode.TEXT_STYLE_UNDERLINE;
+ }
+ if ((pflags& Paint.STRIKE_THRU_TEXT_FLAG) != 0) {
+ mTextStyle |= ViewNode.TEXT_STYLE_STRIKE_THRU;
+ }
+ }
+
+ @Override
public void setHint(CharSequence hint) {
mHint = hint;
}
@@ -98,29 +135,45 @@ final public class AssistData implements Parcelable {
}
final static class ViewNodeTextImpl {
- final String mText;
+ final CharSequence mText;
final int mTextSelectionStart;
final int mTextSelectionEnd;
+ int mTextColor;
+ int mTextBackgroundColor;
+ float mTextSize;
+ int mTextStyle;
final String mHint;
- ViewNodeTextImpl(ViewAssistDataImpl data) {
- mText = data.mText != null ? data.mText.toString() : null;
+ ViewNodeTextImpl(ViewAssistStructureImpl data) {
+ mText = data.mText;
mTextSelectionStart = data.mTextSelectionStart;
mTextSelectionEnd = data.mTextSelectionEnd;
+ mTextColor = data.mTextColor;
+ mTextBackgroundColor = data.mTextBackgroundColor;
+ mTextSize = data.mTextSize;
+ mTextStyle = data.mTextStyle;
mHint = data.mHint != null ? data.mHint.toString() : null;
}
ViewNodeTextImpl(Parcel in) {
- mText = in.readString();
+ mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mTextSelectionStart = in.readInt();
mTextSelectionEnd = in.readInt();
+ mTextColor = in.readInt();
+ mTextBackgroundColor = in.readInt();
+ mTextSize = in.readFloat();
+ mTextStyle = in.readInt();
mHint = in.readString();
}
void writeToParcel(Parcel out) {
- out.writeString(mText);
+ TextUtils.writeToParcel(mText, out, 0);
out.writeInt(mTextSelectionStart);
out.writeInt(mTextSelectionEnd);
+ out.writeInt(mTextColor);
+ out.writeInt(mTextBackgroundColor);
+ out.writeFloat(mTextSize);
+ out.writeInt(mTextStyle);
out.writeString(mHint);
}
}
@@ -155,7 +208,7 @@ final public class AssistData implements Parcelable {
final ViewNodeImpl[] mChildren;
- ViewNodeImpl(AssistData assistData, View view, int left, int top,
+ ViewNodeImpl(AssistStructure assistStructure, View view, int left, int top,
CharSequence contentDescription) {
mX = left;
mY = top;
@@ -197,18 +250,18 @@ final public class AssistData implements Parcelable {
mFlags = flags;
mClassName = view.getAccessibilityClassName().toString();
mContentDescription = contentDescription != null ? contentDescription.toString() : null;
- final ViewAssistDataImpl viewData = assistData.mTmpViewAssistDataImpl;
- final Bundle extras = assistData.mTmpExtras;
- view.onProvideAssistData(viewData, extras);
+ final ViewAssistStructureImpl viewData = assistStructure.mTmpViewAssistStructureImpl;
+ final Bundle extras = assistStructure.mTmpExtras;
+ view.onProvideAssistStructure(viewData, extras);
if (viewData.mText != null || viewData.mHint != null) {
mText = new ViewNodeTextImpl(viewData);
- assistData.mTmpViewAssistDataImpl = new ViewAssistDataImpl();
+ assistStructure.mTmpViewAssistStructureImpl = new ViewAssistStructureImpl();
} else {
mText = null;
}
if (!extras.isEmpty()) {
mExtras = extras;
- assistData.mTmpExtras = new Bundle();
+ assistStructure.mTmpExtras = new Bundle();
} else {
mExtras = null;
}
@@ -218,7 +271,7 @@ final public class AssistData implements Parcelable {
if (NCHILDREN > 0) {
mChildren = new ViewNodeImpl[NCHILDREN];
for (int i=0; i<NCHILDREN; i++) {
- mChildren[i] = new ViewNodeImpl(assistData, vg.getChildAt(i));
+ mChildren[i] = new ViewNodeImpl(assistStructure, vg.getChildAt(i));
}
} else {
mChildren = null;
@@ -228,11 +281,11 @@ final public class AssistData implements Parcelable {
}
}
- ViewNodeImpl(AssistData assistData, View view) {
- this(assistData, view, view.getLeft(), view.getTop(), view.getContentDescription());
+ ViewNodeImpl(AssistStructure assistStructure, View view) {
+ this(assistStructure, view, view.getLeft(), view.getTop(), view.getContentDescription());
}
- ViewNodeImpl(Parcel in) {
+ ViewNodeImpl(Parcel in, PooledStringReader preader) {
mX = in.readInt();
mY = in.readInt();
mScrollX = in.readInt();
@@ -240,7 +293,7 @@ final public class AssistData implements Parcelable {
mWidth = in.readInt();
mHeight = in.readInt();
mFlags = in.readInt();
- mClassName = in.readString();
+ mClassName = preader.readString();
mContentDescription = in.readString();
if (in.readInt() != 0) {
mText = new ViewNodeTextImpl(in);
@@ -252,14 +305,14 @@ final public class AssistData implements Parcelable {
if (NCHILDREN > 0) {
mChildren = new ViewNodeImpl[NCHILDREN];
for (int i=0; i<NCHILDREN; i++) {
- mChildren[i] = new ViewNodeImpl(in);
+ mChildren[i] = new ViewNodeImpl(in, preader);
}
} else {
mChildren = null;
}
}
- void writeToParcel(Parcel out) {
+ void writeToParcel(Parcel out, PooledStringWriter pwriter) {
out.writeInt(mX);
out.writeInt(mY);
out.writeInt(mScrollX);
@@ -267,7 +320,7 @@ final public class AssistData implements Parcelable {
out.writeInt(mWidth);
out.writeInt(mHeight);
out.writeInt(mFlags);
- out.writeString(mClassName);
+ pwriter.writeString(mClassName);
out.writeString(mContentDescription);
if (mText != null) {
out.writeInt(1);
@@ -280,7 +333,7 @@ final public class AssistData implements Parcelable {
final int NCHILDREN = mChildren.length;
out.writeInt(NCHILDREN);
for (int i=0; i<NCHILDREN; i++) {
- mChildren[i].writeToParcel(out);
+ mChildren[i].writeToParcel(out, pwriter);
}
} else {
out.writeInt(0);
@@ -292,6 +345,17 @@ final public class AssistData implements Parcelable {
* Provides access to information about a single view in the assist data.
*/
static public class ViewNode {
+ /**
+ * Magic value for text color that has not been defined, which is very unlikely
+ * to be confused with a real text color.
+ */
+ public static final int TEXT_COLOR_UNDEFINED = 1;
+
+ public static final int TEXT_STYLE_BOLD = 1<<0;
+ public static final int TEXT_STYLE_ITALIC = 1<<1;
+ public static final int TEXT_STYLE_UNDERLINE = 1<<2;
+ public static final int TEXT_STYLE_STRIKE_THRU = 1<<3;
+
ViewNodeImpl mImpl;
public ViewNode() {
@@ -373,7 +437,7 @@ final public class AssistData implements Parcelable {
return mImpl.mContentDescription;
}
- public String getText() {
+ public CharSequence getText() {
return mImpl.mText != null ? mImpl.mText.mText : null;
}
@@ -385,6 +449,22 @@ final public class AssistData implements Parcelable {
return mImpl.mText != null ? mImpl.mText.mTextSelectionEnd : -1;
}
+ public int getTextColor() {
+ return mImpl.mText != null ? mImpl.mText.mTextColor : TEXT_COLOR_UNDEFINED;
+ }
+
+ public int getTextBackgroundColor() {
+ return mImpl.mText != null ? mImpl.mText.mTextBackgroundColor : TEXT_COLOR_UNDEFINED;
+ }
+
+ public float getTextSize() {
+ return mImpl.mText != null ? mImpl.mText.mTextSize : 0;
+ }
+
+ public int getTextStyle() {
+ return mImpl.mText != null ? mImpl.mText.mTextStyle : 0;
+ }
+
public String getHint() {
return mImpl.mText != null ? mImpl.mText.mHint : null;
}
@@ -402,7 +482,7 @@ final public class AssistData implements Parcelable {
}
}
- AssistData(Activity activity) {
+ AssistStructure(Activity activity) {
mActivityComponent = activity.getComponentName();
ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews(
activity.getActivityToken());
@@ -417,11 +497,12 @@ final public class AssistData implements Parcelable {
}
}
- AssistData(Parcel in) {
+ AssistStructure(Parcel in) {
+ PooledStringReader preader = new PooledStringReader(in);
mActivityComponent = ComponentName.readFromParcel(in);
final int N = in.readInt();
for (int i=0; i<N; i++) {
- mRootViews.add(new ViewNodeImpl(in));
+ mRootViews.add(new ViewNodeImpl(in, preader));
}
//dump();
}
@@ -450,10 +531,14 @@ final public class AssistData implements Parcelable {
if (contentDescription != null) {
Log.i(TAG, prefix + " Content description: " + contentDescription);
}
- String text = node.getText();
+ CharSequence text = node.getText();
if (text != null) {
Log.i(TAG, prefix + " Text (sel " + node.getTextSelectionStart() + "-"
+ node.getTextSelectionEnd() + "): " + text);
+ Log.i(TAG, prefix + " Text size: " + node.getTextSize() + " , style: #"
+ + node.getTextStyle());
+ Log.i(TAG, prefix + " Text color fg: #" + Integer.toHexString(node.getTextColor())
+ + ", bg: #" + Integer.toHexString(node.getTextBackgroundColor()));
}
String hint = node.getHint();
if (hint != null) {
@@ -476,10 +561,10 @@ final public class AssistData implements Parcelable {
}
/**
- * Retrieve the framework-generated AssistData that is stored within
+ * Retrieve the framework-generated AssistStructure that is stored within
* the Bundle filled in by {@link Activity#onProvideAssistData}.
*/
- public static AssistData getAssistData(Bundle assistBundle) {
+ public static AssistStructure getAssistStructure(Bundle assistBundle) {
return assistBundle.getParcelable(ASSIST_KEY);
}
@@ -509,23 +594,25 @@ final public class AssistData implements Parcelable {
public void writeToParcel(Parcel out, int flags) {
int start = out.dataPosition();
+ PooledStringWriter pwriter = new PooledStringWriter(out);
ComponentName.writeToParcel(mActivityComponent, out);
final int N = mRootViews.size();
out.writeInt(N);
for (int i=0; i<N; i++) {
- mRootViews.get(i).writeToParcel(out);
+ mRootViews.get(i).writeToParcel(out, pwriter);
}
+ pwriter.finish();
Log.i(TAG, "Flattened assist data: " + (out.dataPosition() - start) + " bytes");
}
- public static final Parcelable.Creator<AssistData> CREATOR
- = new Parcelable.Creator<AssistData>() {
- public AssistData createFromParcel(Parcel in) {
- return new AssistData(in);
+ public static final Parcelable.Creator<AssistStructure> CREATOR
+ = new Parcelable.Creator<AssistStructure>() {
+ public AssistStructure createFromParcel(Parcel in) {
+ return new AssistStructure(in);
}
- public AssistData[] newArray(int size) {
- return new AssistData[size];
+ public AssistStructure[] newArray(int size) {
+ return new AssistStructure[size];
}
};
}
diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl
index 03e7ff4..6d27910 100644
--- a/core/java/android/app/ISearchManager.aidl
+++ b/core/java/android/app/ISearchManager.aidl
@@ -31,5 +31,5 @@ interface ISearchManager {
ComponentName getGlobalSearchActivity();
ComponentName getWebSearchActivity();
ComponentName getAssistIntent(int userHandle);
- boolean launchAssistAction(int requestType, String hint, int userHandle);
+ boolean launchAssistAction(String hint, int userHandle);
}
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index d7c4467..fa27631 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -969,7 +969,7 @@ public class SearchManager
intent.setComponent(comp);
if (inclContext) {
IActivityManager am = ActivityManagerNative.getDefault();
- Bundle extras = am.getAssistContextExtras(0);
+ Bundle extras = am.getAssistContextExtras(ActivityManager.ASSIST_CONTEXT_BASIC);
if (extras != null) {
intent.replaceExtras(extras);
}
@@ -985,12 +985,12 @@ public class SearchManager
* Launch an assist action for the current top activity.
* @hide
*/
- public boolean launchAssistAction(int requestType, String hint, int userHandle) {
+ public boolean launchAssistAction(String hint, int userHandle) {
try {
if (mService == null) {
return false;
}
- return mService.launchAssistAction(requestType, hint, userHandle);
+ return mService.launchAssistAction(hint, userHandle);
} catch (RemoteException re) {
Log.e(TAG, "launchAssistAction() failed: " + re);
return false;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 3222b2b..2ed8c44 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1239,6 +1239,13 @@ public class Intent implements Parcelable, Cloneable {
= "android.intent.extra.ASSIST_PACKAGE";
/**
+ * An optional field on {@link #ACTION_ASSIST} containing the uid of the current foreground
+ * application package at the time the assist was invoked.
+ */
+ public static final String EXTRA_ASSIST_UID
+ = "android.intent.extra.ASSIST_UID";
+
+ /**
* An optional field on {@link #ACTION_ASSIST} and containing additional contextual
* information supplied by the current foreground app at the time of the assist request.
* This is a {@link Bundle} of additional data.
@@ -5386,6 +5393,16 @@ public class Intent implements Parcelable, Cloneable {
}
/**
+ * Filter extras to only basic types.
+ * @hide
+ */
+ public void removeUnsafeExtras() {
+ if (mExtras != null) {
+ mExtras.filterValues();
+ }
+ }
+
+ /**
* Retrieve any special flags associated with this intent. You will
* normally just set them with {@link #setFlags} and let the system
* take the appropriate action with them.
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<String, Object> map) {
+ private PersistableBundle(ArrayMap<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) {
+ final int N = mMap.size();
+ for (int i=0; i<N; i++) {
+ Object value = mMap.valueAt(i);
+ if (value instanceof ArrayMap) {
// 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) &&
- !(value instanceof Boolean) && !(value instanceof boolean[])) {
- throw new IllegalArgumentException("Bad value in PersistableBundle key=" + key +
- " value=" + value);
+ mMap.setValueAt(i, new PersistableBundle((ArrayMap<String, Object>) 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<String, Object>)
- XmlUtils.readThisMapXml(in, startTag, tagName, new MyReadMapCallback()));
+ return new PersistableBundle((ArrayMap<String, Object>)
+ 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<String, Integer> 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);
+ }
+}
diff --git a/core/java/android/view/PhoneWindow.java b/core/java/android/view/PhoneWindow.java
index d4b14f6..cf5affc 100644
--- a/core/java/android/view/PhoneWindow.java
+++ b/core/java/android/view/PhoneWindow.java
@@ -4158,7 +4158,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
& Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
// On TVs, if the app doesn't implement search, we want to launch assist.
return ((SearchManager)getContext().getSystemService(Context.SEARCH_SERVICE))
- .launchAssistAction(0, null, UserHandle.myUserId());
+ .launchAssistAction(null, UserHandle.myUserId());
}
return result;
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 4f2d4a6..69eb7b4 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5620,12 +5620,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * Called when assist data is being retrieved from a view as part of
+ * Called when assist structure is being retrieved from a view as part of
* {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
- * @param data
- * @param extras
+ * @param structure Additional standard structured view structure to supply.
+ * @param extras Non-standard extensions.
*/
- public void onProvideAssistData(ViewAssistData data, Bundle extras) {
+ public void onProvideAssistStructure(ViewAssistStructure structure, Bundle extras) {
}
/**
diff --git a/core/java/android/view/ViewAssistData.java b/core/java/android/view/ViewAssistStructure.java
index 74436ea..5132bb9 100644
--- a/core/java/android/view/ViewAssistData.java
+++ b/core/java/android/view/ViewAssistStructure.java
@@ -16,13 +16,16 @@
package android.view;
+import android.text.TextPaint;
+
/**
- * Container for storing data generated by {@link View#onProvideAssistData
- * View.onProvideAssistData}.
+ * Container for storing additional per-view data generated by {@link View#onProvideAssistStructure
+ * View.onProvideAssistStructure}.
*/
-public abstract class ViewAssistData {
+public abstract class ViewAssistStructure {
public abstract void setText(CharSequence text);
public abstract void setText(CharSequence text, int selectionStart, int selectionEnd);
+ public abstract void setTextPaint(TextPaint paint);
public abstract void setHint(CharSequence hint);
public abstract CharSequence getText();
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index ce1834e..bb290e7 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -46,7 +46,7 @@ import android.view.Gravity;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import android.view.VelocityTracker;
-import android.view.ViewAssistData;
+import android.view.ViewAssistStructure;
import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -1363,18 +1363,19 @@ public class Switch extends CompoundButton {
}
@Override
- public void onProvideAssistData(ViewAssistData data, Bundle extras) {
- super.onProvideAssistData(data, extras);
+ public void onProvideAssistStructure(ViewAssistStructure structure, Bundle extras) {
+ super.onProvideAssistStructure(structure, extras);
CharSequence switchText = isChecked() ? mTextOn : mTextOff;
if (!TextUtils.isEmpty(switchText)) {
- CharSequence oldText = data.getText();
+ CharSequence oldText = structure.getText();
if (TextUtils.isEmpty(oldText)) {
- data.setText(switchText);
+ structure.setText(switchText);
} else {
StringBuilder newText = new StringBuilder();
newText.append(oldText).append(' ').append(switchText);
- data.setText(newText);
+ structure.setText(newText);
}
+ structure.setTextPaint(mTextPaint);
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 628833d..447e9ac 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -115,7 +115,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewAssistData;
+import android.view.ViewAssistStructure;
import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.view.ViewGroup.LayoutParams;
@@ -8580,13 +8580,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
@Override
- public void onProvideAssistData(ViewAssistData data, Bundle extras) {
- super.onProvideAssistData(data, extras);
+ public void onProvideAssistStructure(ViewAssistStructure structure, Bundle extras) {
+ super.onProvideAssistStructure(structure, extras);
final boolean isPassword = hasPasswordTransformationMethod();
if (!isPassword) {
- data.setText(getText(), getSelectionStart(), getSelectionEnd());
+ structure.setText(getText(), getSelectionStart(), getSelectionEnd());
+ structure.setTextPaint(mTextPaint);
}
- data.setHint(getHint());
+ structure.setHint(getHint());
}
/** @hide */
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index 2bd607c..0350d61 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -20,6 +20,7 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.CompressFormat;
import android.net.Uri;
+import android.util.ArrayMap;
import android.util.Base64;
import android.util.Xml;
@@ -822,7 +823,36 @@ public class XmlUtils {
int eventType = parser.getEventType();
do {
if (eventType == parser.START_TAG) {
- Object val = readThisValueXml(parser, name, callback);
+ Object val = readThisValueXml(parser, name, callback, false);
+ map.put(name[0], val);
+ } else if (eventType == parser.END_TAG) {
+ if (parser.getName().equals(endTag)) {
+ return map;
+ }
+ 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");
+ }
+
+ /**
+ * Like {@link #readThisMapXml}, but returns an ArrayMap instead of HashMap.
+ * @hide
+ */
+ public static final ArrayMap<String, ?> readThisArrayMapXml(XmlPullParser parser, String endTag,
+ String[] name, ReadMapCallback callback)
+ throws XmlPullParserException, java.io.IOException
+ {
+ ArrayMap<String, Object> map = new ArrayMap<>();
+
+ int eventType = parser.getEventType();
+ do {
+ if (eventType == parser.START_TAG) {
+ Object val = readThisValueXml(parser, name, callback, true);
map.put(name[0], val);
} else if (eventType == parser.END_TAG) {
if (parser.getName().equals(endTag)) {
@@ -854,7 +884,7 @@ public class XmlUtils {
*/
public static final ArrayList readThisListXml(XmlPullParser parser, String endTag,
String[] name) throws XmlPullParserException, java.io.IOException {
- return readThisListXml(parser, endTag, name, null);
+ return readThisListXml(parser, endTag, name, null, false);
}
/**
@@ -872,14 +902,14 @@ public class XmlUtils {
* @see #readListXml
*/
private static final ArrayList readThisListXml(XmlPullParser parser, String endTag,
- String[] name, ReadMapCallback callback)
+ String[] name, ReadMapCallback callback, boolean arrayMap)
throws XmlPullParserException, java.io.IOException {
ArrayList list = new ArrayList();
int eventType = parser.getEventType();
do {
if (eventType == parser.START_TAG) {
- Object val = readThisValueXml(parser, name, callback);
+ Object val = readThisValueXml(parser, name, callback, arrayMap);
list.add(val);
//System.out.println("Adding to list: " + val);
} else if (eventType == parser.END_TAG) {
@@ -915,7 +945,7 @@ public class XmlUtils {
*/
public static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name)
throws XmlPullParserException, java.io.IOException {
- return readThisSetXml(parser, endTag, name, null);
+ return readThisSetXml(parser, endTag, name, null, false);
}
/**
@@ -937,13 +967,14 @@ public class XmlUtils {
* @hide
*/
private static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name,
- ReadMapCallback callback) throws XmlPullParserException, java.io.IOException {
+ ReadMapCallback callback, boolean arrayMap)
+ throws XmlPullParserException, java.io.IOException {
HashSet set = new HashSet();
int eventType = parser.getEventType();
do {
if (eventType == parser.START_TAG) {
- Object val = readThisValueXml(parser, name, callback);
+ Object val = readThisValueXml(parser, name, callback, arrayMap);
set.add(val);
//System.out.println("Adding to set: " + val);
} else if (eventType == parser.END_TAG) {
@@ -1292,7 +1323,7 @@ public class XmlUtils {
int eventType = parser.getEventType();
do {
if (eventType == parser.START_TAG) {
- return readThisValueXml(parser, name, null);
+ return readThisValueXml(parser, name, null, false);
} else if (eventType == parser.END_TAG) {
throw new XmlPullParserException(
"Unexpected end tag at: " + parser.getName());
@@ -1308,7 +1339,8 @@ public class XmlUtils {
}
private static final Object readThisValueXml(XmlPullParser parser, String[] name,
- ReadMapCallback callback) throws XmlPullParserException, java.io.IOException {
+ ReadMapCallback callback, boolean arrayMap)
+ throws XmlPullParserException, java.io.IOException {
final String valueName = parser.getAttributeValue(null, "name");
final String tagName = parser.getName();
@@ -1368,19 +1400,21 @@ public class XmlUtils {
return res;
} else if (tagName.equals("map")) {
parser.next();
- res = readThisMapXml(parser, "map", name);
+ res = arrayMap
+ ? readThisArrayMapXml(parser, "map", name, callback)
+ : readThisMapXml(parser, "map", name, callback);
name[0] = valueName;
//System.out.println("Returning value for " + valueName + ": " + res);
return res;
} else if (tagName.equals("list")) {
parser.next();
- res = readThisListXml(parser, "list", name);
+ res = readThisListXml(parser, "list", name, callback, arrayMap);
name[0] = valueName;
//System.out.println("Returning value for " + valueName + ": " + res);
return res;
} else if (tagName.equals("set")) {
parser.next();
- res = readThisSetXml(parser, "set", name);
+ res = readThisSetXml(parser, "set", name, callback, arrayMap);
name[0] = valueName;
//System.out.println("Returning value for " + valueName + ": " + res);
return res;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c4122e8..b5ea214 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -10149,16 +10149,13 @@ public final class ActivityManagerService extends ActivityManagerNative
private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint,
IResultReceiver receiver, int userHandle) {
enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
- "getAssistContextExtras()");
- PendingAssistExtras pae;
- Bundle extras = new Bundle();
+ "enqueueAssistContext()");
synchronized (this) {
- ActivityRecord activity = getFocusedStack().mResumedActivity;
+ ActivityRecord activity = getFocusedStack().topActivity();
if (activity == null) {
- Slog.w(TAG, "getAssistContextExtras failed: no resumed activity");
+ Slog.w(TAG, "getAssistContextExtras failed: no top activity");
return null;
}
- extras.putString(Intent.EXTRA_ASSIST_PACKAGE, activity.packageName);
if (activity.app == null || activity.app.thread == null) {
Slog.w(TAG, "getAssistContextExtras failed: no process for " + activity);
return null;
@@ -10167,6 +10164,10 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.w(TAG, "getAssistContextExtras failed: request process same as " + activity);
return null;
}
+ PendingAssistExtras pae;
+ Bundle extras = new Bundle();
+ extras.putString(Intent.EXTRA_ASSIST_PACKAGE, activity.packageName);
+ extras.putInt(Intent.EXTRA_ASSIST_UID, activity.app.uid);
pae = new PendingAssistExtras(activity, extras, intent, hint, receiver, userHandle);
try {
activity.app.thread.requestAssistContextExtras(activity.appToken, pae,
diff --git a/services/core/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java
index 663efe5..2b2b2ac 100644
--- a/services/core/java/com/android/server/search/SearchManagerService.java
+++ b/services/core/java/com/android/server/search/SearchManagerService.java
@@ -264,7 +264,7 @@ public class SearchManagerService extends ISearchManager.Stub {
}
@Override
- public boolean launchAssistAction(int requestType, String hint, int userHandle) {
+ public boolean launchAssistAction(String hint, int userHandle) {
ComponentName comp = getAssistIntent(userHandle);
if (comp == null) {
return false;
@@ -274,7 +274,8 @@ public class SearchManagerService extends ISearchManager.Stub {
Intent intent = new Intent(Intent.ACTION_ASSIST);
intent.setComponent(comp);
IActivityManager am = ActivityManagerNative.getDefault();
- return am.launchAssistIntent(intent, requestType, hint, userHandle);
+ return am.launchAssistIntent(intent, ActivityManager.ASSIST_CONTEXT_BASIC, hint,
+ userHandle);
} catch (RemoteException e) {
} finally {
Binder.restoreCallingIdentity(ident);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index e2b47c3..30d97b9 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -16,12 +16,17 @@
package com.android.server.voiceinteraction;
+import android.app.ActivityManager;
import android.app.ActivityManagerNative;
+import android.app.AssistContent;
import android.app.IActivityManager;
+import android.content.ClipData;
import android.content.ComponentName;
+import android.content.ContentProvider;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -53,6 +58,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
final int mCallingUid;
final IActivityManager mAm;
final IWindowManager mIWindowManager;
+ final IBinder mPermissionOwner;
boolean mShown;
Bundle mShowArgs;
int mShowFlags;
@@ -83,15 +89,9 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
public void send(int resultCode, Bundle resultData) throws RemoteException {
synchronized (mLock) {
if (mShown) {
- if (mSession != null) {
- try {
- mSession.handleAssist(resultData);
- } catch (RemoteException e) {
- }
- } else {
- mHaveAssistData = true;
- mAssistData = resultData;
- }
+ mHaveAssistData = true;
+ mAssistData = resultData;
+ deliverAssistData();
}
}
}
@@ -109,6 +109,14 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
mAm = ActivityManagerNative.getDefault();
mIWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService(Context.WINDOW_SERVICE));
+ IBinder permOwner = null;
+ try {
+ permOwner = mAm.newUriPermissionOwner("voicesession:"
+ + component.flattenToShortString());
+ } catch (RemoteException e) {
+ Slog.w("voicesession", "AM dead", e);
+ }
+ mPermissionOwner = permOwner;
mBindIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
mBindIntent.setComponent(mSessionComponentName);
mBound = mContext.bindServiceAsUser(mBindIntent, this,
@@ -138,7 +146,8 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
mShowFlags = flags;
if ((flags&VoiceInteractionService.START_WITH_ASSIST) != 0) {
try {
- mAm.requestAssistContextExtras(0, mAssistReceiver);
+ mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
+ mAssistReceiver);
} catch (RemoteException e) {
}
} else {
@@ -152,20 +161,91 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
mShowFlags = 0;
} catch (RemoteException e) {
}
- if (mHaveAssistData) {
- try {
- mSession.handleAssist(mAssistData);
- mAssistData = null;
- mHaveAssistData = false;
- } catch (RemoteException e) {
- }
- }
+ deliverAssistData();
}
return true;
}
return false;
}
+ void grantUriPermission(Uri uri, int mode, int srcUid, int destUid, String destPkg) {
+ if (!"content".equals(uri.getScheme())) {
+ return;
+ }
+ long ident = Binder.clearCallingIdentity();
+ try {
+ // This will throw SecurityException for us.
+ mAm.checkGrantUriPermission(srcUid, null, ContentProvider.getUriWithoutUserId(uri),
+ mode, ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(srcUid)));
+ // No security exception, do the grant.
+ int sourceUserId = ContentProvider.getUserIdFromUri(uri, mUser);
+ uri = ContentProvider.getUriWithoutUserId(uri);
+ mAm.grantUriPermissionFromOwner(mPermissionOwner, srcUid, destPkg,
+ uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, sourceUserId, mUser);
+ } catch (RemoteException e) {
+ } catch (SecurityException e) {
+ Slog.w(TAG, "Can't propagate permission", e);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+
+ }
+
+ void grantClipDataItemPermission(ClipData.Item item, int mode, int srcUid, int destUid,
+ String destPkg) {
+ if (item.getUri() != null) {
+ grantUriPermission(item.getUri(), mode, srcUid, destUid, destPkg);
+ }
+ Intent intent = item.getIntent();
+ if (intent != null && intent.getData() != null) {
+ grantUriPermission(intent.getData(), mode, srcUid, destUid, destPkg);
+ }
+ }
+
+ void grantClipDataPermissions(ClipData data, int mode, int srcUid, int destUid,
+ String destPkg) {
+ final int N = data.getItemCount();
+ for (int i=0; i<N; i++) {
+ grantClipDataItemPermission(data.getItemAt(i), mode, srcUid, destUid, destPkg);
+ }
+ }
+
+ void deliverAssistData() {
+ if (mSession == null || !mHaveAssistData) {
+ return;
+ }
+ if (mAssistData != null) {
+ int uid = mAssistData.getInt(Intent.EXTRA_ASSIST_UID, -1);
+ if (uid >= 0) {
+ Bundle assistContext = mAssistData.getBundle(Intent.EXTRA_ASSIST_CONTEXT);
+ if (assistContext != null) {
+ AssistContent content = AssistContent.getAssistContent(assistContext);
+ if (content != null) {
+ Intent intent = content.getIntent();
+ if (intent != null) {
+ ClipData data = intent.getClipData();
+ if (data != null && Intent.isAccessUriMode(intent.getFlags())) {
+ grantClipDataPermissions(data, intent.getFlags(), uid,
+ mCallingUid, mSessionComponentName.getPackageName());
+ }
+ }
+ ClipData data = content.getClipData();
+ if (data != null) {
+ grantClipDataPermissions(data, Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ uid, mCallingUid, mSessionComponentName.getPackageName());
+ }
+ }
+ }
+ }
+ }
+ try {
+ mSession.handleAssist(mAssistData);
+ mAssistData = null;
+ mHaveAssistData = false;
+ } catch (RemoteException e) {
+ }
+ }
+
public boolean hideLocked() {
if (mBound) {
if (mShown) {
@@ -180,6 +260,13 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
} catch (RemoteException e) {
}
}
+ try {
+ mAm.revokeUriPermissionFromOwner(mPermissionOwner, null,
+ Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
+ mUser);
+ } catch (RemoteException e) {
+ }
}
if (mFullyBound) {
mContext.unbindService(mFullConnection);
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistProxyActivity.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistProxyActivity.java
index 6a99351..d0c5e36 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistProxyActivity.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistProxyActivity.java
@@ -28,7 +28,6 @@ public class AssistProxyActivity extends Activity {
finish();
Intent intent = new Intent(this, MainInteractionService.class);
intent.setAction(Intent.ACTION_ASSIST);
- intent.putExtras(getIntent());
startService(intent);
}
}
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
index d35bc5c..bae19a6 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
@@ -17,7 +17,7 @@
package com.android.test.voiceinteraction;
import android.annotation.Nullable;
-import android.app.AssistData;
+import android.app.AssistStructure;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
@@ -31,7 +31,7 @@ import java.util.ArrayList;
public class AssistVisualizer extends View {
static final String TAG = "AssistVisualizer";
- AssistData mAssistData;
+ AssistStructure mAssistStructure;
final Paint mFramePaint = new Paint();
final ArrayList<Rect> mTextRects = new ArrayList<>();
final int[] mTmpLocation = new int[2];
@@ -44,25 +44,25 @@ public class AssistVisualizer extends View {
mFramePaint.setStrokeWidth(0);
}
- public void setAssistData(AssistData ad) {
- mAssistData = ad;
+ public void setAssistStructure(AssistStructure as) {
+ mAssistStructure = as;
mTextRects.clear();
- final int N = ad.getWindowCount();
+ final int N = as.getWindowCount();
if (N > 0) {
- AssistData.ViewNode window = new AssistData.ViewNode();
+ AssistStructure.ViewNode window = new AssistStructure.ViewNode();
for (int i=0; i<N; i++) {
- ad.getWindowAt(i, window);
+ as.getWindowAt(i, window);
buildTextRects(window, 0, 0);
}
}
}
public void clearAssistData() {
- mAssistData = null;
+ mAssistStructure = null;
mTextRects.clear();
}
- void buildTextRects(AssistData.ViewNode root, int parentLeft, int parentTop) {
+ void buildTextRects(AssistStructure.ViewNode root, int parentLeft, int parentTop) {
if (root.getVisibility() != View.VISIBLE) {
return;
}
@@ -78,7 +78,7 @@ public class AssistVisualizer extends View {
if (N > 0) {
left -= root.getScrollX();
top -= root.getScrollY();
- AssistData.ViewNode child = new AssistData.ViewNode();
+ AssistStructure.ViewNode child = new AssistStructure.ViewNode();
for (int i=0; i<N; i++) {
root.getChildAt(i, child);
buildTextRects(child, left, top);
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
index 2cab3ea..722b0de 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
@@ -79,12 +79,7 @@ public class MainInteractionService extends VoiceInteractionService {
Bundle args = new Bundle();
args.putParcelable("intent", new Intent(this, TestInteractionActivity.class));
args.putBundle("assist", intent.getExtras());
- Bundle assistContext = intent.getBundleExtra(Intent.EXTRA_ASSIST_CONTEXT);
- int startFlags = 0;
- if (assistContext == null) {
- startFlags |= START_WITH_ASSIST;
- }
- startSession(args, startFlags);
+ startSession(args, START_WITH_ASSIST);
} else {
Log.w(TAG, "Not starting -- not current voice interaction service");
}
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
index 1e30aff..bcfc6f4 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
@@ -16,7 +16,8 @@
package com.android.test.voiceinteraction;
-import android.app.AssistData;
+import android.app.AssistContent;
+import android.app.AssistStructure;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -41,7 +42,7 @@ public class MainInteractionSession extends VoiceInteractionSession
Button mCompleteButton;
Button mAbortButton;
- AssistData mAssistData;
+ AssistStructure mAssistStructure;
static final int STATE_IDLE = 0;
static final int STATE_LAUNCHING = 1;
@@ -68,8 +69,9 @@ public class MainInteractionSession extends VoiceInteractionSession
super.onShow(args, showFlags);
mState = STATE_IDLE;
mStartIntent = args.getParcelable("intent");
- Bundle assist = args.getBundle("assist");
- parseAssistData(assist);
+ if (mAssistVisualizer != null) {
+ mAssistVisualizer.clearAssistData();
+ }
updateState();
}
@@ -87,8 +89,8 @@ public class MainInteractionSession extends VoiceInteractionSession
public View onCreateContentView() {
mContentView = getLayoutInflater().inflate(R.layout.voice_interaction_session, null);
mAssistVisualizer = (AssistVisualizer)mContentView.findViewById(R.id.assist_visualizer);
- if (mAssistData != null) {
- mAssistVisualizer.setAssistData(mAssistData);
+ if (mAssistStructure != null) {
+ mAssistVisualizer.setAssistStructure(mAssistStructure);
}
mTopContent = mContentView.findViewById(R.id.top_content);
mBottomContent = mContentView.findViewById(R.id.bottom_content);
@@ -117,10 +119,17 @@ public class MainInteractionSession extends VoiceInteractionSession
if (assistBundle != null) {
Bundle assistContext = assistBundle.getBundle(Intent.EXTRA_ASSIST_CONTEXT);
if (assistContext != null) {
- mAssistData = AssistData.getAssistData(assistContext);
- mAssistData.dump();
- if (mAssistVisualizer != null) {
- mAssistVisualizer.setAssistData(mAssistData);
+ mAssistStructure = AssistStructure.getAssistStructure(assistContext);
+ if (mAssistStructure != null) {
+ mAssistStructure.dump();
+ if (mAssistVisualizer != null) {
+ mAssistVisualizer.setAssistStructure(mAssistStructure);
+ }
+ }
+ AssistContent content = AssistContent.getAssistContent(assistContext);
+ if (content != null) {
+ Log.i(TAG, "Assist intent: " + content.getIntent());
+ Log.i(TAG, "Assist clipdata: " + content.getClipData());
}
return;
}