Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1273c4f authored by Dieter Hsu's avatar Dieter Hsu
Browse files

Refresh new extra data AccessibilityNodeInfo.ExtraRenderingInfo

Bug: 136404500
Test: atest AccessibilityTextActionTest AccessibilityNodeInfoTest
Change-Id: Ib1a8556d662d31ffbf3366e1482588ba058530cd
parent 2d4e0f25
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -55621,6 +55621,7 @@ package android.view.accessibility {
    method public CharSequence getContentDescription();
    method public int getDrawingOrder();
    method public CharSequence getError();
    method @Nullable public android.view.accessibility.AccessibilityNodeInfo.ExtraRenderingInfo getExtraRenderingInfo();
    method public android.os.Bundle getExtras();
    method public CharSequence getHintText();
    method public int getInputType();
@@ -55773,6 +55774,7 @@ package android.view.accessibility {
    field public static final int ACTION_SET_SELECTION = 131072; // 0x20000
    field public static final int ACTION_SET_TEXT = 2097152; // 0x200000
    field @NonNull public static final android.os.Parcelable.Creator<android.view.accessibility.AccessibilityNodeInfo> CREATOR;
    field public static final String EXTRA_DATA_RENDERING_INFO_KEY = "android.view.accessibility.extra.DATA_RENDERING_INFO_KEY";
    field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH";
    field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX";
    field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY";
@@ -55860,6 +55862,12 @@ package android.view.accessibility {
    method public static android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo obtain(int, int, int, int, boolean, boolean);
  }
  public static final class AccessibilityNodeInfo.ExtraRenderingInfo {
    method @Nullable public android.util.Size getLayoutParams();
    method public float getTextSizeInPx();
    method public int getTextSizeUnit();
  }
  public static final class AccessibilityNodeInfo.RangeInfo {
    ctor public AccessibilityNodeInfo.RangeInfo(int, float, float, float);
    method public float getCurrent();
@@ -60842,6 +60850,7 @@ package android.widget {
    method @Nullable public android.graphics.drawable.Drawable getTextSelectHandleLeft();
    method @Nullable public android.graphics.drawable.Drawable getTextSelectHandleRight();
    method @android.view.ViewDebug.ExportedProperty(category="text") public float getTextSize();
    method public int getTextSizeUnit();
    method public int getTotalPaddingBottom();
    method public int getTotalPaddingEnd();
    method public int getTotalPaddingLeft();
+25 −0
Original line number Diff line number Diff line
@@ -3692,6 +3692,31 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
            }
            childrenForAccessibility.clear();
        }
        info.setAvailableExtraData(Collections.singletonList(
                AccessibilityNodeInfo.EXTRA_DATA_RENDERING_INFO_KEY));
    }

    /**
     * {@inheritDoc}
     *
     * @param info The info to which to add the extra data. Never {@code null}.
     * @param extraDataKey A key specifying the type of extra data to add to the info. The
     *                     extra data should be added to the {@link Bundle} returned by
     *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
     *                     {@code null}.
     * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
     *                  {@code null} if the service provided no arguments.
     *
     */
    @Override
    public void addExtraDataToAccessibilityNodeInfo(@NonNull AccessibilityNodeInfo info,
            @NonNull String extraDataKey, @Nullable Bundle arguments) {
        if (extraDataKey.equals(AccessibilityNodeInfo.EXTRA_DATA_RENDERING_INFO_KEY)) {
            final AccessibilityNodeInfo.ExtraRenderingInfo extraRenderingInfo =
                    AccessibilityNodeInfo.ExtraRenderingInfo.obtain();
            extraRenderingInfo.setLayoutParams(getLayoutParams().width, getLayoutParams().height);
            info.setExtraRenderingInfo(extraRenderingInfo);
        }
    }

    @Override
+205 −0
Original line number Diff line number Diff line
@@ -50,8 +50,12 @@ import android.util.ArraySet;
import android.util.Log;
import android.util.LongArray;
import android.util.Pools.SynchronizedPool;
import android.util.Size;
import android.util.TypedValue;
import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.android.internal.R;
import com.android.internal.util.CollectionUtils;
@@ -634,6 +638,25 @@ public class AccessibilityNodeInfo implements Parcelable {
    public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH =
            "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH";

    /**
     * Key used to request extra data for accessibility scanning tool's purposes.
     * The key requests that a {@link AccessibilityNodeInfo.ExtraRenderingInfo} be added to this
     * info. This request is made with {@link #refreshWithExtraData(String, Bundle)} without
     * argument.
     * <p>
     * The data can be retrieved from the {@link ExtraRenderingInfo} returned by
     * {@link #getExtraRenderingInfo()} using {@link ExtraRenderingInfo#getLayoutParams},
     * {@link ExtraRenderingInfo#getTextSizeInPx()} and
     * {@link ExtraRenderingInfo#getTextSizeUnit()}. For layout params, it is supported by both
     * {@link TextView} and {@link ViewGroup}. For text size and unit, it is only supported by
     * {@link TextView}.
     *
     * @see #refreshWithExtraData(String, Bundle)
     */

    public static final String EXTRA_DATA_RENDERING_INFO_KEY =
            "android.view.accessibility.extra.DATA_RENDERING_INFO_KEY";

    /** @hide */
    public static final String EXTRA_DATA_REQUESTED_KEY =
            "android.view.accessibility.AccessibilityNodeInfo.extra_data_requested";
@@ -804,6 +827,8 @@ public class AccessibilityNodeInfo implements Parcelable {

    private TouchDelegateInfo mTouchDelegateInfo;

    private ExtraRenderingInfo mExtraRenderingInfo;

    private IBinder mLeashedChild;
    private IBinder mLeashedParent;
    private long mLeashedParentNodeId = UNDEFINED_NODE_ID;
@@ -991,6 +1016,7 @@ public class AccessibilityNodeInfo implements Parcelable {
     * @param extraDataKey The extra data requested. Data that must be requested
     *                     with this mechanism is generally expensive to retrieve, so should only be
     *                     requested when needed. See
     *                     {@link #EXTRA_DATA_RENDERING_INFO_KEY},
     *                     {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY} and
     *                     {@link #getAvailableExtraData()}.
     * @param args A bundle of arguments for the request. These depend on the particular request.
@@ -1547,6 +1573,7 @@ public class AccessibilityNodeInfo implements Parcelable {
     * {@link #refreshWithExtraData(String, Bundle)}.
     *
     * @return An unmodifiable list of keys corresponding to extra data that can be requested.
     * @see #EXTRA_DATA_RENDERING_INFO_KEY
     * @see #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY
     */
    public List<String> getAvailableExtraData() {
@@ -2374,6 +2401,32 @@ public class AccessibilityNodeInfo implements Parcelable {
        mRangeInfo = rangeInfo;
    }

    /**
     * Gets the conformance info if the node is meant to be refreshed with extra data.
     *
     * @return The conformance info.
     */
    @Nullable
    public ExtraRenderingInfo getExtraRenderingInfo() {
        return mExtraRenderingInfo;
    }

    /**
     * Sets the conformance info if the node is meant to be refreshed with extra data.
     * <p>
     *   <strong>Note:</strong> Cannot be called from an
     *   {@link android.accessibilityservice.AccessibilityService}.
     *   This class is made immutable before being delivered to an AccessibilityService.
     * </p>
     *
     * @param extraRenderingInfo The conformance info.
     * @hide
     */
    public void setExtraRenderingInfo(@NonNull ExtraRenderingInfo extraRenderingInfo) {
        enforceNotSealed();
        mExtraRenderingInfo = extraRenderingInfo;
    }

    /**
     * Gets if the content of this node is invalid. For example,
     * a date is not well-formed.
@@ -3695,6 +3748,10 @@ public class AccessibilityNodeInfo implements Parcelable {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        fieldIndex++;
        if (!Objects.equals(mExtraRenderingInfo, DEFAULT.mExtraRenderingInfo)) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        fieldIndex++;
        if (mLeashedChild != DEFAULT.mLeashedChild) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
@@ -3832,6 +3889,12 @@ public class AccessibilityNodeInfo implements Parcelable {
            mTouchDelegateInfo.writeToParcel(parcel, flags);
        }

        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            parcel.writeValue(mExtraRenderingInfo.getLayoutParams());
            parcel.writeFloat(mExtraRenderingInfo.getTextSizeInPx());
            parcel.writeInt(mExtraRenderingInfo.getTextSizeUnit());
        }

        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            parcel.writeStrongBinder(mLeashedChild);
        }
@@ -3941,6 +4004,9 @@ public class AccessibilityNodeInfo implements Parcelable {
        if (mCollectionItemInfo != null) mCollectionItemInfo.recycle();
        mCollectionItemInfo =  (other.mCollectionItemInfo != null)
                ? CollectionItemInfo.obtain(other.mCollectionItemInfo) : null;
        if (mExtraRenderingInfo != null) mExtraRenderingInfo.recycle();
        mExtraRenderingInfo = (other.mExtraRenderingInfo != null)
                ? ExtraRenderingInfo.obtain(other.mExtraRenderingInfo) : null;
    }

    private void initCopyInfos(AccessibilityNodeInfo other) {
@@ -3955,6 +4021,9 @@ public class AccessibilityNodeInfo implements Parcelable {
        mCollectionItemInfo = (cii == null)  ? null
                : new CollectionItemInfo(cii.mRowIndex, cii.mRowSpan, cii.mColumnIndex,
                                         cii.mColumnSpan, cii.mHeading, cii.mSelected);
        ExtraRenderingInfo ti = other.mExtraRenderingInfo;
        mExtraRenderingInfo = (ti == null) ? null
                : new ExtraRenderingInfo(ti);
    }

    /**
@@ -4082,6 +4151,14 @@ public class AccessibilityNodeInfo implements Parcelable {
            mTouchDelegateInfo = TouchDelegateInfo.CREATOR.createFromParcel(parcel);
        }

        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            if (mExtraRenderingInfo != null) mExtraRenderingInfo.recycle();
            mExtraRenderingInfo = ExtraRenderingInfo.obtain();
            mExtraRenderingInfo.mLayoutParams = (Size) parcel.readValue(null);
            mExtraRenderingInfo.mTextSizeInPx = parcel.readFloat();
            mExtraRenderingInfo.mTextSizeUnit = parcel.readInt();
        }

        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            mLeashedChild = parcel.readStrongBinder();
        }
@@ -5678,6 +5755,134 @@ public class AccessibilityNodeInfo implements Parcelable {
        };
    }

    /**
     * Class with information of a view useful to evaluate accessibility needs. Developers can
     * refresh the node with the key {@link #EXTRA_DATA_RENDERING_INFO_KEY} to fetch the text size
     * and unit if it is {@link TextView} and the height and the width of layout params from
     * {@link ViewGroup} or {@link TextView}.
     *
     * @see #EXTRA_DATA_RENDERING_INFO_KEY
     * @see #refreshWithExtraData(String, Bundle)
     */
    public static final class ExtraRenderingInfo {
        private static final int UNDEFINED_VALUE = -1;
        private static final int MAX_POOL_SIZE = 20;
        private static final SynchronizedPool<ExtraRenderingInfo> sPool =
                new SynchronizedPool<>(MAX_POOL_SIZE);

        private Size mLayoutParams;
        private float mTextSizeInPx = UNDEFINED_VALUE;
        private int mTextSizeUnit = UNDEFINED_VALUE;

        /**
         * Obtains a pooled instance.
         * @hide
         */
        @NonNull
        public static ExtraRenderingInfo obtain() {
            final ExtraRenderingInfo info = sPool.acquire();
            if (info == null) {
                return new ExtraRenderingInfo(null);
            }
            return info;
        }

        /** Obtains a pooled instance that is a clone of another one. */
        private static ExtraRenderingInfo obtain(ExtraRenderingInfo other) {
            ExtraRenderingInfo extraRenderingInfo = ExtraRenderingInfo.obtain();
            extraRenderingInfo.mLayoutParams = other.mLayoutParams;
            extraRenderingInfo.mTextSizeInPx = other.mTextSizeInPx;
            extraRenderingInfo.mTextSizeUnit = other.mTextSizeUnit;
            return extraRenderingInfo;
        }

        /**
         * Creates a new conformance info of a view, and this new instance is initialized from
         * the given <code>other</code>.
         *
         * @param other The instance to clone.
         */
        private ExtraRenderingInfo(@Nullable ExtraRenderingInfo other) {
            if (other != null) {
                mLayoutParams = other.mLayoutParams;
                mTextSizeInPx = other.mTextSizeInPx;
                mTextSizeUnit = other.mTextSizeUnit;
            }
        }

        /**
         * @return a {@link Size} stores layout height and layout width of the view,
         *         or null otherwise.
         */
        public @Nullable Size getLayoutParams() {
            return mLayoutParams;
        }

        /**
         * Sets layout width and layout height of the view.
         *
         * @param width The layout width.
         * @param height The layout height.
         * @hide
         */
        public void setLayoutParams(int width, int height) {
            mLayoutParams = new Size(width, height);
        }

        /**
         * @return the text size of a {@code TextView}, or -1 otherwise.
         */
        public float getTextSizeInPx() {
            return mTextSizeInPx;
        }

        /**
         * Sets text size of the view.
         *
         * @param textSizeInPx The text size in pixels.
         * @hide
         */
        public void setTextSizeInPx(float textSizeInPx) {
            mTextSizeInPx = textSizeInPx;
        }

        /**
         * @return the text size unit which type is {@link TypedValue#TYPE_DIMENSION} of a
         *         {@code TextView}, or -1 otherwise.
         *
         * @see TypedValue#TYPE_DIMENSION
         */
        public int getTextSizeUnit() {
            return mTextSizeUnit;
        }

        /**
         * Sets text size unit of the view.
         *
         * @param textSizeUnit The text size unit.
         * @hide
         */
        public void setTextSizeUnit(int textSizeUnit) {
            mTextSizeUnit = textSizeUnit;
        }

        /**
         * Recycles this instance.
         *
         * <p>In most situations object pooling is not beneficial, and recycling is not necessary.
         */
        void recycle() {
            clear();
            sPool.release(this);
        }

        private void clear() {
            mLayoutParams = null;
            mTextSizeInPx = UNDEFINED_VALUE;
            mTextSizeUnit = UNDEFINED_VALUE;
        }
    }

    /**
     * @see android.os.Parcelable.Creator
     */
+36 −7
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.widget;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_RENDERING_INFO_KEY;
import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH;
import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX;
import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY;
@@ -727,6 +728,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    @UnsupportedAppUsage
    private Layout mLayout;
    private boolean mLocalesChanged = false;
    private int mTextSizeUnit = -1;
    // True if setKeyListener() has been explicitly called
    private boolean mListenerChanged = false;
@@ -3842,6 +3844,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        ColorStateList mTextColorHint = null;
        ColorStateList mTextColorLink = null;
        int mTextSize = -1;
        int mTextSizeUnit = -1;
        LocaleList mTextLocales = null;
        String mFontFamily = null;
        Typeface mFontTypeface = null;
@@ -3869,6 +3872,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                    + "    mTextColorHint:" + mTextColorHint + "\n"
                    + "    mTextColorLink:" + mTextColorLink + "\n"
                    + "    mTextSize:" + mTextSize + "\n"
                    + "    mTextSizeUnit:" + mTextSizeUnit + "\n"
                    + "    mTextLocales:" + mTextLocales + "\n"
                    + "    mFontFamily:" + mFontFamily + "\n"
                    + "    mFontTypeface:" + mFontTypeface + "\n"
@@ -3980,6 +3984,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                case com.android.internal.R.styleable.TextAppearance_textSize:
                    attributes.mTextSize =
                            appearance.getDimensionPixelSize(attr, attributes.mTextSize);
                    attributes.mTextSizeUnit = appearance.peekValue(attr).getComplexUnit();
                    break;
                case com.android.internal.R.styleable.TextAppearance_textLocale:
                    final String localeString = appearance.getString(attr);
@@ -4073,6 +4078,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        }
        if (attributes.mTextSize != -1) {
            mTextSizeUnit = attributes.mTextSizeUnit;
            setRawTextSize(attributes.mTextSize, true /* shouldRequestLayout */);
        }
@@ -4295,6 +4301,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            r = c.getResources();
        }
        mTextSizeUnit = unit;
        setRawTextSize(TypedValue.applyDimension(unit, size, r.getDisplayMetrics()),
                shouldRequestLayout);
    }
@@ -4314,6 +4321,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        }
    }
    /**
     * Gets the text size unit defined by the developer. It may be specified in resources or be
     * passed as the unit argument of {@link #setTextSize(int, float)} at runtime.
     *
     * @return the dimension type of the text size unit originally defined.
     * @see TypedValue#TYPE_DIMENSION
     */
    public int getTextSizeUnit() {
        return mTextSizeUnit;
    }
    /**
     * Gets the extent by which text should be stretched horizontally.
     * This will usually be 1.0.
@@ -11769,8 +11787,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
            info.setAvailableExtraData(
                    Arrays.asList(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY));
            info.setAvailableExtraData(Arrays.asList(
                    EXTRA_DATA_RENDERING_INFO_KEY,
                    EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY
            ));
        } else {
            info.setAvailableExtraData(Arrays.asList(
                    EXTRA_DATA_RENDERING_INFO_KEY
            ));
        }
        if (isFocused()) {
@@ -11824,11 +11848,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    @Override
    public void addExtraDataToAccessibilityNodeInfo(
            AccessibilityNodeInfo info, String extraDataKey, Bundle arguments) {
        // The only extra data we support requires arguments.
        if (arguments == null) {
            return;
        }
        if (extraDataKey.equals(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY)) {
        if (arguments != null && extraDataKey.equals(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY)) {
            int positionInfoStartIndex = arguments.getInt(
                    EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX, -1);
            int positionInfoLength = arguments.getInt(
@@ -11856,6 +11876,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                }
            }
            info.getExtras().putParcelableArray(extraDataKey, boundingRects);
            return;
        }
        if (extraDataKey.equals(AccessibilityNodeInfo.EXTRA_DATA_RENDERING_INFO_KEY)) {
            final AccessibilityNodeInfo.ExtraRenderingInfo extraRenderingInfo =
                    AccessibilityNodeInfo.ExtraRenderingInfo.obtain();
            extraRenderingInfo.setLayoutParams(getLayoutParams().width, getLayoutParams().height);
            extraRenderingInfo.setTextSizeInPx(getTextSize());
            extraRenderingInfo.setTextSizeUnit(getTextSizeUnit());
            info.setExtraRenderingInfo(extraRenderingInfo);
        }
    }
+1 −1
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ public class AccessibilityNodeInfoTest {
    // The number of fields tested in the corresponding CTS AccessibilityNodeInfoTest:
    // See fullyPopulateAccessibilityNodeInfo, assertEqualsAccessibilityNodeInfo,
    // and assertAccessibilityNodeInfoCleared in that class.
    private static final int NUM_MARSHALLED_PROPERTIES = 38;
    private static final int NUM_MARSHALLED_PROPERTIES = 39;

    /**
     * The number of properties that are purposely not marshalled