/* * 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.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; import android.view.View; import android.view.ViewAssistData; 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 #getAssistData(android.os.Bundle)}. */ final public class AssistData implements Parcelable { static final String TAG = "AssistData"; /** * Key name this data structure is stored in the Bundle generated by * {@link Activity#onProvideAssistData}. */ public static final String ASSIST_KEY = "android:assist"; final ComponentName mActivityComponent; final ArrayList mRootViews = new ArrayList<>(); ViewAssistDataImpl mTmpViewAssistDataImpl = new ViewAssistDataImpl(); Bundle mTmpExtras = new Bundle(); final static class ViewAssistDataImpl extends ViewAssistData { CharSequence mText; int mTextSelectionStart = -1; int mTextSelectionEnd = -1; 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 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 String mText; final int mTextSelectionStart; final int mTextSelectionEnd; final String mHint; ViewNodeTextImpl(ViewAssistDataImpl data) { mText = data.mText != null ? data.mText.toString() : null; mTextSelectionStart = data.mTextSelectionStart; mTextSelectionEnd = data.mTextSelectionEnd; mHint = data.mHint != null ? data.mHint.toString() : null; } ViewNodeTextImpl(Parcel in) { mText = in.readString(); mTextSelectionStart = in.readInt(); mTextSelectionEnd = in.readInt(); mHint = in.readString(); } void writeToParcel(Parcel out) { out.writeString(mText); out.writeInt(mTextSelectionStart); out.writeInt(mTextSelectionEnd); 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(AssistData assistData, 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 ViewAssistDataImpl viewData = assistData.mTmpViewAssistDataImpl; final Bundle extras = assistData.mTmpExtras; view.onProvideAssistData(viewData, extras); if (viewData.mText != null || viewData.mHint != null) { mText = new ViewNodeTextImpl(viewData); assistData.mTmpViewAssistDataImpl = new ViewAssistDataImpl(); } else { mText = null; } if (!extras.isEmpty()) { mExtras = extras; assistData.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 AssistData createFromParcel(Parcel in) { return new AssistData(in); } public AssistData[] newArray(int size) { return new AssistData[size]; } }; }