From 0b071a08d8dec3e68937590938199273f3b123cc Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Fri, 20 Mar 2015 15:05:35 -0700 Subject: Add view ID, rework assist API. Add view ID information to the assist structure. Also rework the API to simplify how it works by removing the ViewNode wrapper around ViewNodeImpl -- these are now just the same thing. And then add complexity by introducing a formal WindowNode object that contains the top-level window information (so I can add in some more window-specific info in the future). Change-Id: I5d525cf61ab6a73193e5cceb4c09d2d21cc27bae --- api/current.txt | 22 +- api/system-current.txt | 22 +- core/java/android/app/AssistStructure.java | 305 ++++++++++++++------- .../test/voiceinteraction/AssistVisualizer.java | 11 +- 4 files changed, 251 insertions(+), 109 deletions(-) diff --git a/api/current.txt b/api/current.txt index 29f0a29e4864..7d40c7be976e 100644 --- a/api/current.txt +++ b/api/current.txt @@ -3977,22 +3977,25 @@ package android.app { method public int describeContents(); method public android.content.ComponentName getActivityComponent(); method public static android.app.AssistStructure getAssistStructure(android.os.Bundle); - method public void getWindowAt(int, android.app.AssistStructure.ViewNode); - method public int getWindowCount(); + method public android.app.AssistStructure.WindowNode getWindowNodeAt(int); + method public int getWindowNodeCount(); method public void writeToParcel(android.os.Parcel, int); field public static final java.lang.String ASSIST_KEY = "android:assist_structure"; field public static final android.os.Parcelable.Creator CREATOR; } public static class AssistStructure.ViewNode { - ctor public AssistStructure.ViewNode(); - method public void getChildAt(int, android.app.AssistStructure.ViewNode); + method public android.app.AssistStructure.ViewNode getChildAt(int); method public int getChildCount(); method public java.lang.String getClassName(); - method public java.lang.String getContentDescription(); + 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(); @@ -4023,6 +4026,15 @@ package android.app { field public static final int TEXT_STYLE_UNDERLINE = 4; // 0x4 } + public static class AssistStructure.WindowNode { + 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); diff --git a/api/system-current.txt b/api/system-current.txt index c98f7a334693..0c61110f353e 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4067,22 +4067,25 @@ package android.app { method public int describeContents(); method public android.content.ComponentName getActivityComponent(); method public static android.app.AssistStructure getAssistStructure(android.os.Bundle); - method public void getWindowAt(int, android.app.AssistStructure.ViewNode); - method public int getWindowCount(); + method public android.app.AssistStructure.WindowNode getWindowNodeAt(int); + method public int getWindowNodeCount(); method public void writeToParcel(android.os.Parcel, int); field public static final java.lang.String ASSIST_KEY = "android:assist_structure"; field public static final android.os.Parcelable.Creator CREATOR; } public static class AssistStructure.ViewNode { - ctor public AssistStructure.ViewNode(); - method public void getChildAt(int, android.app.AssistStructure.ViewNode); + method public android.app.AssistStructure.ViewNode getChildAt(int); method public int getChildCount(); method public java.lang.String getClassName(); - method public java.lang.String getContentDescription(); + 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(); @@ -4113,6 +4116,15 @@ package android.app { field public static final int TEXT_STYLE_UNDERLINE = 4; // 0x4 } + public static class AssistStructure.WindowNode { + 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); diff --git a/core/java/android/app/AssistStructure.java b/core/java/android/app/AssistStructure.java index 25153fc5e24f..c435ccb27d7f 100644 --- a/core/java/android/app/AssistStructure.java +++ b/core/java/android/app/AssistStructure.java @@ -17,6 +17,7 @@ package android.app; import android.content.ComponentName; +import android.content.res.Resources; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.Typeface; @@ -53,7 +54,7 @@ final public class AssistStructure implements Parcelable { final ComponentName mActivityComponent; - final ArrayList mRootViews = new ArrayList<>(); + final ArrayList mWindowNodes = new ArrayList<>(); ViewAssistStructureImpl mTmpViewAssistStructureImpl = new ViewAssistStructureImpl(); Bundle mTmpExtras = new Bundle(); @@ -178,7 +179,91 @@ final public class AssistStructure implements Parcelable { } } - final static class ViewNodeImpl { + /** + * 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 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(); + mRoot = new ViewNode(assist, view); + } + + WindowNode(Parcel in, PooledStringReader preader) { + mX = in.readInt(); + mY = in.readInt(); + mWidth = in.readInt(); + mHeight = in.readInt(); + mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); + 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); + mRoot.writeToParcel(out, pwriter); + } + + public int getLeft() { + return mX; + } + + public int getTop() { + return mY; + } + + public int getWidth() { + return mWidth; + } + + public int getHeight() { + return mHeight; + } + + public CharSequence getTitle() { + return mTitle; + } + + 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; + + final int mId; + final String mIdPackage; + final String mIdType; + final String mIdEntry; final int mX; final int mY; final int mScrollX; @@ -201,17 +286,34 @@ final public class AssistStructure implements Parcelable { final int mFlags; final String mClassName; - final String mContentDescription; + final CharSequence mContentDescription; final ViewNodeTextImpl mText; final Bundle mExtras; - final ViewNodeImpl[] mChildren; - - ViewNodeImpl(AssistStructure assistStructure, View view, int left, int top, - CharSequence contentDescription) { - mX = left; - mY = top; + final 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(); @@ -249,7 +351,7 @@ final public class AssistStructure implements Parcelable { } mFlags = flags; mClassName = view.getAccessibilityClassName().toString(); - mContentDescription = contentDescription != null ? contentDescription.toString() : null; + mContentDescription = view.getContentDescription(); final ViewAssistStructureImpl viewData = assistStructure.mTmpViewAssistStructureImpl; final Bundle extras = assistStructure.mTmpExtras; view.onProvideAssistStructure(viewData, extras); @@ -269,9 +371,9 @@ final public class AssistStructure implements Parcelable { ViewGroup vg = (ViewGroup)view; final int NCHILDREN = vg.getChildCount(); if (NCHILDREN > 0) { - mChildren = new ViewNodeImpl[NCHILDREN]; + mChildren = new ViewNode[NCHILDREN]; for (int i=0; i 0) { - mChildren = new ViewNodeImpl[NCHILDREN]; + mChildren = new ViewNode[NCHILDREN]; for (int i=0; i 0) { Log.i(TAG, prefix + " Children:"); String cprefix = prefix + " "; - ViewNode cnode = new ViewNode(); for (int i=0; i 0) { - AssistStructure.ViewNode window = new AssistStructure.ViewNode(); for (int i=0; i 0) { left -= root.getScrollX(); top -= root.getScrollY(); - AssistStructure.ViewNode child = new AssistStructure.ViewNode(); for (int i=0; i