summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;
}