diff options
-rw-r--r-- | api/current.txt | 24 | ||||
-rw-r--r-- | api/system-current.txt | 24 | ||||
-rw-r--r-- | core/java/android/app/AssistStructure.java | 444 | ||||
-rw-r--r-- | core/java/android/view/View.java | 140 | ||||
-rw-r--r-- | core/java/android/view/ViewAssistStructure.java | 43 | ||||
-rw-r--r-- | core/java/android/view/ViewGroup.java | 27 | ||||
-rw-r--r-- | core/java/android/widget/Switch.java | 4 | ||||
-rw-r--r-- | core/java/android/widget/TextView.java | 4 | ||||
-rw-r--r-- | tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java | 10 | ||||
-rw-r--r-- | tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java | 1 |
10 files changed, 507 insertions, 214 deletions
diff --git a/api/current.txt b/api/current.txt index ce6bbfa..6890968 100644 --- a/api/current.txt +++ b/api/current.txt @@ -34511,6 +34511,7 @@ package android.view { method public boolean dispatchNestedPreScroll(int, int, int[], int[]); method public boolean dispatchNestedScroll(int, int, int, int, int[]); method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent); + method public void dispatchProvideAssistStructure(android.view.ViewAssistStructure); method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>); method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>); method protected void dispatchSetActivated(boolean); @@ -34767,7 +34768,8 @@ package android.view { method protected void onMeasure(int, int); method protected void onOverScrolled(int, int, boolean, boolean); method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent); - method public void onProvideAssistStructure(android.view.ViewAssistStructure, android.os.Bundle); + method public void onProvideAssistStructure(android.view.ViewAssistStructure); + method public void onProvideVirtualAssistStructure(android.view.ViewAssistStructure); method protected void onRestoreInstanceState(android.os.Parcelable); method public void onRtlPropertiesChanged(int); method protected android.os.Parcelable onSaveInstanceState(); @@ -35177,14 +35179,34 @@ package android.view { public abstract class ViewAssistStructure { ctor public ViewAssistStructure(); + method public abstract void clearExtras(); + method public abstract android.os.Bundle editExtras(); + method public abstract int getChildCount(); method public abstract java.lang.CharSequence getHint(); method public abstract java.lang.CharSequence getText(); method public abstract int getTextSelectionEnd(); method public abstract int getTextSelectionStart(); + method public abstract android.view.ViewAssistStructure newChild(int); + method public abstract void setAccessibilityFocused(boolean); + method public abstract void setActivated(boolean); + method public abstract void setCheckable(boolean); + method public abstract void setChecked(boolean); + method public abstract void setChildCount(int); + method public abstract void setClassName(java.lang.String); + method public abstract void setClickable(boolean); + method public abstract void setContentDescription(java.lang.CharSequence); + method public abstract void setDimens(int, int, int, int, int, int); + method public abstract void setEnabled(boolean); + method public abstract void setFocusable(boolean); + method public abstract void setFocused(boolean); method public abstract void setHint(java.lang.CharSequence); + method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String); + method public abstract void setLongClickable(boolean); + method public abstract void setSelected(boolean); method public abstract void setText(java.lang.CharSequence); method public abstract void setText(java.lang.CharSequence, int, int); method public abstract void setTextPaint(android.text.TextPaint); + method public abstract void setVisibility(int); } public class ViewConfiguration { diff --git a/api/system-current.txt b/api/system-current.txt index 6053603..b5b7c05 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -37053,6 +37053,7 @@ package android.view { method public boolean dispatchNestedPreScroll(int, int, int[], int[]); method public boolean dispatchNestedScroll(int, int, int, int, int[]); method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent); + method public void dispatchProvideAssistStructure(android.view.ViewAssistStructure); method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>); method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>); method protected void dispatchSetActivated(boolean); @@ -37309,7 +37310,8 @@ package android.view { method protected void onMeasure(int, int); method protected void onOverScrolled(int, int, boolean, boolean); method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent); - method public void onProvideAssistStructure(android.view.ViewAssistStructure, android.os.Bundle); + method public void onProvideAssistStructure(android.view.ViewAssistStructure); + method public void onProvideVirtualAssistStructure(android.view.ViewAssistStructure); method protected void onRestoreInstanceState(android.os.Parcelable); method public void onRtlPropertiesChanged(int); method protected android.os.Parcelable onSaveInstanceState(); @@ -37719,14 +37721,34 @@ package android.view { public abstract class ViewAssistStructure { ctor public ViewAssistStructure(); + method public abstract void clearExtras(); + method public abstract android.os.Bundle editExtras(); + method public abstract int getChildCount(); method public abstract java.lang.CharSequence getHint(); method public abstract java.lang.CharSequence getText(); method public abstract int getTextSelectionEnd(); method public abstract int getTextSelectionStart(); + method public abstract android.view.ViewAssistStructure newChild(int); + method public abstract void setAccessibilityFocused(boolean); + method public abstract void setActivated(boolean); + method public abstract void setCheckable(boolean); + method public abstract void setChecked(boolean); + method public abstract void setChildCount(int); + method public abstract void setClassName(java.lang.String); + method public abstract void setClickable(boolean); + method public abstract void setContentDescription(java.lang.CharSequence); + method public abstract void setDimens(int, int, int, int, int, int); + method public abstract void setEnabled(boolean); + method public abstract void setFocusable(boolean); + method public abstract void setFocused(boolean); method public abstract void setHint(java.lang.CharSequence); + method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String); + method public abstract void setLongClickable(boolean); + method public abstract void setSelected(boolean); method public abstract void setText(java.lang.CharSequence); method public abstract void setText(java.lang.CharSequence, int, int); method public abstract void setTextPaint(android.text.TextPaint); + method public abstract void setVisibility(int); } public class ViewConfiguration { diff --git a/core/java/android/app/AssistStructure.java b/core/java/android/app/AssistStructure.java index c435ccb..e31c821 100644 --- a/core/java/android/app/AssistStructure.java +++ b/core/java/android/app/AssistStructure.java @@ -17,7 +17,6 @@ package android.app; import android.content.ComponentName; -import android.content.res.Resources; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.Typeface; @@ -31,10 +30,8 @@ import android.text.TextUtils; import android.util.Log; import android.view.View; import android.view.ViewAssistStructure; -import android.view.ViewGroup; import android.view.ViewRootImpl; import android.view.WindowManagerGlobal; -import android.widget.Checkable; import java.util.ArrayList; @@ -56,107 +53,22 @@ final public class AssistStructure implements Parcelable { final ArrayList<WindowNode> mWindowNodes = new ArrayList<>(); - ViewAssistStructureImpl mTmpViewAssistStructureImpl = new ViewAssistStructureImpl(); - Bundle mTmpExtras = new Bundle(); + Rect mTmpRect = new Rect(); - final static class ViewAssistStructureImpl extends ViewAssistStructure { + final static class ViewNodeText { CharSequence mText; - int mTextSelectionStart = -1; - int mTextSelectionEnd = -1; - int mTextColor = ViewNode.TEXT_COLOR_UNDEFINED; - int mTextBackgroundColor = ViewNode.TEXT_COLOR_UNDEFINED; - float mTextSize = 0; - int mTextStyle = 0; - CharSequence mHint; - - @Override - public void setText(CharSequence text) { - mText = text; - mTextSelectionStart = mTextSelectionEnd = -1; - } - - @Override - public void setText(CharSequence text, int selectionStart, int selectionEnd) { - mText = text; - mTextSelectionStart = selectionStart; - mTextSelectionEnd = selectionEnd; - } - - @Override - public void setTextPaint(TextPaint paint) { - mTextColor = paint.getColor(); - mTextBackgroundColor = paint.bgColor; - mTextSize = paint.getTextSize(); - mTextStyle = 0; - Typeface tf = paint.getTypeface(); - if (tf != null) { - if (tf.isBold()) { - mTextStyle |= ViewNode.TEXT_STYLE_BOLD; - } - if (tf.isItalic()) { - mTextStyle |= ViewNode.TEXT_STYLE_ITALIC; - } - } - int pflags = paint.getFlags(); - if ((pflags& Paint.FAKE_BOLD_TEXT_FLAG) != 0) { - mTextStyle |= ViewNode.TEXT_STYLE_BOLD; - } - if ((pflags& Paint.UNDERLINE_TEXT_FLAG) != 0) { - mTextStyle |= ViewNode.TEXT_STYLE_UNDERLINE; - } - if ((pflags& Paint.STRIKE_THRU_TEXT_FLAG) != 0) { - mTextStyle |= ViewNode.TEXT_STYLE_STRIKE_THRU; - } - } - - @Override - public void setHint(CharSequence hint) { - mHint = hint; - } - - @Override - public CharSequence getText() { - return mText; - } - - @Override - public int getTextSelectionStart() { - return mTextSelectionStart; - } - - @Override - public int getTextSelectionEnd() { - return mTextSelectionEnd; - } - - @Override - public CharSequence getHint() { - return mHint; - } - } - - final static class ViewNodeTextImpl { - final CharSequence mText; - final int mTextSelectionStart; - final int mTextSelectionEnd; + int mTextSelectionStart; + int mTextSelectionEnd; int mTextColor; int mTextBackgroundColor; float mTextSize; int mTextStyle; - final String mHint; + String mHint; - ViewNodeTextImpl(ViewAssistStructureImpl data) { - mText = data.mText; - mTextSelectionStart = data.mTextSelectionStart; - mTextSelectionEnd = data.mTextSelectionEnd; - mTextColor = data.mTextColor; - mTextBackgroundColor = data.mTextBackgroundColor; - mTextSize = data.mTextSize; - mTextStyle = data.mTextStyle; - mHint = data.mHint != null ? data.mHint.toString() : null; + ViewNodeText() { } - ViewNodeTextImpl(Parcel in) { + ViewNodeText(Parcel in) { mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); mTextSelectionStart = in.readInt(); mTextSelectionEnd = in.readInt(); @@ -199,7 +111,9 @@ final public class AssistStructure implements Parcelable { mWidth = rect.width(); mHeight = rect.height(); mTitle = root.getTitle(); - mRoot = new ViewNode(assist, view); + mRoot = new ViewNode(); + ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot); + view.dispatchProvideAssistStructure(builder); } WindowNode(Parcel in, PooledStringReader preader) { @@ -260,16 +174,16 @@ final public class AssistStructure implements Parcelable { public static final int TEXT_STYLE_UNDERLINE = 1<<2; public static final int TEXT_STYLE_STRIKE_THRU = 1<<3; - final int mId; - final String mIdPackage; - final String mIdType; - final String mIdEntry; - final int mX; - final int mY; - final int mScrollX; - final int mScrollY; - final int mWidth; - final int mHeight; + 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; @@ -283,104 +197,17 @@ final public class AssistStructure implements Parcelable { static final int FLAGS_CLICKABLE = 0x00004000; static final int FLAGS_LONG_CLICKABLE = 0x00200000; - final int mFlags; + int mFlags; - final String mClassName; - final CharSequence mContentDescription; + String mClassName; + CharSequence mContentDescription; - final ViewNodeTextImpl mText; - final Bundle mExtras; + ViewNodeText mText; + Bundle mExtras; - final ViewNode[] mChildren; + ViewNode[] mChildren; - ViewNode(AssistStructure assistStructure, View view) { - mId = view.getId(); - if (mId > 0 && (mId&0xff000000) != 0 && (mId&0x00ff0000) != 0 - && (mId&0x0000ffff) != 0) { - String pkg, type, entry; - try { - Resources res = view.getResources(); - entry = res.getResourceEntryName(mId); - type = res.getResourceTypeName(mId); - pkg = res.getResourcePackageName(mId); - } catch (Resources.NotFoundException e) { - entry = type = pkg = null; - } - mIdPackage = pkg; - mIdType = type; - mIdEntry = entry; - } else { - mIdPackage = mIdType = mIdEntry = null; - } - mX = view.getLeft(); - mY = view.getTop(); - mScrollX = view.getScrollX(); - mScrollY = view.getScrollY(); - mWidth = view.getWidth(); - mHeight = view.getHeight(); - int flags = view.getVisibility(); - if (!view.isEnabled()) { - flags |= FLAGS_DISABLED; - } - if (!view.isClickable()) { - flags |= FLAGS_CLICKABLE; - } - if (!view.isFocusable()) { - flags |= FLAGS_FOCUSABLE; - } - if (!view.isFocused()) { - flags |= FLAGS_FOCUSED; - } - if (!view.isAccessibilityFocused()) { - flags |= FLAGS_ACCESSIBILITY_FOCUSED; - } - if (!view.isSelected()) { - flags |= FLAGS_SELECTED; - } - if (!view.isActivated()) { - flags |= FLAGS_ACTIVATED; - } - if (!view.isLongClickable()) { - flags |= FLAGS_LONG_CLICKABLE; - } - if (view instanceof Checkable) { - flags |= FLAGS_CHECKABLE; - if (((Checkable)view).isChecked()) { - flags |= FLAGS_CHECKED; - } - } - mFlags = flags; - mClassName = view.getAccessibilityClassName().toString(); - mContentDescription = view.getContentDescription(); - final ViewAssistStructureImpl viewData = assistStructure.mTmpViewAssistStructureImpl; - final Bundle extras = assistStructure.mTmpExtras; - view.onProvideAssistStructure(viewData, extras); - if (viewData.mText != null || viewData.mHint != null) { - mText = new ViewNodeTextImpl(viewData); - assistStructure.mTmpViewAssistStructureImpl = new ViewAssistStructureImpl(); - } else { - mText = null; - } - if (!extras.isEmpty()) { - mExtras = extras; - assistStructure.mTmpExtras = new Bundle(); - } else { - mExtras = null; - } - if (view instanceof ViewGroup) { - ViewGroup vg = (ViewGroup)view; - final int NCHILDREN = vg.getChildCount(); - if (NCHILDREN > 0) { - mChildren = new ViewNode[NCHILDREN]; - for (int i=0; i<NCHILDREN; i++) { - mChildren[i] = new ViewNode(assistStructure, vg.getChildAt(i)); - } - } else { - mChildren = null; - } - } else { - mChildren = null; - } + ViewNode() { } ViewNode(Parcel in, PooledStringReader preader) { @@ -406,7 +233,7 @@ final public class AssistStructure implements Parcelable { mClassName = preader.readString(); mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); if (in.readInt() != 0) { - mText = new ViewNodeTextImpl(in); + mText = new ViewNodeText(in); } else { mText = null; } @@ -595,6 +422,221 @@ final public class AssistStructure implements Parcelable { } } + static class ViewNodeBuilder extends ViewAssistStructure { + final AssistStructure mAssist; + final ViewNode mNode; + + ViewNodeBuilder(AssistStructure assist, ViewNode node) { + mAssist = assist; + mNode = node; + } + + @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 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 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 setTextPaint(TextPaint paint) { + ViewNodeText t = getNodeText(); + t.mTextColor = paint.getColor(); + t.mTextBackgroundColor = paint.bgColor; + t.mTextSize = paint.getTextSize(); + t.mTextStyle = 0; + Typeface tf = paint.getTypeface(); + if (tf != null) { + if (tf.isBold()) { + t.mTextStyle |= ViewNode.TEXT_STYLE_BOLD; + } + if (tf.isItalic()) { + t.mTextStyle |= ViewNode.TEXT_STYLE_ITALIC; + } + } + int pflags = paint.getFlags(); + if ((pflags& Paint.FAKE_BOLD_TEXT_FLAG) != 0) { + t.mTextStyle |= ViewNode.TEXT_STYLE_BOLD; + } + if ((pflags& Paint.UNDERLINE_TEXT_FLAG) != 0) { + t.mTextStyle |= ViewNode.TEXT_STYLE_UNDERLINE; + } + if ((pflags& Paint.STRIKE_THRU_TEXT_FLAG) != 0) { + t.mTextStyle |= ViewNode.TEXT_STYLE_STRIKE_THRU; + } + } + + @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 editExtras() { + if (mNode.mExtras != null) { + return mNode.mExtras; + } + mNode.mExtras = new Bundle(); + return mNode.mExtras; + } + + @Override + public void clearExtras() { + mNode.mExtras = null; + } + + @Override + public void setChildCount(int num) { + mNode.mChildren = new ViewNode[num]; + } + + @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); + } + + @Override + public Rect getTempRect() { + return mAssist.mTmpRect; + } + } + AssistStructure(Activity activity) { mActivityComponent = activity.getComponentName(); ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews( diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a69384a..c0e253b 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -91,6 +91,7 @@ import android.view.animation.Transformation; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; +import android.widget.Checkable; import android.widget.ScrollBarDrawable; import static android.os.Build.VERSION_CODES.*; @@ -5676,10 +5677,143 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Called when assist structure is being retrieved from a view as part of * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}. - * @param structure Additional standard structured view structure to supply. - * @param extras Non-standard extensions. + * @param structure Fill in with structured view data. The default implementation + * fills in all data that can be inferred from the view itself. + */ + public void onProvideAssistStructure(ViewAssistStructure structure) { + final int id = mID; + if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0 + && (id&0x0000ffff) != 0) { + String pkg, type, entry; + try { + final Resources res = getResources(); + entry = res.getResourceEntryName(id); + type = res.getResourceTypeName(id); + pkg = res.getResourcePackageName(id); + } catch (Resources.NotFoundException e) { + entry = type = pkg = null; + } + structure.setId(id, pkg, type, entry); + } else { + structure.setId(id, null, null, null); + } + structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight-mLeft, mBottom-mTop); + structure.setVisibility(getVisibility()); + structure.setEnabled(isEnabled()); + if (isClickable()) { + structure.setClickable(true); + } + if (isFocusable()) { + structure.setFocusable(true); + } + if (isFocused()) { + structure.setFocused(true); + } + if (isAccessibilityFocused()) { + structure.setAccessibilityFocused(true); + } + if (isSelected()) { + structure.setSelected(true); + } + if (isActivated()) { + structure.setActivated(true); + } + if (isLongClickable()) { + structure.setLongClickable(true); + } + if (this instanceof Checkable) { + structure.setCheckable(true); + if (((Checkable)this).isChecked()) { + structure.setChecked(true); + } + } + structure.setClassName(getAccessibilityClassName().toString()); + structure.setContentDescription(getContentDescription()); + } + + /** + * Called when assist structure is being retrieved from a view as part of + * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to + * generate additional virtual structure under this view. The defaullt implementation + * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the + * view's virtual accessibility nodes, if any. You can override this for a more + * optimal implementation providing this data. + */ + public void onProvideVirtualAssistStructure(ViewAssistStructure structure) { + AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); + if (provider != null) { + AccessibilityNodeInfo info = createAccessibilityNodeInfo(); + Log.i("View", "Provider of " + this + ": children=" + info.getChildCount()); + structure.setChildCount(1); + ViewAssistStructure root = structure.newChild(0); + populateVirtualAssistStructure(root, provider, info); + info.recycle(); + } + } + + private void populateVirtualAssistStructure(ViewAssistStructure structure, + AccessibilityNodeProvider provider, AccessibilityNodeInfo info) { + structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()), + null, null, null); + Rect rect = structure.getTempRect(); + info.getBoundsInParent(rect); + structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height()); + structure.setVisibility(VISIBLE); + structure.setEnabled(info.isEnabled()); + if (info.isClickable()) { + structure.setClickable(true); + } + if (info.isFocusable()) { + structure.setFocusable(true); + } + if (info.isFocused()) { + structure.setFocused(true); + } + if (info.isAccessibilityFocused()) { + structure.setAccessibilityFocused(true); + } + if (info.isSelected()) { + structure.setSelected(true); + } + if (info.isLongClickable()) { + structure.setLongClickable(true); + } + if (info.isCheckable()) { + structure.setCheckable(true); + if (info.isChecked()) { + structure.setChecked(true); + } + } + CharSequence cname = info.getClassName(); + structure.setClassName(cname != null ? cname.toString() : null); + structure.setContentDescription(info.getContentDescription()); + Log.i("View", "vassist " + cname + " @ " + rect.toShortString() + + " text=" + info.getText() + " cd=" + info.getContentDescription()); + if (info.getText() != null || info.getError() != null) { + structure.setText(info.getText(), info.getTextSelectionStart(), + info.getTextSelectionEnd()); + } + final int NCHILDREN = info.getChildCount(); + if (NCHILDREN > 0) { + structure.setChildCount(NCHILDREN); + for (int i=0; i<NCHILDREN; i++) { + AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo( + AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i))); + ViewAssistStructure child = structure.newChild(i); + populateVirtualAssistStructure(child, provider, cinfo); + cinfo.recycle(); + } + } + } + + /** + * Dispatch creation of {@link ViewAssistStructure} down the hierarchy. The default + * implementation calls {@link #onProvideAssistStructure} and + * {@link #onProvideVirtualAssistStructure}. */ - public void onProvideAssistStructure(ViewAssistStructure structure, Bundle extras) { + public void dispatchProvideAssistStructure(ViewAssistStructure structure) { + onProvideAssistStructure(structure); + onProvideVirtualAssistStructure(structure); } /** diff --git a/core/java/android/view/ViewAssistStructure.java b/core/java/android/view/ViewAssistStructure.java index 5132bb9..c05ed6f 100644 --- a/core/java/android/view/ViewAssistStructure.java +++ b/core/java/android/view/ViewAssistStructure.java @@ -16,6 +16,8 @@ package android.view; +import android.graphics.Rect; +import android.os.Bundle; import android.text.TextPaint; /** @@ -23,6 +25,37 @@ import android.text.TextPaint; * View.onProvideAssistStructure}. */ public abstract class ViewAssistStructure { + public abstract void setId(int id, String packageName, String typeName, String entryName); + + public abstract void setDimens(int left, int top, int scrollX, int scrollY, int width, + int height); + + public abstract void setVisibility(int visibility); + + public abstract void setEnabled(boolean state); + + public abstract void setClickable(boolean state); + + public abstract void setLongClickable(boolean state); + + public abstract void setFocusable(boolean state); + + public abstract void setFocused(boolean state); + + public abstract void setAccessibilityFocused(boolean state); + + public abstract void setCheckable(boolean state); + + public abstract void setChecked(boolean state); + + public abstract void setSelected(boolean state); + + public abstract void setActivated(boolean state); + + public abstract void setClassName(String className); + + public abstract void setContentDescription(CharSequence contentDescription); + public abstract void setText(CharSequence text); public abstract void setText(CharSequence text, int selectionStart, int selectionEnd); public abstract void setTextPaint(TextPaint paint); @@ -32,4 +65,14 @@ public abstract class ViewAssistStructure { public abstract int getTextSelectionStart(); public abstract int getTextSelectionEnd(); public abstract CharSequence getHint(); + + public abstract Bundle editExtras(); + public abstract void clearExtras(); + + public abstract void setChildCount(int num); + public abstract int getChildCount(); + public abstract ViewAssistStructure newChild(int index); + + /** @hide */ + public abstract Rect getTempRect(); } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 87f3e94..7a84bb0 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -2852,6 +2852,33 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return false; } + /** + * Dispatch creation of {@link ViewAssistStructure} down the hierarchy. This implementation + * adds in all child views of the view group, in addition to calling the default View + * implementation. + */ + public void dispatchProvideAssistStructure(ViewAssistStructure structure) { + super.dispatchProvideAssistStructure(structure); + if (structure.getChildCount() == 0) { + final int childrenCount = getChildCount(); + if (childrenCount > 0) { + structure.setChildCount(childrenCount); + final ArrayList<View> preorderedList = buildOrderedChildList(); + final boolean customOrder = preorderedList == null + && isChildrenDrawingOrderEnabled(); + final View[] children = mChildren; + for (int i=0; i<childrenCount; i++) { + final int childIndex = customOrder + ? getChildDrawingOrder(childrenCount, i) : i; + final View child = (preorderedList == null) + ? children[childIndex] : preorderedList.get(childIndex); + ViewAssistStructure cstructure = structure.newChild(i); + child.dispatchProvideAssistStructure(cstructure); + } + } + } + } + /** @hide */ @Override public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java index bb290e7..ae779fe 100644 --- a/core/java/android/widget/Switch.java +++ b/core/java/android/widget/Switch.java @@ -1363,8 +1363,8 @@ public class Switch extends CompoundButton { } @Override - public void onProvideAssistStructure(ViewAssistStructure structure, Bundle extras) { - super.onProvideAssistStructure(structure, extras); + public void onProvideAssistStructure(ViewAssistStructure structure) { + super.onProvideAssistStructure(structure); CharSequence switchText = isChecked() ? mTextOn : mTextOff; if (!TextUtils.isEmpty(switchText)) { CharSequence oldText = structure.getText(); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 718ef93..877647d 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -8576,8 +8576,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } @Override - public void onProvideAssistStructure(ViewAssistStructure structure, Bundle extras) { - super.onProvideAssistStructure(structure, extras); + public void onProvideAssistStructure(ViewAssistStructure structure) { + super.onProvideAssistStructure(structure); final boolean isPassword = hasPasswordTransformationMethod(); if (!isPassword) { structure.setText(getText(), getSelectionStart(), getSelectionEnd()); diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java index bdc1276..782d112 100644 --- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java +++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java @@ -45,6 +45,7 @@ public class AssistVisualizer extends View { } public void setAssistStructure(AssistStructure as) { + mAssistStructure.dump(); mAssistStructure = as; mTextRects.clear(); final int N = as.getWindowNodeCount(); @@ -55,6 +56,7 @@ public class AssistVisualizer extends View { windowNode.getTop()); } } + Log.d(TAG, "Building text rects in " + this + ": found " + mTextRects.size()); invalidate(); } @@ -69,10 +71,11 @@ public class AssistVisualizer extends View { } int left = parentLeft+root.getLeft(); int top = parentTop+root.getTop(); - Log.d(TAG, "View " + root.getClassName() + ": " + left + ", " + top); - if (root.getText() != null) { + if (root.getText() != null || root.getContentDescription() != null) { Rect r = new Rect(left, top, left+root.getWidth(), top+root.getHeight()); - Log.d(TAG, "Text Rect " + r.toShortString() + ": " + root.getText()); + Log.d(TAG, "View " + root.getClassName() + " " + left + "," + top + " tr " + + r.toShortString() + ": " + + (root.getText() != null ? root.getText() : root.getContentDescription())); mTextRects.add(r); } final int N = root.getChildCount(); @@ -91,6 +94,7 @@ public class AssistVisualizer extends View { super.onDraw(canvas); getLocationOnScreen(mTmpLocation); final int N = mTextRects.size(); + Log.d(TAG, "Drawing text rects in " + this + ": found " + mTextRects.size()); for (int i=0; i<N; i++) { Rect r = mTextRects.get(i); canvas.drawRect(r.left-mTmpLocation[0], r.top-mTmpLocation[1], diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java index bc18ca9..ec727c4 100644 --- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java +++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java @@ -142,7 +142,6 @@ public class MainInteractionSession extends VoiceInteractionSession if (assistContext != null) { mAssistStructure = AssistStructure.getAssistStructure(assistContext); if (mAssistStructure != null) { - mAssistStructure.dump(); if (mAssistVisualizer != null) { mAssistVisualizer.setAssistStructure(mAssistStructure); } |