diff options
-rw-r--r-- | api/current.txt | 146 | ||||
-rw-r--r-- | api/system-current.txt | 146 | ||||
-rw-r--r-- | core/java/android/app/AssistContent.java | 219 | ||||
-rw-r--r-- | core/java/android/app/AssistStructure.java | 1075 | ||||
-rw-r--r-- | core/java/android/app/VoiceInteractor.java | 3 | ||||
-rw-r--r-- | core/java/android/app/assist/AssistContent.java | 172 | ||||
-rw-r--r-- | core/java/android/app/assist/AssistStructure.java | 1024 | ||||
-rw-r--r-- | core/java/android/service/voice/VoiceInteractionSession.java | 13 | ||||
-rw-r--r-- | core/java/android/view/ViewStructure.java | 2 | ||||
-rw-r--r-- | core/java/android/widget/TextView.java | 2 | ||||
-rw-r--r-- | tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java | 2 | ||||
-rw-r--r-- | tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java | 41 | ||||
-rw-r--r-- | tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java | 126 |
13 files changed, 1405 insertions, 1566 deletions
diff --git a/api/current.txt b/api/current.txt index 1287c74..cd726a8 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4016,79 +4016,6 @@ package android.app { field public java.lang.String serviceDetails; } - public deprecated class AssistContent { - ctor public AssistContent(); - method public android.content.ClipData getClipData(); - method public android.os.Bundle getExtras(); - method public java.lang.String getStructuredData(); - method public android.net.Uri getWebUri(); - method public boolean isAppProvidedIntent(); - method public void setClipData(android.content.ClipData); - method public void setIntent(android.content.Intent); - method public void setStructuredData(java.lang.String); - method public void setWebUri(android.net.Uri); - } - - public deprecated class AssistStructure { - ctor public AssistStructure(); - method public android.content.ComponentName getActivityComponent(); - method public int getWindowNodeCount(); - } - - public static class AssistStructure.ViewNode { - method public android.app.AssistStructure.ViewNode getChildAt(int); - method public int getChildCount(); - method public java.lang.String getClassName(); - method public java.lang.CharSequence getContentDescription(); - method public android.os.Bundle getExtras(); - method public int getHeight(); - method public java.lang.String getHint(); - method public int getId(); - method public java.lang.String getIdEntry(); - method public java.lang.String getIdPackage(); - method public java.lang.String getIdType(); - method public int getLeft(); - method public int getScrollX(); - method public int getScrollY(); - 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(); - method public boolean isAccessibilityFocused(); - method public boolean isActivated(); - method public boolean isAssistBlocked(); - method public boolean isCheckable(); - method public boolean isChecked(); - method public boolean isClickable(); - method public boolean isContextClickable(); - method public boolean isEnabled(); - method public boolean isFocusable(); - 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 static class AssistStructure.WindowNode { - method public int getDisplayId(); - method public int getHeight(); - method public int getLeft(); - method public android.app.AssistStructure.ViewNode getRootViewNode(); - method public java.lang.CharSequence getTitle(); - method public int getTop(); - method public int getWidth(); - } - public class DatePickerDialog extends android.app.AlertDialog implements android.widget.DatePicker.OnDateChangedListener android.content.DialogInterface.OnClickListener { ctor public DatePickerDialog(android.content.Context, android.app.DatePickerDialog.OnDateSetListener, int, int, int); ctor public DatePickerDialog(android.content.Context, int, android.app.DatePickerDialog.OnDateSetListener, int, int, int); @@ -5900,22 +5827,87 @@ package android.app.admin { package android.app.assist { - public final class AssistContent extends android.app.AssistContent implements android.os.Parcelable { - ctor public AssistContent(android.os.Parcel); + public deprecated class AssistContent implements android.os.Parcelable { + ctor public AssistContent(); method public int describeContents(); + method public android.content.ClipData getClipData(); + method public android.os.Bundle getExtras(); method public android.content.Intent getIntent(); + method public java.lang.String getStructuredData(); + method public android.net.Uri getWebUri(); + method public boolean isAppProvidedIntent(); + method public void setClipData(android.content.ClipData); + method public void setIntent(android.content.Intent); + method public void setStructuredData(java.lang.String); + method public void setWebUri(android.net.Uri); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.assist.AssistContent> CREATOR; } - public final class AssistStructure extends android.app.AssistStructure implements android.os.Parcelable { + public class AssistStructure implements android.os.Parcelable { ctor public AssistStructure(); method public int describeContents(); - method public android.app.AssistStructure.WindowNode getWindowNodeAt(int); + method public android.content.ComponentName getActivityComponent(); + method public android.app.assist.AssistStructure.WindowNode getWindowNodeAt(int); + method public int getWindowNodeCount(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.assist.AssistStructure> CREATOR; } + public static class AssistStructure.ViewNode { + method public android.app.assist.AssistStructure.ViewNode getChildAt(int); + method public int getChildCount(); + method public java.lang.String getClassName(); + method public java.lang.CharSequence getContentDescription(); + method public android.os.Bundle getExtras(); + method public int getHeight(); + method public java.lang.String getHint(); + method public int getId(); + method public java.lang.String getIdEntry(); + method public java.lang.String getIdPackage(); + method public java.lang.String getIdType(); + method public int getLeft(); + method public int getScrollX(); + method public int getScrollY(); + 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(); + method public boolean isAccessibilityFocused(); + method public boolean isActivated(); + method public boolean isAssistBlocked(); + method public boolean isCheckable(); + method public boolean isChecked(); + method public boolean isClickable(); + method public boolean isContextClickable(); + method public boolean isEnabled(); + method public boolean isFocusable(); + 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 static class AssistStructure.WindowNode { + method public int getDisplayId(); + method public int getHeight(); + method public int getLeft(); + method public android.app.assist.AssistStructure.ViewNode getRootViewNode(); + method public java.lang.CharSequence getTitle(); + method public int getTop(); + method public int getWidth(); + } + } package android.app.backup { diff --git a/api/system-current.txt b/api/system-current.txt index 1f8f7a3..65f6ca5 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4112,79 +4112,6 @@ package android.app { field public java.lang.String serviceDetails; } - public deprecated class AssistContent { - ctor public AssistContent(); - method public android.content.ClipData getClipData(); - method public android.os.Bundle getExtras(); - method public java.lang.String getStructuredData(); - method public android.net.Uri getWebUri(); - method public boolean isAppProvidedIntent(); - method public void setClipData(android.content.ClipData); - method public void setIntent(android.content.Intent); - method public void setStructuredData(java.lang.String); - method public void setWebUri(android.net.Uri); - } - - public deprecated class AssistStructure { - ctor public AssistStructure(); - method public android.content.ComponentName getActivityComponent(); - method public int getWindowNodeCount(); - } - - public static class AssistStructure.ViewNode { - method public android.app.AssistStructure.ViewNode getChildAt(int); - method public int getChildCount(); - method public java.lang.String getClassName(); - method public java.lang.CharSequence getContentDescription(); - method public android.os.Bundle getExtras(); - method public int getHeight(); - method public java.lang.String getHint(); - method public int getId(); - method public java.lang.String getIdEntry(); - method public java.lang.String getIdPackage(); - method public java.lang.String getIdType(); - method public int getLeft(); - method public int getScrollX(); - method public int getScrollY(); - 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(); - method public boolean isAccessibilityFocused(); - method public boolean isActivated(); - method public boolean isAssistBlocked(); - method public boolean isCheckable(); - method public boolean isChecked(); - method public boolean isClickable(); - method public boolean isContextClickable(); - method public boolean isEnabled(); - method public boolean isFocusable(); - 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 static class AssistStructure.WindowNode { - method public int getDisplayId(); - method public int getHeight(); - method public int getLeft(); - method public android.app.AssistStructure.ViewNode getRootViewNode(); - method public java.lang.CharSequence getTitle(); - method public int getTop(); - method public int getWidth(); - } - public class BroadcastOptions { method public static android.app.BroadcastOptions makeBasic(); method public void setTemporaryAppWhitelistDuration(long); @@ -6018,22 +5945,87 @@ package android.app.admin { package android.app.assist { - public final class AssistContent extends android.app.AssistContent implements android.os.Parcelable { - ctor public AssistContent(android.os.Parcel); + public deprecated class AssistContent implements android.os.Parcelable { + ctor public AssistContent(); method public int describeContents(); + method public android.content.ClipData getClipData(); + method public android.os.Bundle getExtras(); method public android.content.Intent getIntent(); + method public java.lang.String getStructuredData(); + method public android.net.Uri getWebUri(); + method public boolean isAppProvidedIntent(); + method public void setClipData(android.content.ClipData); + method public void setIntent(android.content.Intent); + method public void setStructuredData(java.lang.String); + method public void setWebUri(android.net.Uri); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.assist.AssistContent> CREATOR; } - public final class AssistStructure extends android.app.AssistStructure implements android.os.Parcelable { + public class AssistStructure implements android.os.Parcelable { ctor public AssistStructure(); method public int describeContents(); - method public android.app.AssistStructure.WindowNode getWindowNodeAt(int); + method public android.content.ComponentName getActivityComponent(); + method public android.app.assist.AssistStructure.WindowNode getWindowNodeAt(int); + method public int getWindowNodeCount(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.assist.AssistStructure> CREATOR; } + public static class AssistStructure.ViewNode { + method public android.app.assist.AssistStructure.ViewNode getChildAt(int); + method public int getChildCount(); + method public java.lang.String getClassName(); + method public java.lang.CharSequence getContentDescription(); + method public android.os.Bundle getExtras(); + method public int getHeight(); + method public java.lang.String getHint(); + method public int getId(); + method public java.lang.String getIdEntry(); + method public java.lang.String getIdPackage(); + method public java.lang.String getIdType(); + method public int getLeft(); + method public int getScrollX(); + method public int getScrollY(); + 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(); + method public boolean isAccessibilityFocused(); + method public boolean isActivated(); + method public boolean isAssistBlocked(); + method public boolean isCheckable(); + method public boolean isChecked(); + method public boolean isClickable(); + method public boolean isContextClickable(); + method public boolean isEnabled(); + method public boolean isFocusable(); + 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 static class AssistStructure.WindowNode { + method public int getDisplayId(); + method public int getHeight(); + method public int getLeft(); + method public android.app.assist.AssistStructure.ViewNode getRootViewNode(); + method public java.lang.CharSequence getTitle(); + method public int getTop(); + method public int getWidth(); + } + } package android.app.backup { diff --git a/core/java/android/app/AssistContent.java b/core/java/android/app/AssistContent.java deleted file mode 100644 index ad2ba39..0000000 --- a/core/java/android/app/AssistContent.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * 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.net.Uri; -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 android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}. - * @deprecated use {@link android.app.assist.AssistContent}. - */ -@Deprecated -public class AssistContent { - private boolean mIsAppProvidedIntent = false; - private Intent mIntent; - private String mStructuredData; - private ClipData mClipData; - private Uri mUri; - private final Bundle mExtras; - - /** - * @hide - * Key name this data structure is stored in the Bundle generated by - * {@link android.app.Activity#onProvideAssistData}. - */ - public static final String ASSIST_KEY = "android:assist_content"; - - /** - * @hide - * Retrieve the framework-generated AssistContent that is stored within - * the Bundle filled in by {@link android.app.Activity#onProvideAssistContent}. - */ - public static android.app.assist.AssistContent getAssistContent(Bundle assistBundle) { - return assistBundle.getParcelable(ASSIST_KEY); - } - - public AssistContent() { - mExtras = new Bundle(); - } - - /** - * @hide - * Called by {@link android.app.ActivityThread} to set the default Intent based on - * {@link android.app.Activity#getIntent Activity.getIntent}. - * - * <p>Automatically populates {@link #mUri} if that Intent is an {@link Intent#ACTION_VIEW} - * of a web (http or https scheme) URI.</p> - */ - public void setDefaultIntent(Intent intent) { - mIntent = intent; - setWebUri(null); - if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) { - Uri uri = intent.getData(); - if (uri != null) { - if ("http".equals(uri.getScheme()) || "https".equals(uri.getScheme())) { - setWebUri(uri); - } - } - } - } - - /** - * 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 accessibility - * service can access it. - */ - public void setIntent(Intent intent) { - mIsAppProvidedIntent = true; - mIntent = intent; - } - - /** - * Returns the current {@link #setIntent} if one is set, else the default Intent obtained from - * {@link android.app.Activity#getIntent Activity.getIntent}. Can be modified in-place. - * @hide - */ - public Intent getIntent() { - return mIntent; - } - - /** - * Returns whether or not the current Intent was explicitly provided in - * {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}. If not, - * the Intent was automatically set based on - * {@link android.app.Activity#getIntent Activity.getIntent}. - */ - public boolean isAppProvidedIntent() { - return mIsAppProvidedIntent; - } - - /** - * 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; - } - - /** - * Sets optional structured data regarding the content being viewed. The provided data - * must be a string represented with <a href="http://json-ld.org/">JSON-LD</a> using the - * <a href="http://schema.org/">schema.org</a> vocabulary. - */ - public void setStructuredData(String structuredData) { - mStructuredData = structuredData; - } - - /** - * Returns the current {@link #setStructuredData}. - */ - public String getStructuredData() { - return mStructuredData; - } - - /** - * Set a web URI associated with the current data being shown to the user. - * This URI could be opened in a web browser, or in the app as an - * {@link Intent#ACTION_VIEW} Intent, to show the same data that is currently - * being displayed by it. The URI here should be something that is transportable - * off the device into other environments to acesss the same data as is currently - * being shown in the app; if the app does not have such a representation, it should - * leave the null and only report the local intent and clip data. - */ - public void setWebUri(Uri uri) { - mUri = uri; - } - - /** - * Return the content's web URI as per {@link #setWebUri(android.net.Uri)}, or null if - * there is none. - */ - public Uri getWebUri() { - return mUri; - } - - /** - * Return Bundle for extra vendor-specific data that can be modified and examined. - */ - public Bundle getExtras() { - return mExtras; - } - - /** @hide */ - public AssistContent(Parcel in) { - if (in.readInt() != 0) { - mIntent = Intent.CREATOR.createFromParcel(in); - } - if (in.readInt() != 0) { - mClipData = ClipData.CREATOR.createFromParcel(in); - } - if (in.readInt() != 0) { - mUri = Uri.CREATOR.createFromParcel(in); - } - if (in.readInt() != 0) { - mStructuredData = in.readString(); - } - mIsAppProvidedIntent = in.readInt() == 1; - mExtras = in.readBundle(); - } - - /** @hide */ - public void writeToParcelInternal(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); - } - if (mUri != null) { - dest.writeInt(1); - mUri.writeToParcel(dest, flags); - } else { - dest.writeInt(0); - } - if (mStructuredData != null) { - dest.writeInt(1); - dest.writeString(mStructuredData); - } else { - dest.writeInt(0); - } - dest.writeInt(mIsAppProvidedIntent ? 1 : 0); - dest.writeBundle(mExtras); - } -} diff --git a/core/java/android/app/AssistStructure.java b/core/java/android/app/AssistStructure.java deleted file mode 100644 index 7f6dae5..0000000 --- a/core/java/android/app/AssistStructure.java +++ /dev/null @@ -1,1075 +0,0 @@ -/* - * 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.ComponentName; -import android.graphics.Rect; -import android.os.Binder; -import android.os.Bundle; -import android.os.IBinder; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.PooledStringReader; -import android.os.PooledStringWriter; -import android.os.RemoteException; -import android.os.SystemClock; -import android.text.TextUtils; -import android.util.Log; -import android.view.View; -import android.view.ViewAssistStructure; -import android.view.ViewRootImpl; -import android.view.WindowManager; -import android.view.WindowManagerGlobal; - -import java.util.ArrayList; - -/** - * Assist data automatically created by the platform's implementation - * of {@link android.app.Activity#onProvideAssistData}. - * @deprecated use {@link android.app.assist.AssistStructure}. - */ -@Deprecated -public class AssistStructure { - static final String TAG = "AssistStructure"; - - /** - * @hide - * Key name this data structure is stored in the Bundle generated by - * {@link android.app.Activity#onProvideAssistData}. - */ - public static final String ASSIST_KEY = "android:assist_structure"; - - /** @hide */ - public boolean mHaveData; - - ComponentName mActivityComponent; - - final ArrayList<WindowNode> mWindowNodes = new ArrayList<>(); - - final ArrayList<ViewNodeBuilder> mPendingAsyncChildren = new ArrayList<>(); - - /** @hide */ - public SendChannel mSendChannel; - /** @hide */ - public IBinder mReceiveChannel; - - Rect mTmpRect = new Rect(); - - static final int TRANSACTION_XFER = Binder.FIRST_CALL_TRANSACTION+1; - static final String DESCRIPTOR = "android.app.AssistStructure"; - - /** @hide */ - public final class SendChannel extends Binder { - @Override protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) - throws RemoteException { - if (code == TRANSACTION_XFER) { - data.enforceInterface(DESCRIPTOR); - writeContentToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); - return true; - } else { - return super.onTransact(code, data, reply, flags); - } - } - } - - final static class ViewNodeText { - CharSequence mText; - int mTextSelectionStart; - int mTextSelectionEnd; - int mTextColor; - int mTextBackgroundColor; - float mTextSize; - int mTextStyle; - String mHint; - - ViewNodeText() { - } - - ViewNodeText(Parcel in) { - 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) { - 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); - } - } - - /** - * Describes a window in the assist data. - */ - static public class WindowNode { - final int mX; - final int mY; - final int mWidth; - final int mHeight; - final CharSequence mTitle; - final int mDisplayId; - final ViewNode mRoot; - - WindowNode(AssistStructure assist, ViewRootImpl root) { - View view = root.getView(); - Rect rect = new Rect(); - view.getBoundsOnScreen(rect); - mX = rect.left - view.getLeft(); - mY = rect.top - view.getTop(); - mWidth = rect.width(); - mHeight = rect.height(); - mTitle = root.getTitle(); - mDisplayId = root.getDisplayId(); - mRoot = new ViewNode(); - ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false); - if ((root.getWindowFlags()&WindowManager.LayoutParams.FLAG_SECURE) != 0) { - // This is a secure window, so it doesn't want a screenshot, and that - // means we should also not copy out its view hierarchy. - view.onProvideStructure(builder); - builder.setAssistBlocked(true); - return; - } - view.dispatchProvideStructure(builder); - } - - WindowNode(Parcel in, PooledStringReader preader) { - mX = in.readInt(); - mY = in.readInt(); - mWidth = in.readInt(); - mHeight = in.readInt(); - mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); - mDisplayId = in.readInt(); - mRoot = new ViewNode(in, preader); - } - - void writeToParcel(Parcel out, PooledStringWriter pwriter) { - out.writeInt(mX); - out.writeInt(mY); - out.writeInt(mWidth); - out.writeInt(mHeight); - TextUtils.writeToParcel(mTitle, out, 0); - out.writeInt(mDisplayId); - mRoot.writeToParcel(out, pwriter); - } - - /** - * Returns the left edge of the window, in pixels, relative to the left - * edge of the screen. - */ - public int getLeft() { - return mX; - } - - /** - * Returns the top edge of the window, in pixels, relative to the top - * edge of the screen. - */ - public int getTop() { - return mY; - } - - /** - * Returns the total width of the window in pixels. - */ - public int getWidth() { - return mWidth; - } - - /** - * Returns the total height of the window in pixels. - */ - public int getHeight() { - return mHeight; - } - - /** - * Returns the title associated with the window, if it has one. - */ - public CharSequence getTitle() { - return mTitle; - } - - /** - * Returns the ID of the display this window is on, for use with - * {@link android.hardware.display.DisplayManager#getDisplay DisplayManager.getDisplay()}. - */ - public int getDisplayId() { - return mDisplayId; - } - - /** - * Returns the {@link ViewNode} containing the root content of the window. - */ - public ViewNode getRootViewNode() { - return mRoot; - } - } - - /** - * Describes 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; - - int mId; - String mIdPackage; - String mIdType; - String mIdEntry; - int mX; - int mY; - int mScrollX; - int mScrollY; - int mWidth; - int mHeight; - - static final int FLAGS_DISABLED = 0x00000001; - static final int FLAGS_VISIBILITY_MASK = View.VISIBLE|View.INVISIBLE|View.GONE; - static final int FLAGS_FOCUSABLE = 0x00000010; - static final int FLAGS_FOCUSED = 0x00000020; - static final int FLAGS_ACCESSIBILITY_FOCUSED = 0x04000000; - static final int FLAGS_SELECTED = 0x00000040; - static final int FLAGS_ASSIST_BLOCKED = 0x00000080; - static final int FLAGS_ACTIVATED = 0x40000000; - static final int FLAGS_CHECKABLE = 0x00000100; - static final int FLAGS_CHECKED = 0x00000200; - static final int FLAGS_CLICKABLE = 0x00004000; - static final int FLAGS_LONG_CLICKABLE = 0x00200000; - static final int FLAGS_CONTEXT_CLICKABLE = 0x00400000; - - int mFlags; - - String mClassName; - CharSequence mContentDescription; - - ViewNodeText mText; - Bundle mExtras; - - ViewNode[] mChildren; - - ViewNode() { - } - - ViewNode(Parcel in, PooledStringReader preader) { - mId = in.readInt(); - if (mId != 0) { - mIdEntry = preader.readString(); - if (mIdEntry != null) { - mIdType = preader.readString(); - mIdPackage = preader.readString(); - } else { - mIdPackage = mIdType = null; - } - } else { - mIdPackage = mIdType = mIdEntry = null; - } - mX = in.readInt(); - mY = in.readInt(); - mScrollX = in.readInt(); - mScrollY = in.readInt(); - mWidth = in.readInt(); - mHeight = in.readInt(); - mFlags = in.readInt(); - mClassName = preader.readString(); - mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); - if (in.readInt() != 0) { - mText = new ViewNodeText(in); - } else { - mText = null; - } - mExtras = in.readBundle(); - final int NCHILDREN = in.readInt(); - if (NCHILDREN > 0) { - mChildren = new ViewNode[NCHILDREN]; - for (int i=0; i<NCHILDREN; i++) { - mChildren[i] = new ViewNode(in, preader); - } - } else { - mChildren = null; - } - } - - void writeToParcel(Parcel out, PooledStringWriter pwriter) { - out.writeInt(mId); - if (mId != 0) { - pwriter.writeString(mIdEntry); - if (mIdEntry != null) { - pwriter.writeString(mIdType); - pwriter.writeString(mIdPackage); - } - } - out.writeInt(mX); - out.writeInt(mY); - out.writeInt(mScrollX); - out.writeInt(mScrollY); - out.writeInt(mWidth); - out.writeInt(mHeight); - out.writeInt(mFlags); - pwriter.writeString(mClassName); - TextUtils.writeToParcel(mContentDescription, out, 0); - if (mText != null) { - out.writeInt(1); - mText.writeToParcel(out); - } else { - out.writeInt(0); - } - out.writeBundle(mExtras); - if (mChildren != null) { - final int NCHILDREN = mChildren.length; - out.writeInt(NCHILDREN); - for (int i=0; i<NCHILDREN; i++) { - mChildren[i].writeToParcel(out, pwriter); - } - } else { - out.writeInt(0); - } - } - - /** - * Returns the ID associated with this view, as per {@link View#getId() View.getId()}. - */ - public int getId() { - return mId; - } - - /** - * If {@link #getId()} is a resource identifier, this is the package name of that - * identifier. See {@link android.view.ViewStructure#setId ViewStructure.setId} - * for more information. - */ - public String getIdPackage() { - return mIdPackage; - } - - /** - * If {@link #getId()} is a resource identifier, this is the type name of that - * identifier. See {@link android.view.ViewStructure#setId ViewStructure.setId} - * for more information. - */ - public String getIdType() { - return mIdType; - } - - /** - * If {@link #getId()} is a resource identifier, this is the entry name of that - * identifier. See {@link android.view.ViewStructure#setId ViewStructure.setId} - * for more information. - */ - public String getIdEntry() { - return mIdEntry; - } - - /** - * Returns the left edge of this view, in pixels, relative to the left edge of its parent. - */ - public int getLeft() { - return mX; - } - - /** - * Returns the top edge of this view, in pixels, relative to the top edge of its parent. - */ - public int getTop() { - return mY; - } - - /** - * Returns the current X scroll offset of this view, as per - * {@link android.view.View#getScrollX() View.getScrollX()}. - */ - public int getScrollX() { - return mScrollX; - } - - /** - * Returns the current Y scroll offset of this view, as per - * {@link android.view.View#getScrollX() View.getScrollY()}. - */ - public int getScrollY() { - return mScrollY; - } - - /** - * Returns the width of this view, in pixels. - */ - public int getWidth() { - return mWidth; - } - - /** - * Returns the height of this view, in pixels. - */ - public int getHeight() { - return mHeight; - } - - /** - * Returns the visibility mode of this view, as per - * {@link android.view.View#getVisibility() View.getVisibility()}. - */ - public int getVisibility() { - return mFlags&ViewNode.FLAGS_VISIBILITY_MASK; - } - - /** - * Returns true if assist data has been blocked starting at this node in the hierarchy. - */ - public boolean isAssistBlocked() { - return (mFlags&ViewNode.FLAGS_ASSIST_BLOCKED) == 0; - } - - /** - * Returns true if this node is in an enabled state. - */ - public boolean isEnabled() { - return (mFlags&ViewNode.FLAGS_DISABLED) == 0; - } - - /** - * Returns true if this node is clickable by the user. - */ - public boolean isClickable() { - return (mFlags&ViewNode.FLAGS_CLICKABLE) != 0; - } - - /** - * Returns true if this node can take input focus. - */ - public boolean isFocusable() { - return (mFlags&ViewNode.FLAGS_FOCUSABLE) != 0; - } - - /** - * Returns true if this node currently had input focus at the time that the - * structure was collected. - */ - public boolean isFocused() { - return (mFlags&ViewNode.FLAGS_FOCUSED) != 0; - } - - /** - * Returns true if this node currently had accessibility focus at the time that the - * structure was collected. - */ - public boolean isAccessibilityFocused() { - return (mFlags&ViewNode.FLAGS_ACCESSIBILITY_FOCUSED) != 0; - } - - /** - * Returns true if this node represents something that is checkable by the user. - */ - public boolean isCheckable() { - return (mFlags&ViewNode.FLAGS_CHECKABLE) != 0; - } - - /** - * Returns true if this node is currently in a checked state. - */ - public boolean isChecked() { - return (mFlags&ViewNode.FLAGS_CHECKED) != 0; - } - - /** - * Returns true if this node has currently been selected by the user. - */ - public boolean isSelected() { - return (mFlags&ViewNode.FLAGS_SELECTED) != 0; - } - - /** - * Returns true if this node has currently been activated by the user. - */ - public boolean isActivated() { - return (mFlags&ViewNode.FLAGS_ACTIVATED) != 0; - } - - /** - * Returns true if this node is something the user can perform a long click/press on. - */ - public boolean isLongClickable() { - return (mFlags&ViewNode.FLAGS_LONG_CLICKABLE) != 0; - } - - /** - * Returns true if this node is something the user can perform a context click on. - */ - public boolean isContextClickable() { - return (mFlags&ViewNode.FLAGS_CONTEXT_CLICKABLE) != 0; - } - - /** - * Returns the class name of the node's implementation, indicating its behavior. - * For example, a button will report "android.widget.Button" meaning it behaves - * like a {@link android.widget.Button}. - */ - public String getClassName() { - return mClassName; - } - - /** - * Returns any content description associated with the node, which semantically describes - * its purpose for accessibility and other uses. - */ - public CharSequence getContentDescription() { - return mContentDescription; - } - - /** - * Returns any text associated with the node that is displayed to the user, or null - * if there is none. - */ - public CharSequence getText() { - return mText != null ? mText.mText : null; - } - - /** - * If {@link #getText()} is non-null, this is where the current selection starts. - */ - public int getTextSelectionStart() { - return mText != null ? mText.mTextSelectionStart : -1; - } - - /** - * If {@link #getText()} is non-null, this is where the current selection starts. - * If there is no selection, returns the same value as {@link #getTextSelectionStart()}, - * indicating the cursor position. - */ - public int getTextSelectionEnd() { - return mText != null ? mText.mTextSelectionEnd : -1; - } - - /** - * If {@link #getText()} is non-null, this is the main text color associated with it. - * If there is no text color, {@link #TEXT_COLOR_UNDEFINED} is returned. - * Note that the text may also contain style spans that modify the color of specific - * parts of the text. - */ - public int getTextColor() { - return mText != null ? mText.mTextColor : TEXT_COLOR_UNDEFINED; - } - - /** - * If {@link #getText()} is non-null, this is the main text background color associated - * with it. - * If there is no text background color, {@link #TEXT_COLOR_UNDEFINED} is returned. - * Note that the text may also contain style spans that modify the color of specific - * parts of the text. - */ - public int getTextBackgroundColor() { - return mText != null ? mText.mTextBackgroundColor : TEXT_COLOR_UNDEFINED; - } - - /** - * If {@link #getText()} is non-null, this is the main text size (in pixels) associated - * with it. - * Note that the text may also contain style spans that modify the size of specific - * parts of the text. - */ - public float getTextSize() { - return mText != null ? mText.mTextSize : 0; - } - - /** - * If {@link #getText()} is non-null, this is the main text style associated - * with it, containing a bit mask of {@link #TEXT_STYLE_BOLD}, - * {@link #TEXT_STYLE_BOLD}, {@link #TEXT_STYLE_STRIKE_THRU}, and/or - * {@link #TEXT_STYLE_UNDERLINE}. - * Note that the text may also contain style spans that modify the style of specific - * parts of the text. - */ - public int getTextStyle() { - return mText != null ? mText.mTextStyle : 0; - } - - /** - * Return additional hint text associated with the node; this is typically used with - * a node that takes user input, describing to the user what the input means. - */ - public String getHint() { - return mText != null ? mText.mHint : null; - } - - /** - * Return a Bundle containing optional vendor-specific extension information. - */ - public Bundle getExtras() { - return mExtras; - } - - /** - * Return the number of children this node has. - */ - public int getChildCount() { - return mChildren != null ? mChildren.length : 0; - } - - /** - * Return a child of this node, given an index value from 0 to - * {@link #getChildCount()}-1. - */ - public ViewNode getChildAt(int index) { - return mChildren[index]; - } - } - - static class ViewNodeBuilder extends ViewAssistStructure { - final AssistStructure mAssist; - final ViewNode mNode; - final boolean mAsync; - - ViewNodeBuilder(AssistStructure assist, ViewNode node, boolean async) { - mAssist = assist; - mNode = node; - mAsync = async; - } - - @Override - public void setId(int id, String packageName, String typeName, String entryName) { - mNode.mId = id; - mNode.mIdPackage = packageName; - mNode.mIdType = typeName; - mNode.mIdEntry = entryName; - } - - @Override - public void setDimens(int left, int top, int scrollX, int scrollY, int width, int height) { - mNode.mX = left; - mNode.mY = top; - mNode.mScrollX = scrollX; - mNode.mScrollY = scrollY; - mNode.mWidth = width; - mNode.mHeight = height; - } - - @Override - public void setVisibility(int visibility) { - mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_VISIBILITY_MASK) | visibility; - } - - @Override - public void setAssistBlocked(boolean state) { - mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ASSIST_BLOCKED) - | (state ? 0 : ViewNode.FLAGS_ASSIST_BLOCKED); - } - - @Override - public void setEnabled(boolean state) { - mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_DISABLED) - | (state ? 0 : ViewNode.FLAGS_DISABLED); - } - - @Override - public void setClickable(boolean state) { - mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CLICKABLE) - | (state ? ViewNode.FLAGS_CLICKABLE : 0); - } - - @Override - public void setLongClickable(boolean state) { - mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_LONG_CLICKABLE) - | (state ? ViewNode.FLAGS_LONG_CLICKABLE : 0); - } - - @Override - public void setContextClickable(boolean state) { - mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CONTEXT_CLICKABLE) - | (state ? ViewNode.FLAGS_CONTEXT_CLICKABLE : 0); - } - - @Override - public void setFocusable(boolean state) { - mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSABLE) - | (state ? ViewNode.FLAGS_FOCUSABLE : 0); - } - - @Override - public void setFocused(boolean state) { - mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSED) - | (state ? ViewNode.FLAGS_FOCUSED : 0); - } - - @Override - public void setAccessibilityFocused(boolean state) { - mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ACCESSIBILITY_FOCUSED) - | (state ? ViewNode.FLAGS_ACCESSIBILITY_FOCUSED : 0); - } - - @Override - public void setCheckable(boolean state) { - mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CHECKABLE) - | (state ? ViewNode.FLAGS_CHECKABLE : 0); - } - - @Override - public void setChecked(boolean state) { - mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CHECKED) - | (state ? ViewNode.FLAGS_CHECKED : 0); - } - - @Override - public void setSelected(boolean state) { - mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_SELECTED) - | (state ? ViewNode.FLAGS_SELECTED : 0); - } - - @Override - public void setActivated(boolean state) { - mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ACTIVATED) - | (state ? ViewNode.FLAGS_ACTIVATED : 0); - } - - @Override - public void setClassName(String className) { - mNode.mClassName = className; - } - - @Override - public void setContentDescription(CharSequence contentDescription) { - mNode.mContentDescription = contentDescription; - } - - private final ViewNodeText getNodeText() { - if (mNode.mText != null) { - return mNode.mText; - } - mNode.mText = new ViewNodeText(); - return mNode.mText; - } - - @Override - public void setText(CharSequence text) { - ViewNodeText t = getNodeText(); - t.mText = text; - t.mTextSelectionStart = t.mTextSelectionEnd = -1; - } - - @Override - public void setText(CharSequence text, int selectionStart, int selectionEnd) { - ViewNodeText t = getNodeText(); - t.mText = text; - t.mTextSelectionStart = selectionStart; - t.mTextSelectionEnd = selectionEnd; - } - - @Override - public void setTextStyle(float size, int fgColor, int bgColor, int style) { - ViewNodeText t = getNodeText(); - t.mTextColor = fgColor; - t.mTextBackgroundColor = bgColor; - t.mTextSize = size; - t.mTextStyle = style; - } - - @Override - public void setHint(CharSequence hint) { - getNodeText().mHint = hint != null ? hint.toString() : null; - } - - @Override - public CharSequence getText() { - return mNode.mText != null ? mNode.mText.mText : null; - } - - @Override - public int getTextSelectionStart() { - return mNode.mText != null ? mNode.mText.mTextSelectionStart : -1; - } - - @Override - public int getTextSelectionEnd() { - return mNode.mText != null ? mNode.mText.mTextSelectionEnd : -1; - } - - @Override - public CharSequence getHint() { - return mNode.mText != null ? mNode.mText.mHint : null; - } - - @Override - public Bundle getExtras() { - if (mNode.mExtras != null) { - return mNode.mExtras; - } - mNode.mExtras = new Bundle(); - return mNode.mExtras; - } - - @Override - public boolean hasExtras() { - return mNode.mExtras != null; - } - - @Override - public void setChildCount(int num) { - mNode.mChildren = new ViewNode[num]; - } - - @Override - public int addChildCount(int num) { - if (mNode.mChildren == null) { - setChildCount(num); - return 0; - } - final int start = mNode.mChildren.length; - ViewNode[] newArray = new ViewNode[start + num]; - System.arraycopy(mNode.mChildren, 0, newArray, 0, start); - mNode.mChildren = newArray; - return start; - } - - @Override - public int getChildCount() { - return mNode.mChildren != null ? mNode.mChildren.length : 0; - } - - @Override - public ViewAssistStructure newChild(int index) { - ViewNode node = new ViewNode(); - mNode.mChildren[index] = node; - return new ViewNodeBuilder(mAssist, node, false); - } - - @Override - public ViewAssistStructure asyncNewChild(int index) { - synchronized (mAssist) { - ViewNode node = new ViewNode(); - mNode.mChildren[index] = node; - ViewNodeBuilder builder = new ViewNodeBuilder(mAssist, node, true); - mAssist.mPendingAsyncChildren.add(builder); - return builder; - } - } - - @Override - public void asyncCommit() { - synchronized (mAssist) { - if (!mAsync) { - throw new IllegalStateException("Child " + this - + " was not created with ViewAssistStructure.asyncNewChild"); - } - if (!mAssist.mPendingAsyncChildren.remove(this)) { - throw new IllegalStateException("Child " + this + " already committed"); - } - mAssist.notifyAll(); - } - } - - @Override - public Rect getTempRect() { - return mAssist.mTmpRect; - } - } - - /** @hide */ - public AssistStructure(Activity activity) { - mHaveData = true; - mActivityComponent = activity.getComponentName(); - ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews( - activity.getActivityToken()); - for (int i=0; i<views.size(); i++) { - ViewRootImpl root = views.get(i); - mWindowNodes.add(new WindowNode(this, root)); - } - } - - public AssistStructure() { - mHaveData = true; - mActivityComponent = null; - } - - /** @hide */ - public AssistStructure(Parcel in) { - mReceiveChannel = in.readStrongBinder(); - } - - /** @hide */ - public void dump() { - Log.i(TAG, "Activity: " + mActivityComponent.flattenToShortString()); - final int N = getWindowNodeCount(); - for (int i=0; i<N; i++) { - WindowNode node = getWindowNodeAt(i); - Log.i(TAG, "Window #" + i + " [" + node.getLeft() + "," + node.getTop() - + " " + node.getWidth() + "x" + node.getHeight() + "]" + " " + node.getTitle()); - dump(" ", node.getRootViewNode()); - } - } - - void dump(String prefix, ViewNode node) { - Log.i(TAG, prefix + "View [" + node.getLeft() + "," + node.getTop() - + " " + node.getWidth() + "x" + node.getHeight() + "]" + " " + node.getClassName()); - int id = node.getId(); - if (id != 0) { - StringBuilder sb = new StringBuilder(); - sb.append(prefix); sb.append(" ID: #"); sb.append(Integer.toHexString(id)); - String entry = node.getIdEntry(); - if (entry != null) { - String type = node.getIdType(); - String pkg = node.getIdPackage(); - sb.append(" "); sb.append(pkg); sb.append(":"); sb.append(type); - sb.append("/"); sb.append(entry); - } - Log.i(TAG, sb.toString()); - } - int scrollX = node.getScrollX(); - int scrollY = node.getScrollY(); - if (scrollX != 0 || scrollY != 0) { - Log.i(TAG, prefix + " Scroll: " + scrollX + "," + scrollY); - } - CharSequence contentDescription = node.getContentDescription(); - if (contentDescription != null) { - Log.i(TAG, prefix + " Content description: " + contentDescription); - } - 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) { - Log.i(TAG, prefix + " Hint: " + hint); - } - Bundle extras = node.getExtras(); - if (extras != null) { - Log.i(TAG, prefix + " Extras: " + extras); - } - final int NCHILDREN = node.getChildCount(); - if (NCHILDREN > 0) { - Log.i(TAG, prefix + " Children:"); - String cprefix = prefix + " "; - for (int i=0; i<NCHILDREN; i++) { - ViewNode cnode = node.getChildAt(i); - dump(cprefix, cnode); - } - } - } - - /** - * @hide - * Retrieve the framework-generated AssistStructure that is stored within - * the Bundle filled in by {@link Activity#onProvideAssistData}. - */ - public static android.app.assist.AssistStructure getAssistStructure(Bundle assistBundle) { - return assistBundle.getParcelable(ASSIST_KEY); - } - - /** - * Return the activity this AssistStructure came from. - */ - public ComponentName getActivityComponent() { - ensureData(); - return mActivityComponent; - } - - /** - * Return the number of window contents that have been collected in this assist data. - */ - public int getWindowNodeCount() { - ensureData(); - return mWindowNodes.size(); - } - - /** - * Return one of the windows in the assist data. - * @param index Which window to retrieve, may be 0 to {@link #getWindowNodeCount()}-1. - * @hide - */ - public WindowNode getWindowNodeAt(int index) { - ensureData(); - return mWindowNodes.get(index); - } - - /** @hide */ - public void ensureData() { - if (mHaveData) { - return; - } - mHaveData = true; - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - data.writeInterfaceToken(DESCRIPTOR); - try { - mReceiveChannel.transact(TRANSACTION_XFER, data, reply, 0); - } catch (RemoteException e) { - Log.w(TAG, "Failure reading AssistStructure data", e); - return; - } - readContentFromParcel(reply); - data.recycle(); - reply.recycle(); - } - - void writeContentToParcel(Parcel out, int flags) { - // First make sure all content has been created. - boolean skipStructure = false; - synchronized (this) { - long endTime = SystemClock.uptimeMillis() + 5000; - long now; - while (mPendingAsyncChildren.size() > 0 && (now=SystemClock.uptimeMillis()) < endTime) { - try { - wait(endTime-now); - } catch (InterruptedException e) { - } - } - if (mPendingAsyncChildren.size() > 0) { - // We waited too long, assume none of the assist structure is valid. - skipStructure = true; - } - } - int start = out.dataPosition(); - PooledStringWriter pwriter = new PooledStringWriter(out); - ComponentName.writeToParcel(mActivityComponent, out); - final int N = skipStructure ? 0 : mWindowNodes.size(); - out.writeInt(N); - for (int i=0; i<N; i++) { - mWindowNodes.get(i).writeToParcel(out, pwriter); - } - pwriter.finish(); - Log.i(TAG, "Flattened assist data: " + (out.dataPosition() - start) + " bytes"); - } - - void readContentFromParcel(Parcel in) { - PooledStringReader preader = new PooledStringReader(in); - mActivityComponent = ComponentName.readFromParcel(in); - final int N = in.readInt(); - for (int i=0; i<N; i++) { - mWindowNodes.add(new WindowNode(in, preader)); - } - //dump(); - } -} diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java index 9cc399d..abb8244 100644 --- a/core/java/android/app/VoiceInteractor.java +++ b/core/java/android/app/VoiceInteractor.java @@ -225,6 +225,9 @@ public final class VoiceInteractor { * Cancel this active request. */ public void cancel() { + if (mRequestInterface == null) { + throw new IllegalStateException("Request " + this + " is no longer active"); + } try { mRequestInterface.cancel(); } catch (RemoteException e) { diff --git a/core/java/android/app/assist/AssistContent.java b/core/java/android/app/assist/AssistContent.java index c7e7330..07b2d57 100644 --- a/core/java/android/app/assist/AssistContent.java +++ b/core/java/android/app/assist/AssistContent.java @@ -1,24 +1,184 @@ package android.app.assist; +import android.content.ClipData; import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; /** - * New home for AssistContent. + * 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 android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}. */ -public final class AssistContent extends android.app.AssistContent implements Parcelable { +@Deprecated +public class AssistContent implements Parcelable { + private boolean mIsAppProvidedIntent = false; + private Intent mIntent; + private String mStructuredData; + private ClipData mClipData; + private Uri mUri; + private final Bundle mExtras; - /** @hide */ public AssistContent() { + mExtras = new Bundle(); } - public AssistContent(Parcel in) { - super(in); + /** + * @hide + * Called by {@link android.app.ActivityThread} to set the default Intent based on + * {@link android.app.Activity#getIntent Activity.getIntent}. + * + * <p>Automatically populates {@link #mUri} if that Intent is an {@link Intent#ACTION_VIEW} + * of a web (http or https scheme) URI.</p> + */ + public void setDefaultIntent(Intent intent) { + mIntent = intent; + setWebUri(null); + if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) { + Uri uri = intent.getData(); + if (uri != null) { + if ("http".equals(uri.getScheme()) || "https".equals(uri.getScheme())) { + setWebUri(uri); + } + } + } + } + + /** + * 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 accessibility + * service can access it. + */ + public void setIntent(Intent intent) { + mIsAppProvidedIntent = true; + mIntent = intent; } + /** + * Returns the current {@link #setIntent} if one is set, else the default Intent obtained from + * {@link android.app.Activity#getIntent Activity.getIntent}. Can be modified in-place. + */ public Intent getIntent() { - return super.getIntent(); + return mIntent; + } + + /** + * Returns whether or not the current Intent was explicitly provided in + * {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}. If not, + * the Intent was automatically set based on + * {@link android.app.Activity#getIntent Activity.getIntent}. + */ + public boolean isAppProvidedIntent() { + return mIsAppProvidedIntent; + } + + /** + * 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; + } + + /** + * Sets optional structured data regarding the content being viewed. The provided data + * must be a string represented with <a href="http://json-ld.org/">JSON-LD</a> using the + * <a href="http://schema.org/">schema.org</a> vocabulary. + */ + public void setStructuredData(String structuredData) { + mStructuredData = structuredData; + } + + /** + * Returns the current {@link #setStructuredData}. + */ + public String getStructuredData() { + return mStructuredData; + } + + /** + * Set a web URI associated with the current data being shown to the user. + * This URI could be opened in a web browser, or in the app as an + * {@link Intent#ACTION_VIEW} Intent, to show the same data that is currently + * being displayed by it. The URI here should be something that is transportable + * off the device into other environments to acesss the same data as is currently + * being shown in the app; if the app does not have such a representation, it should + * leave the null and only report the local intent and clip data. + */ + public void setWebUri(Uri uri) { + mUri = uri; + } + + /** + * Return the content's web URI as per {@link #setWebUri(android.net.Uri)}, or null if + * there is none. + */ + public Uri getWebUri() { + return mUri; + } + + /** + * Return Bundle for extra vendor-specific data that can be modified and examined. + */ + public Bundle getExtras() { + return mExtras; + } + + AssistContent(Parcel in) { + if (in.readInt() != 0) { + mIntent = Intent.CREATOR.createFromParcel(in); + } + if (in.readInt() != 0) { + mClipData = ClipData.CREATOR.createFromParcel(in); + } + if (in.readInt() != 0) { + mUri = Uri.CREATOR.createFromParcel(in); + } + if (in.readInt() != 0) { + mStructuredData = in.readString(); + } + mIsAppProvidedIntent = in.readInt() == 1; + mExtras = in.readBundle(); + } + + void writeToParcelInternal(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); + } + if (mUri != null) { + dest.writeInt(1); + mUri.writeToParcel(dest, flags); + } else { + dest.writeInt(0); + } + if (mStructuredData != null) { + dest.writeInt(1); + dest.writeString(mStructuredData); + } else { + dest.writeInt(0); + } + dest.writeInt(mIsAppProvidedIntent ? 1 : 0); + dest.writeBundle(mExtras); } @Override diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index 1677e95..1a04895 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -1,28 +1,1038 @@ package android.app.assist; import android.app.Activity; +import android.content.ComponentName; +import android.graphics.Rect; +import android.os.Binder; +import android.os.Bundle; +import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; +import android.os.PooledStringReader; +import android.os.PooledStringWriter; +import android.os.RemoteException; +import android.os.SystemClock; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.view.ViewAssistStructure; +import android.view.ViewRootImpl; +import android.view.WindowManager; +import android.view.WindowManagerGlobal; + +import java.util.ArrayList; /** - * New home for AssistStructure. + * Assist data automatically created by the platform's implementation + * of {@link android.app.Activity#onProvideAssistData}. */ -public final class AssistStructure extends android.app.AssistStructure implements Parcelable { +public class AssistStructure implements Parcelable { + static final String TAG = "AssistStructure"; - public AssistStructure() { + boolean mHaveData; + + ComponentName mActivityComponent; + + final ArrayList<WindowNode> mWindowNodes = new ArrayList<>(); + + final ArrayList<ViewNodeBuilder> mPendingAsyncChildren = new ArrayList<>(); + + SendChannel mSendChannel; + IBinder mReceiveChannel; + + Rect mTmpRect = new Rect(); + + static final int TRANSACTION_XFER = Binder.FIRST_CALL_TRANSACTION+1; + static final String DESCRIPTOR = "android.app.AssistStructure"; + + final class SendChannel extends Binder { + @Override protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) + throws RemoteException { + if (code == TRANSACTION_XFER) { + data.enforceInterface(DESCRIPTOR); + writeContentToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + return true; + } else { + return super.onTransact(code, data, reply, flags); + } + } + } + + final static class ViewNodeText { + CharSequence mText; + int mTextSelectionStart; + int mTextSelectionEnd; + int mTextColor; + int mTextBackgroundColor; + float mTextSize; + int mTextStyle; + String mHint; + + ViewNodeText() { + } + + ViewNodeText(Parcel in) { + 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) { + 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); + } + } + + /** + * Describes a window in the assist data. + */ + static public class WindowNode { + final int mX; + final int mY; + final int mWidth; + final int mHeight; + final CharSequence mTitle; + final int mDisplayId; + final ViewNode mRoot; + + WindowNode(AssistStructure assist, ViewRootImpl root) { + View view = root.getView(); + Rect rect = new Rect(); + view.getBoundsOnScreen(rect); + mX = rect.left - view.getLeft(); + mY = rect.top - view.getTop(); + mWidth = rect.width(); + mHeight = rect.height(); + mTitle = root.getTitle(); + mDisplayId = root.getDisplayId(); + mRoot = new ViewNode(); + ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false); + if ((root.getWindowFlags()& WindowManager.LayoutParams.FLAG_SECURE) != 0) { + // This is a secure window, so it doesn't want a screenshot, and that + // means we should also not copy out its view hierarchy. + view.onProvideStructure(builder); + builder.setAssistBlocked(true); + return; + } + view.dispatchProvideStructure(builder); + } + + WindowNode(Parcel in, PooledStringReader preader) { + mX = in.readInt(); + mY = in.readInt(); + mWidth = in.readInt(); + mHeight = in.readInt(); + mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); + mDisplayId = in.readInt(); + mRoot = new ViewNode(in, preader); + } + + void writeToParcel(Parcel out, PooledStringWriter pwriter) { + out.writeInt(mX); + out.writeInt(mY); + out.writeInt(mWidth); + out.writeInt(mHeight); + TextUtils.writeToParcel(mTitle, out, 0); + out.writeInt(mDisplayId); + mRoot.writeToParcel(out, pwriter); + } + + /** + * Returns the left edge of the window, in pixels, relative to the left + * edge of the screen. + */ + public int getLeft() { + return mX; + } + + /** + * Returns the top edge of the window, in pixels, relative to the top + * edge of the screen. + */ + public int getTop() { + return mY; + } + + /** + * Returns the total width of the window in pixels. + */ + public int getWidth() { + return mWidth; + } + + /** + * Returns the total height of the window in pixels. + */ + public int getHeight() { + return mHeight; + } + + /** + * Returns the title associated with the window, if it has one. + */ + public CharSequence getTitle() { + return mTitle; + } + + /** + * Returns the ID of the display this window is on, for use with + * {@link android.hardware.display.DisplayManager#getDisplay DisplayManager.getDisplay()}. + */ + public int getDisplayId() { + return mDisplayId; + } + + /** + * Returns the {@link ViewNode} containing the root content of the window. + */ + public ViewNode getRootViewNode() { + return mRoot; + } + } + + /** + * Describes 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; + + int mId; + String mIdPackage; + String mIdType; + String mIdEntry; + int mX; + int mY; + int mScrollX; + int mScrollY; + int mWidth; + int mHeight; + + static final int FLAGS_DISABLED = 0x00000001; + static final int FLAGS_VISIBILITY_MASK = View.VISIBLE|View.INVISIBLE|View.GONE; + static final int FLAGS_FOCUSABLE = 0x00000010; + static final int FLAGS_FOCUSED = 0x00000020; + static final int FLAGS_ACCESSIBILITY_FOCUSED = 0x04000000; + static final int FLAGS_SELECTED = 0x00000040; + static final int FLAGS_ASSIST_BLOCKED = 0x00000080; + static final int FLAGS_ACTIVATED = 0x40000000; + static final int FLAGS_CHECKABLE = 0x00000100; + static final int FLAGS_CHECKED = 0x00000200; + static final int FLAGS_CLICKABLE = 0x00004000; + static final int FLAGS_LONG_CLICKABLE = 0x00200000; + static final int FLAGS_CONTEXT_CLICKABLE = 0x00400000; + + int mFlags; + + String mClassName; + CharSequence mContentDescription; + + ViewNodeText mText; + Bundle mExtras; + + ViewNode[] mChildren; + + ViewNode() { + } + + ViewNode(Parcel in, PooledStringReader preader) { + mId = in.readInt(); + if (mId != 0) { + mIdEntry = preader.readString(); + if (mIdEntry != null) { + mIdType = preader.readString(); + mIdPackage = preader.readString(); + } else { + mIdPackage = mIdType = null; + } + } else { + mIdPackage = mIdType = mIdEntry = null; + } + mX = in.readInt(); + mY = in.readInt(); + mScrollX = in.readInt(); + mScrollY = in.readInt(); + mWidth = in.readInt(); + mHeight = in.readInt(); + mFlags = in.readInt(); + mClassName = preader.readString(); + mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); + if (in.readInt() != 0) { + mText = new ViewNodeText(in); + } else { + mText = null; + } + mExtras = in.readBundle(); + final int NCHILDREN = in.readInt(); + if (NCHILDREN > 0) { + mChildren = new ViewNode[NCHILDREN]; + for (int i=0; i<NCHILDREN; i++) { + mChildren[i] = new ViewNode(in, preader); + } + } else { + mChildren = null; + } + } + + void writeToParcel(Parcel out, PooledStringWriter pwriter) { + out.writeInt(mId); + if (mId != 0) { + pwriter.writeString(mIdEntry); + if (mIdEntry != null) { + pwriter.writeString(mIdType); + pwriter.writeString(mIdPackage); + } + } + out.writeInt(mX); + out.writeInt(mY); + out.writeInt(mScrollX); + out.writeInt(mScrollY); + out.writeInt(mWidth); + out.writeInt(mHeight); + out.writeInt(mFlags); + pwriter.writeString(mClassName); + TextUtils.writeToParcel(mContentDescription, out, 0); + if (mText != null) { + out.writeInt(1); + mText.writeToParcel(out); + } else { + out.writeInt(0); + } + out.writeBundle(mExtras); + if (mChildren != null) { + final int NCHILDREN = mChildren.length; + out.writeInt(NCHILDREN); + for (int i=0; i<NCHILDREN; i++) { + mChildren[i].writeToParcel(out, pwriter); + } + } else { + out.writeInt(0); + } + } + + /** + * Returns the ID associated with this view, as per {@link View#getId() View.getId()}. + */ + public int getId() { + return mId; + } + + /** + * If {@link #getId()} is a resource identifier, this is the package name of that + * identifier. See {@link android.view.ViewStructure#setId ViewStructure.setId} + * for more information. + */ + public String getIdPackage() { + return mIdPackage; + } + + /** + * If {@link #getId()} is a resource identifier, this is the type name of that + * identifier. See {@link android.view.ViewStructure#setId ViewStructure.setId} + * for more information. + */ + public String getIdType() { + return mIdType; + } + + /** + * If {@link #getId()} is a resource identifier, this is the entry name of that + * identifier. See {@link android.view.ViewStructure#setId ViewStructure.setId} + * for more information. + */ + public String getIdEntry() { + return mIdEntry; + } + + /** + * Returns the left edge of this view, in pixels, relative to the left edge of its parent. + */ + public int getLeft() { + return mX; + } + + /** + * Returns the top edge of this view, in pixels, relative to the top edge of its parent. + */ + public int getTop() { + return mY; + } + + /** + * Returns the current X scroll offset of this view, as per + * {@link android.view.View#getScrollX() View.getScrollX()}. + */ + public int getScrollX() { + return mScrollX; + } + + /** + * Returns the current Y scroll offset of this view, as per + * {@link android.view.View#getScrollX() View.getScrollY()}. + */ + public int getScrollY() { + return mScrollY; + } + + /** + * Returns the width of this view, in pixels. + */ + public int getWidth() { + return mWidth; + } + + /** + * Returns the height of this view, in pixels. + */ + public int getHeight() { + return mHeight; + } + + /** + * Returns the visibility mode of this view, as per + * {@link android.view.View#getVisibility() View.getVisibility()}. + */ + public int getVisibility() { + return mFlags&ViewNode.FLAGS_VISIBILITY_MASK; + } + + /** + * Returns true if assist data has been blocked starting at this node in the hierarchy. + */ + public boolean isAssistBlocked() { + return (mFlags&ViewNode.FLAGS_ASSIST_BLOCKED) == 0; + } + + /** + * Returns true if this node is in an enabled state. + */ + public boolean isEnabled() { + return (mFlags&ViewNode.FLAGS_DISABLED) == 0; + } + + /** + * Returns true if this node is clickable by the user. + */ + public boolean isClickable() { + return (mFlags&ViewNode.FLAGS_CLICKABLE) != 0; + } + + /** + * Returns true if this node can take input focus. + */ + public boolean isFocusable() { + return (mFlags&ViewNode.FLAGS_FOCUSABLE) != 0; + } + + /** + * Returns true if this node currently had input focus at the time that the + * structure was collected. + */ + public boolean isFocused() { + return (mFlags&ViewNode.FLAGS_FOCUSED) != 0; + } + + /** + * Returns true if this node currently had accessibility focus at the time that the + * structure was collected. + */ + public boolean isAccessibilityFocused() { + return (mFlags&ViewNode.FLAGS_ACCESSIBILITY_FOCUSED) != 0; + } + + /** + * Returns true if this node represents something that is checkable by the user. + */ + public boolean isCheckable() { + return (mFlags&ViewNode.FLAGS_CHECKABLE) != 0; + } + + /** + * Returns true if this node is currently in a checked state. + */ + public boolean isChecked() { + return (mFlags&ViewNode.FLAGS_CHECKED) != 0; + } + + /** + * Returns true if this node has currently been selected by the user. + */ + public boolean isSelected() { + return (mFlags&ViewNode.FLAGS_SELECTED) != 0; + } + + /** + * Returns true if this node has currently been activated by the user. + */ + public boolean isActivated() { + return (mFlags&ViewNode.FLAGS_ACTIVATED) != 0; + } + + /** + * Returns true if this node is something the user can perform a long click/press on. + */ + public boolean isLongClickable() { + return (mFlags&ViewNode.FLAGS_LONG_CLICKABLE) != 0; + } + + /** + * Returns true if this node is something the user can perform a context click on. + */ + public boolean isContextClickable() { + return (mFlags&ViewNode.FLAGS_CONTEXT_CLICKABLE) != 0; + } + + /** + * Returns the class name of the node's implementation, indicating its behavior. + * For example, a button will report "android.widget.Button" meaning it behaves + * like a {@link android.widget.Button}. + */ + public String getClassName() { + return mClassName; + } + + /** + * Returns any content description associated with the node, which semantically describes + * its purpose for accessibility and other uses. + */ + public CharSequence getContentDescription() { + return mContentDescription; + } + + /** + * Returns any text associated with the node that is displayed to the user, or null + * if there is none. + */ + public CharSequence getText() { + return mText != null ? mText.mText : null; + } + + /** + * If {@link #getText()} is non-null, this is where the current selection starts. + */ + public int getTextSelectionStart() { + return mText != null ? mText.mTextSelectionStart : -1; + } + + /** + * If {@link #getText()} is non-null, this is where the current selection starts. + * If there is no selection, returns the same value as {@link #getTextSelectionStart()}, + * indicating the cursor position. + */ + public int getTextSelectionEnd() { + return mText != null ? mText.mTextSelectionEnd : -1; + } + + /** + * If {@link #getText()} is non-null, this is the main text color associated with it. + * If there is no text color, {@link #TEXT_COLOR_UNDEFINED} is returned. + * Note that the text may also contain style spans that modify the color of specific + * parts of the text. + */ + public int getTextColor() { + return mText != null ? mText.mTextColor : TEXT_COLOR_UNDEFINED; + } + + /** + * If {@link #getText()} is non-null, this is the main text background color associated + * with it. + * If there is no text background color, {@link #TEXT_COLOR_UNDEFINED} is returned. + * Note that the text may also contain style spans that modify the color of specific + * parts of the text. + */ + public int getTextBackgroundColor() { + return mText != null ? mText.mTextBackgroundColor : TEXT_COLOR_UNDEFINED; + } + + /** + * If {@link #getText()} is non-null, this is the main text size (in pixels) associated + * with it. + * Note that the text may also contain style spans that modify the size of specific + * parts of the text. + */ + public float getTextSize() { + return mText != null ? mText.mTextSize : 0; + } + + /** + * If {@link #getText()} is non-null, this is the main text style associated + * with it, containing a bit mask of {@link #TEXT_STYLE_BOLD}, + * {@link #TEXT_STYLE_BOLD}, {@link #TEXT_STYLE_STRIKE_THRU}, and/or + * {@link #TEXT_STYLE_UNDERLINE}. + * Note that the text may also contain style spans that modify the style of specific + * parts of the text. + */ + public int getTextStyle() { + return mText != null ? mText.mTextStyle : 0; + } + + /** + * Return additional hint text associated with the node; this is typically used with + * a node that takes user input, describing to the user what the input means. + */ + public String getHint() { + return mText != null ? mText.mHint : null; + } + + /** + * Return a Bundle containing optional vendor-specific extension information. + */ + public Bundle getExtras() { + return mExtras; + } + + /** + * Return the number of children this node has. + */ + public int getChildCount() { + return mChildren != null ? mChildren.length : 0; + } + + /** + * Return a child of this node, given an index value from 0 to + * {@link #getChildCount()}-1. + */ + public ViewNode getChildAt(int index) { + return mChildren[index]; + } + } + + static class ViewNodeBuilder extends ViewAssistStructure { + final AssistStructure mAssist; + final ViewNode mNode; + final boolean mAsync; + + ViewNodeBuilder(AssistStructure assist, ViewNode node, boolean async) { + mAssist = assist; + mNode = node; + mAsync = async; + } + + @Override + public void setId(int id, String packageName, String typeName, String entryName) { + mNode.mId = id; + mNode.mIdPackage = packageName; + mNode.mIdType = typeName; + mNode.mIdEntry = entryName; + } + + @Override + public void setDimens(int left, int top, int scrollX, int scrollY, int width, int height) { + mNode.mX = left; + mNode.mY = top; + mNode.mScrollX = scrollX; + mNode.mScrollY = scrollY; + mNode.mWidth = width; + mNode.mHeight = height; + } + + @Override + public void setVisibility(int visibility) { + mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_VISIBILITY_MASK) | visibility; + } + + @Override + public void setAssistBlocked(boolean state) { + mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ASSIST_BLOCKED) + | (state ? 0 : ViewNode.FLAGS_ASSIST_BLOCKED); + } + + @Override + public void setEnabled(boolean state) { + mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_DISABLED) + | (state ? 0 : ViewNode.FLAGS_DISABLED); + } + + @Override + public void setClickable(boolean state) { + mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CLICKABLE) + | (state ? ViewNode.FLAGS_CLICKABLE : 0); + } + + @Override + public void setLongClickable(boolean state) { + mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_LONG_CLICKABLE) + | (state ? ViewNode.FLAGS_LONG_CLICKABLE : 0); + } + + @Override + public void setContextClickable(boolean state) { + mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CONTEXT_CLICKABLE) + | (state ? ViewNode.FLAGS_CONTEXT_CLICKABLE : 0); + } + + @Override + public void setFocusable(boolean state) { + mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSABLE) + | (state ? ViewNode.FLAGS_FOCUSABLE : 0); + } + + @Override + public void setFocused(boolean state) { + mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSED) + | (state ? ViewNode.FLAGS_FOCUSED : 0); + } + + @Override + public void setAccessibilityFocused(boolean state) { + mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ACCESSIBILITY_FOCUSED) + | (state ? ViewNode.FLAGS_ACCESSIBILITY_FOCUSED : 0); + } + + @Override + public void setCheckable(boolean state) { + mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CHECKABLE) + | (state ? ViewNode.FLAGS_CHECKABLE : 0); + } + + @Override + public void setChecked(boolean state) { + mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CHECKED) + | (state ? ViewNode.FLAGS_CHECKED : 0); + } + + @Override + public void setSelected(boolean state) { + mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_SELECTED) + | (state ? ViewNode.FLAGS_SELECTED : 0); + } + + @Override + public void setActivated(boolean state) { + mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ACTIVATED) + | (state ? ViewNode.FLAGS_ACTIVATED : 0); + } + + @Override + public void setClassName(String className) { + mNode.mClassName = className; + } + + @Override + public void setContentDescription(CharSequence contentDescription) { + mNode.mContentDescription = contentDescription; + } + + private final ViewNodeText getNodeText() { + if (mNode.mText != null) { + return mNode.mText; + } + mNode.mText = new ViewNodeText(); + return mNode.mText; + } + + @Override + public void setText(CharSequence text) { + ViewNodeText t = getNodeText(); + t.mText = text; + t.mTextSelectionStart = t.mTextSelectionEnd = -1; + } + + @Override + public void setText(CharSequence text, int selectionStart, int selectionEnd) { + ViewNodeText t = getNodeText(); + t.mText = text; + t.mTextSelectionStart = selectionStart; + t.mTextSelectionEnd = selectionEnd; + } + + @Override + public void setTextStyle(float size, int fgColor, int bgColor, int style) { + ViewNodeText t = getNodeText(); + t.mTextColor = fgColor; + t.mTextBackgroundColor = bgColor; + t.mTextSize = size; + t.mTextStyle = style; + } + + @Override + public void setHint(CharSequence hint) { + getNodeText().mHint = hint != null ? hint.toString() : null; + } + + @Override + public CharSequence getText() { + return mNode.mText != null ? mNode.mText.mText : null; + } + + @Override + public int getTextSelectionStart() { + return mNode.mText != null ? mNode.mText.mTextSelectionStart : -1; + } + + @Override + public int getTextSelectionEnd() { + return mNode.mText != null ? mNode.mText.mTextSelectionEnd : -1; + } + + @Override + public CharSequence getHint() { + return mNode.mText != null ? mNode.mText.mHint : null; + } + + @Override + public Bundle getExtras() { + if (mNode.mExtras != null) { + return mNode.mExtras; + } + mNode.mExtras = new Bundle(); + return mNode.mExtras; + } + + @Override + public boolean hasExtras() { + return mNode.mExtras != null; + } + + @Override + public void setChildCount(int num) { + mNode.mChildren = new ViewNode[num]; + } + + @Override + public int addChildCount(int num) { + if (mNode.mChildren == null) { + setChildCount(num); + return 0; + } + final int start = mNode.mChildren.length; + ViewNode[] newArray = new ViewNode[start + num]; + System.arraycopy(mNode.mChildren, 0, newArray, 0, start); + mNode.mChildren = newArray; + return start; + } + + @Override + public int getChildCount() { + return mNode.mChildren != null ? mNode.mChildren.length : 0; + } + + @Override + public ViewAssistStructure newChild(int index) { + ViewNode node = new ViewNode(); + mNode.mChildren[index] = node; + return new ViewNodeBuilder(mAssist, node, false); + } + + @Override + public ViewAssistStructure asyncNewChild(int index) { + synchronized (mAssist) { + ViewNode node = new ViewNode(); + mNode.mChildren[index] = node; + ViewNodeBuilder builder = new ViewNodeBuilder(mAssist, node, true); + mAssist.mPendingAsyncChildren.add(builder); + return builder; + } + } + + @Override + public void asyncCommit() { + synchronized (mAssist) { + if (!mAsync) { + throw new IllegalStateException("Child " + this + + " was not created with ViewAssistStructure.asyncNewChild"); + } + if (!mAssist.mPendingAsyncChildren.remove(this)) { + throw new IllegalStateException("Child " + this + " already committed"); + } + mAssist.notifyAll(); + } + } + + @Override + public Rect getTempRect() { + return mAssist.mTmpRect; + } } /** @hide */ public AssistStructure(Activity activity) { - super(activity); + mHaveData = true; + mActivityComponent = activity.getComponentName(); + ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews( + activity.getActivityToken()); + for (int i=0; i<views.size(); i++) { + ViewRootImpl root = views.get(i); + mWindowNodes.add(new WindowNode(this, root)); + } + } + + public AssistStructure() { + mHaveData = true; + mActivityComponent = null; } - AssistStructure(Parcel in) { - super(in); + /** @hide */ + public AssistStructure(Parcel in) { + mReceiveChannel = in.readStrongBinder(); } + /** @hide */ + public void dump() { + Log.i(TAG, "Activity: " + mActivityComponent.flattenToShortString()); + final int N = getWindowNodeCount(); + for (int i=0; i<N; i++) { + WindowNode node = getWindowNodeAt(i); + Log.i(TAG, "Window #" + i + " [" + node.getLeft() + "," + node.getTop() + + " " + node.getWidth() + "x" + node.getHeight() + "]" + " " + node.getTitle()); + dump(" ", node.getRootViewNode()); + } + } + + void dump(String prefix, ViewNode node) { + Log.i(TAG, prefix + "View [" + node.getLeft() + "," + node.getTop() + + " " + node.getWidth() + "x" + node.getHeight() + "]" + " " + node.getClassName()); + int id = node.getId(); + if (id != 0) { + StringBuilder sb = new StringBuilder(); + sb.append(prefix); sb.append(" ID: #"); sb.append(Integer.toHexString(id)); + String entry = node.getIdEntry(); + if (entry != null) { + String type = node.getIdType(); + String pkg = node.getIdPackage(); + sb.append(" "); sb.append(pkg); sb.append(":"); sb.append(type); + sb.append("/"); sb.append(entry); + } + Log.i(TAG, sb.toString()); + } + int scrollX = node.getScrollX(); + int scrollY = node.getScrollY(); + if (scrollX != 0 || scrollY != 0) { + Log.i(TAG, prefix + " Scroll: " + scrollX + "," + scrollY); + } + CharSequence contentDescription = node.getContentDescription(); + if (contentDescription != null) { + Log.i(TAG, prefix + " Content description: " + contentDescription); + } + 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) { + Log.i(TAG, prefix + " Hint: " + hint); + } + Bundle extras = node.getExtras(); + if (extras != null) { + Log.i(TAG, prefix + " Extras: " + extras); + } + final int NCHILDREN = node.getChildCount(); + if (NCHILDREN > 0) { + Log.i(TAG, prefix + " Children:"); + String cprefix = prefix + " "; + for (int i=0; i<NCHILDREN; i++) { + ViewNode cnode = node.getChildAt(i); + dump(cprefix, cnode); + } + } + } + + /** + * Return the activity this AssistStructure came from. + */ + public ComponentName getActivityComponent() { + ensureData(); + return mActivityComponent; + } + + /** + * Return the number of window contents that have been collected in this assist data. + */ + public int getWindowNodeCount() { + ensureData(); + return mWindowNodes.size(); + } + + /** + * Return one of the windows in the assist data. + * @param index Which window to retrieve, may be 0 to {@link #getWindowNodeCount()}-1. + */ public WindowNode getWindowNodeAt(int index) { - return super.getWindowNodeAt(index); + ensureData(); + return mWindowNodes.get(index); + } + + /** @hide */ + public void ensureData() { + if (mHaveData) { + return; + } + mHaveData = true; + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(DESCRIPTOR); + try { + mReceiveChannel.transact(TRANSACTION_XFER, data, reply, 0); + } catch (RemoteException e) { + Log.w(TAG, "Failure reading AssistStructure data", e); + return; + } + readContentFromParcel(reply); + data.recycle(); + reply.recycle(); + } + + void writeContentToParcel(Parcel out, int flags) { + // First make sure all content has been created. + boolean skipStructure = false; + synchronized (this) { + long endTime = SystemClock.uptimeMillis() + 5000; + long now; + while (mPendingAsyncChildren.size() > 0 && (now=SystemClock.uptimeMillis()) < endTime) { + try { + wait(endTime-now); + } catch (InterruptedException e) { + } + } + if (mPendingAsyncChildren.size() > 0) { + // We waited too long, assume none of the assist structure is valid. + skipStructure = true; + } + } + int start = out.dataPosition(); + PooledStringWriter pwriter = new PooledStringWriter(out); + ComponentName.writeToParcel(mActivityComponent, out); + final int N = skipStructure ? 0 : mWindowNodes.size(); + out.writeInt(N); + for (int i=0; i<N; i++) { + mWindowNodes.get(i).writeToParcel(out, pwriter); + } + pwriter.finish(); + Log.i(TAG, "Flattened assist data: " + (out.dataPosition() - start) + " bytes"); + } + + void readContentFromParcel(Parcel in) { + PooledStringReader preader = new PooledStringReader(in); + mActivityComponent = ComponentName.readFromParcel(in); + final int N = in.readInt(); + for (int i=0; i<N; i++) { + mWindowNodes.add(new WindowNode(in, preader)); + } + //dump(); } public int describeContents() { diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java index 39dd29b..f9e216a 100644 --- a/core/java/android/service/voice/VoiceInteractionSession.java +++ b/core/java/android/service/voice/VoiceInteractionSession.java @@ -1146,20 +1146,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall mContentFrame.requestApplyInsets(); } - /** @hide */ - public void onHandleAssist(Bundle assistBundle) { - } - public void onHandleAssist(Bundle data, AssistStructure structure, AssistContent content) { - if (data != null) { - Bundle assistContext = data.getBundle(Intent.EXTRA_ASSIST_CONTEXT); - if (assistContext != null) { - assistContext.putParcelable(AssistStructure.ASSIST_KEY, structure); - assistContext.putParcelable(AssistContent.ASSIST_KEY, content); - data.putBundle(Intent.EXTRA_ASSIST_CONTEXT, assistContext); - } - } - onHandleAssist(data); } public void onHandleScreenshot(Bitmap screenshot) { diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java index d06cd83..3572f1e 100644 --- a/core/java/android/view/ViewStructure.java +++ b/core/java/android/view/ViewStructure.java @@ -150,7 +150,7 @@ public abstract class ViewStructure { * @param size The size, in pixels, of the text. * @param fgColor The foreground color, packed as 0xAARRGGBB. * @param bgColor The background color, packed as 0xAARRGGBB. - * @param style Style flags, as defined by {@link android.app.AssistStructure.ViewNode}. + * @param style Style flags, as defined by {@link android.app.assist.AssistStructure.ViewNode}. */ public abstract void setTextStyle(float size, int fgColor, int bgColor, int style); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index f733eab..f20f8d0 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -25,7 +25,7 @@ import android.annotation.StringRes; import android.annotation.StyleRes; import android.annotation.XmlRes; import android.app.Activity; -import android.app.AssistStructure; +import android.app.assist.AssistStructure; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java index 8a72341..439ace8 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.AssistStructure; +import android.app.assist.AssistStructure; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java index 3090a11..90a781c 100644 --- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java +++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java @@ -18,8 +18,8 @@ package com.android.test.voiceinteraction; import android.app.ActivityManager; import android.app.VoiceInteractor; -import android.app.AssistContent; -import android.app.AssistStructure; +import android.app.assist.AssistContent; +import android.app.assist.AssistStructure; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; @@ -123,34 +123,8 @@ public class MainInteractionSession extends VoiceInteractionSession } public void onHandleAssist(Bundle assistBundle) { - boolean hasStructure = false; - if (assistBundle != null) { - Bundle assistContext = assistBundle.getBundle(Intent.EXTRA_ASSIST_CONTEXT); - if (assistContext != null) { - mAssistStructure = AssistStructure.getAssistStructure(assistContext); - if (mAssistStructure != null) { - if (mAssistVisualizer != null) { - mAssistVisualizer.setAssistStructure(mAssistStructure); - hasStructure = true; - } - } - AssistContent content = AssistContent.getAssistContent(assistContext); - if (content != null) { - Log.i(TAG, "Assist intent: " + content.getIntent()); - Log.i(TAG, "Assist clipdata: " + content.getClipData()); - } - } - Uri referrer = assistBundle.getParcelable(Intent.EXTRA_REFERRER); - if (referrer != null) { - Log.i(TAG, "Referrer: " + referrer); - } - } - if (!hasStructure && mAssistVisualizer != null) { - mAssistVisualizer.clearAssistData(); - } } - /* @Override public void onHandleAssist(Bundle data, AssistStructure structure, AssistContent content) { mAssistStructure = structure; @@ -158,13 +132,22 @@ public class MainInteractionSession extends VoiceInteractionSession if (mAssistVisualizer != null) { mAssistVisualizer.setAssistStructure(mAssistStructure); } + } else { + if (mAssistVisualizer != null) { + mAssistVisualizer.clearAssistData(); + } } if (content != null) { Log.i(TAG, "Assist intent: " + content.getIntent()); Log.i(TAG, "Assist clipdata: " + content.getClipData()); } + if (data != null) { + Uri referrer = data.getParcelable(Intent.EXTRA_REFERRER); + if (referrer != null) { + Log.i(TAG, "Referrer: " + referrer); + } + } } - */ @Override public void onHandleScreenshot(Bitmap screenshot) { diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java index c038414..943c647 100644 --- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java +++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java @@ -16,6 +16,7 @@ package com.android.test.voiceinteraction; +import android.annotation.Nullable; import android.app.Activity; import android.app.VoiceInteractor; import android.content.ComponentName; @@ -111,38 +112,10 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis @Override public void onClick(View v) { if (v == mAbortButton) { - VoiceInteractor.AbortVoiceRequest req = new VoiceInteractor.AbortVoiceRequest( - new VoiceInteractor.Prompt("Dammit, we suck :("), null) { - @Override - public void onCancel() { - Log.i(TAG, "Canceled!"); - mLog.append("Canceled abort\n"); - } - - @Override - public void onAbortResult(Bundle result) { - Log.i(TAG, "Abort result: result=" + result); - mLog.append("Abort: result=" + result + "\n"); - getActivity().finish(); - } - }; + VoiceInteractor.AbortVoiceRequest req = new TestAbortVoice(); mInteractor.submitRequest(req, REQUEST_ABORT); } else if (v == mCompleteButton) { - VoiceInteractor.CompleteVoiceRequest req = new VoiceInteractor.CompleteVoiceRequest( - new VoiceInteractor.Prompt("Woohoo, completed!"), null) { - @Override - public void onCancel() { - Log.i(TAG, "Canceled!"); - mLog.append("Canceled complete\n"); - } - - @Override - public void onCompleteResult(Bundle result) { - Log.i(TAG, "Complete result: result=" + result); - mLog.append("Complete: result=" + result + "\n"); - getActivity().finish(); - } - }; + VoiceInteractor.CompleteVoiceRequest req = new TestCompleteVoice(); mInteractor.submitRequest(req, REQUEST_COMPLETE); } else if (v == mPickButton) { VoiceInteractor.PickOptionRequest.Option[] options = @@ -152,36 +125,7 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis options[2] = new VoiceInteractor.PickOptionRequest.Option("Three"); options[3] = new VoiceInteractor.PickOptionRequest.Option("Four"); options[4] = new VoiceInteractor.PickOptionRequest.Option("Five"); - VoiceInteractor.PickOptionRequest req = new VoiceInteractor.PickOptionRequest( - new VoiceInteractor.Prompt("Need to pick something"), options, null) { - @Override - public void onCancel() { - Log.i(TAG, "Canceled!"); - mLog.append("Canceled pick\n"); - } - - @Override - public void onPickOptionResult(boolean finished, Option[] selections, Bundle result) { - Log.i(TAG, "Pick result: finished=" + finished + " selections=" + selections - + " result=" + result); - StringBuilder sb = new StringBuilder(); - if (finished) { - sb.append("Pick final result: "); - } else { - sb.append("Pick intermediate result: "); - } - for (int i=0; i<selections.length; i++) { - if (i >= 1) { - sb.append(", "); - } - sb.append(selections[i].getLabel()); - } - mLog.append(sb.toString()); - if (finished) { - getActivity().finish(); - } - } - }; + VoiceInteractor.PickOptionRequest req = new TestPickOption(options); mInteractor.submitRequest(req, REQUEST_PICK); } else if (v == mJumpOutButton) { Log.i(TAG, "Jump out"); @@ -200,4 +144,66 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis public void onDestroy() { super.onDestroy(); } + + static class TestAbortVoice extends VoiceInteractor.AbortVoiceRequest { + public TestAbortVoice() { + super(new VoiceInteractor.Prompt("Dammit, we suck :("), null); + } + @Override public void onCancel() { + Log.i(TAG, "Canceled!"); + ((TestInteractionActivity)getActivity()).mLog.append("Canceled abort\n"); + } + @Override public void onAbortResult(Bundle result) { + Log.i(TAG, "Abort result: result=" + result); + ((TestInteractionActivity)getActivity()).mLog.append("Abort: result=" + result + "\n"); + getActivity().finish(); + } + } + + static class TestCompleteVoice extends VoiceInteractor.CompleteVoiceRequest { + public TestCompleteVoice() { + super(new VoiceInteractor.Prompt("Woohoo, completed!"), null); + } + @Override public void onCancel() { + Log.i(TAG, "Canceled!"); + ((TestInteractionActivity)getActivity()).mLog.append("Canceled complete\n"); + } + @Override public void onCompleteResult(Bundle result) { + Log.i(TAG, "Complete result: result=" + result); + ((TestInteractionActivity)getActivity()).mLog.append("Complete: result=" + + result + "\n"); + getActivity().finish(); + } + } + + static class TestPickOption extends VoiceInteractor.PickOptionRequest { + public TestPickOption(Option[] options) { + super(new VoiceInteractor.Prompt("Need to pick something"), options, null); + } + @Override public void onCancel() { + Log.i(TAG, "Canceled!"); + ((TestInteractionActivity)getActivity()).mLog.append("Canceled pick\n"); + } + @Override + public void onPickOptionResult(boolean finished, Option[] selections, Bundle result) { + Log.i(TAG, "Pick result: finished=" + finished + " selections=" + selections + + " result=" + result); + StringBuilder sb = new StringBuilder(); + if (finished) { + sb.append("Pick final result: "); + } else { + sb.append("Pick intermediate result: "); + } + for (int i=0; i<selections.length; i++) { + if (i >= 1) { + sb.append(", "); + } + sb.append(selections[i].getLabel()); + } + ((TestInteractionActivity)getActivity()).mLog.append(sb.toString()); + if (finished) { + getActivity().finish(); + } + } + } } |