/* * 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.Paint; import android.graphics.Rect; import android.graphics.Typeface; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.os.PooledStringReader; import android.os.PooledStringWriter; import android.text.TextPaint; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.view.ViewAssistStructure; import android.view.ViewGroup; import android.view.ViewRootImpl; import android.view.WindowManagerGlobal; import android.widget.Checkable; import java.util.ArrayList; /** * Assist data automatically created by the platform's implementation * of {@link Activity#onProvideAssistData}. Retrieve it from the assist * data with {@link #getAssistStructure(android.os.Bundle)}. */ final public class AssistStructure implements Parcelable { static final String TAG = "AssistStructure"; /** * Key name this data structure is stored in the Bundle generated by * {@link Activity#onProvideAssistData}. */ public static final String ASSIST_KEY = "android:assist_structure"; final ComponentName mActivityComponent; final ArrayList mRootViews = new ArrayList<>(); ViewAssistStructureImpl mTmpViewAssistStructureImpl = new ViewAssistStructureImpl(); Bundle mTmpExtras = new Bundle(); final static class ViewAssistStructureImpl extends ViewAssistStructure { CharSequence mText; int mTextSelectionStart = -1; int mTextSelectionEnd = -1; int mTextColor = ViewNode.TEXT_COLOR_UNDEFINED; int mTextBackgroundColor = ViewNode.TEXT_COLOR_UNDEFINED; float mTextSize = 0; int mTextStyle = 0; CharSequence mHint; @Override 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 mTextColor; int mTextBackgroundColor; float mTextSize; int mTextStyle; final 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; } ViewNodeTextImpl(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); } } final static class ViewNodeImpl { final int mX; final int mY; final int mScrollX; final int mScrollY; final int mWidth; final 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_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; final int mFlags; final String mClassName; final String 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; 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 = contentDescription != null ? contentDescription.toString() : null; 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 ViewNodeImpl[NCHILDREN]; for (int i=0; i 0) { mChildren = new ViewNodeImpl[NCHILDREN]; for (int i=0; i views = WindowManagerGlobal.getInstance().getRootViews( activity.getActivityToken()); for (int i=0; i 0) { Log.i(TAG, prefix + " Children:"); String cprefix = prefix + " "; ViewNode cnode = new ViewNode(); for (int i=0; i CREATOR = new Parcelable.Creator() { public AssistStructure createFromParcel(Parcel in) { return new AssistStructure(in); } public AssistStructure[] newArray(int size) { return new AssistStructure[size]; } }; }