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

Commit 212800a6 authored by Yinglei Wang's avatar Yinglei Wang
Browse files

Add tri-state checked api

Design doc: https://docs.google.com/document/d/1vUzX7eSbIw_0N0kD5cYO09almUzYB7YhHNRhZcfKfXo/edit?usp=sharing

Test: CTS test added
Flag: android.view.accessibility.tri_state_checked

Bug: 333784774
Change-Id: Ifc8eee777740397d089ad242daa711bfc224722d
parent 79d66353
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -54919,6 +54919,7 @@ package android.view.accessibility {
    method public void setPackageName(CharSequence);
    method public void setSpeechStateChangeTypes(int);
    method public void writeToParcel(android.os.Parcel, int);
    field @FlaggedApi("android.view.accessibility.tri_state_checked") public static final int CONTENT_CHANGE_TYPE_CHECKED = 8192; // 0x2000
    field public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 4; // 0x4
    field public static final int CONTENT_CHANGE_TYPE_CONTENT_INVALID = 1024; // 0x400
    field public static final int CONTENT_CHANGE_TYPE_DRAG_CANCELLED = 512; // 0x200
@@ -55064,6 +55065,7 @@ package android.view.accessibility {
    method @Deprecated public void getBoundsInParent(android.graphics.Rect);
    method public void getBoundsInScreen(android.graphics.Rect);
    method public void getBoundsInWindow(@NonNull android.graphics.Rect);
    method @FlaggedApi("android.view.accessibility.tri_state_checked") public int getChecked();
    method public android.view.accessibility.AccessibilityNodeInfo getChild(int);
    method @Nullable public android.view.accessibility.AccessibilityNodeInfo getChild(int, int);
    method public int getChildCount();
@@ -55106,7 +55108,7 @@ package android.view.accessibility {
    method public boolean isAccessibilityDataSensitive();
    method public boolean isAccessibilityFocused();
    method public boolean isCheckable();
    method public boolean isChecked();
    method @Deprecated @FlaggedApi("android.view.accessibility.tri_state_checked") public boolean isChecked();
    method public boolean isClickable();
    method public boolean isContentInvalid();
    method public boolean isContextClickable();
@@ -55151,7 +55153,8 @@ package android.view.accessibility {
    method public void setBoundsInWindow(@NonNull android.graphics.Rect);
    method public void setCanOpenPopup(boolean);
    method public void setCheckable(boolean);
    method public void setChecked(boolean);
    method @Deprecated @FlaggedApi("android.view.accessibility.tri_state_checked") public void setChecked(boolean);
    method @FlaggedApi("android.view.accessibility.tri_state_checked") public void setChecked(int);
    method public void setClassName(CharSequence);
    method public void setClickable(boolean);
    method public void setCollectionInfo(android.view.accessibility.AccessibilityNodeInfo.CollectionInfo);
@@ -55247,6 +55250,9 @@ package android.view.accessibility {
    field public static final int ACTION_SELECT = 4; // 0x4
    field public static final int ACTION_SET_SELECTION = 131072; // 0x20000
    field public static final int ACTION_SET_TEXT = 2097152; // 0x200000
    field @FlaggedApi("android.view.accessibility.tri_state_checked") public static final int CHECKED_STATE_FALSE = 0; // 0x0
    field @FlaggedApi("android.view.accessibility.tri_state_checked") public static final int CHECKED_STATE_PARTIAL = 2; // 0x2
    field @FlaggedApi("android.view.accessibility.tri_state_checked") public static final int CHECKED_STATE_TRUE = 1; // 0x1
    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";
+14 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.view.accessibility;

import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
@@ -784,6 +785,19 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
     */
    public static final int CONTENT_CHANGE_TYPE_ENABLED = 1 << 12;

    /**
     * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
     * The source node changed its checked state, which is returned by
     * {@link AccessibilityNodeInfo#getChecked()}.
     * The view changing its checked state should call
     * {@link AccessibilityNodeInfo#setChecked(int)} and then send this event.
     *
     * @see AccessibilityNodeInfo#getChecked()
     * @see AccessibilityNodeInfo#setChecked(int)
     */
    @FlaggedApi(Flags.FLAG_TRI_STATE_CHECKED)
    public static final int CONTENT_CHANGE_TYPE_CHECKED = 1 << 13;

    // Speech state change types.

    /** Change type for {@link #TYPE_SPEECH_STATE_CHANGE} event: another service is speaking. */
+120 −2
Original line number Diff line number Diff line
@@ -860,6 +860,37 @@ public class AccessibilityNodeInfo implements Parcelable {
    public static final String EXTRA_DATA_REQUESTED_KEY =
            "android.view.accessibility.AccessibilityNodeInfo.extra_data_requested";

    // Tri-state checked states.

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "CHECKED_STATE" }, value = {
            CHECKED_STATE_FALSE,
            CHECKED_STATE_TRUE,
            CHECKED_STATE_PARTIAL
    })
    public @interface CheckedState {}

    /**
     * This node is not checked.
     */
    @FlaggedApi(Flags.FLAG_TRI_STATE_CHECKED)
    public static final int CHECKED_STATE_FALSE = 0;

    /**
     * This node is checked.
     */
    @FlaggedApi(Flags.FLAG_TRI_STATE_CHECKED)
    public static final int CHECKED_STATE_TRUE = 1;

    /**
     * This node is partially checked. For example,
     * when a checkbox owns a number of sub-options and they have
     * different states, then the main checkbox is in a partially-checked state.
     */
    @FlaggedApi(Flags.FLAG_TRI_STATE_CHECKED)
    public static final int CHECKED_STATE_PARTIAL = 2;

    // Boolean attributes.

    private static final int BOOLEAN_PROPERTY_CHECKABLE = 1 /* << 0 */;
@@ -1038,6 +1069,10 @@ public class AccessibilityNodeInfo implements Parcelable {
    private IBinder mLeashedParent;
    private long mLeashedParentNodeId = UNDEFINED_NODE_ID;

    // TODO(b/369951517) Initialize mChecked explicitly with
    // the CHECKED_FALSE state when flagging is removed.
    private int mChecked;

    /**
     * Creates a new {@link AccessibilityNodeInfo}.
     */
@@ -2319,28 +2354,100 @@ public class AccessibilityNodeInfo implements Parcelable {
    }

    /**
     * Gets whether this node is checked.
     * Gets whether this node is checked. This is only meaningful
     * when {@link #isCheckable()} returns {@code true}.
     *
     * @deprecated Use {@link #getChecked()} instead.
     *
     * @return True if the node is checked.
     */
    @FlaggedApi(Flags.FLAG_TRI_STATE_CHECKED)
    @Deprecated
    public boolean isChecked() {
        return getBooleanProperty(BOOLEAN_PROPERTY_CHECKED);
    }

    /**
     * Sets whether this node is checked.
     * Sets whether this node is checked. This is only meaningful
     * when {@link #isCheckable()} returns {@code true}.
     * <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>
     *
     * @deprecated Use {@link #setChecked(int)} instead.
     *
     * @param checked True if the node is checked.
     *
     * @throws IllegalStateException If called from an AccessibilityService.
     */
    @FlaggedApi(Flags.FLAG_TRI_STATE_CHECKED)
    @Deprecated
    public void setChecked(boolean checked) {
        setBooleanProperty(BOOLEAN_PROPERTY_CHECKED, checked);
        if (Flags.triStateChecked()) {
            mChecked = checked ? CHECKED_STATE_TRUE : CHECKED_STATE_FALSE;
        }
    }

    /**
     * Gets the checked state of this node. This is only meaningful
     * when {@link #isCheckable()} returns {@code true}.
     *
     * @see #setCheckable(boolean)
     * @see #isCheckable()
     * @see #setChecked(int)
     *
     * @return The checked state, one of:
     *          <ul>
     *          <li>{@link #CHECKED_STATE_FALSE}
     *          <li>{@link #CHECKED_STATE_TRUE}
     *          <li>{@link #CHECKED_STATE_PARTIAL}
     *          </ul>
     */
    @FlaggedApi(Flags.FLAG_TRI_STATE_CHECKED)
    public @CheckedState int getChecked() {
        return mChecked;
    }

    /**
     * Sets the checked state of this node. This is only meaningful
     * when {@link #isCheckable()} returns {@code true}.
     * <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>
     *
     * @see #setCheckable(boolean)
     * @see #isCheckable()
     * @see #getChecked()
     *
     * @param checked The checked state. One of
     *          <ul>
     *          <li>{@link #CHECKED_STATE_FALSE}
     *          <li>{@link #CHECKED_STATE_TRUE}
     *          <li>{@link #CHECKED_STATE_PARTIAL}
     *          </ul>
     *
     * @throws IllegalStateException If called from an AccessibilityService.
     * @throws IllegalArgumentException if checked is not one of {@link #CHECKED_STATE_FALSE},
     *          {@link #CHECKED_STATE_TRUE}, or {@link #CHECKED_STATE_PARTIAL}.
     */
    @FlaggedApi(Flags.FLAG_TRI_STATE_CHECKED)
    public void setChecked(@CheckedState int checked) {
        enforceNotSealed();
        switch (checked) {
            case CHECKED_STATE_FALSE:
            case CHECKED_STATE_TRUE:
            case CHECKED_STATE_PARTIAL:
                mChecked = checked;
                break;
            default:
                throw new IllegalArgumentException("Unknown checked argument: " + checked);
        }
        setBooleanProperty(BOOLEAN_PROPERTY_CHECKED, checked == CHECKED_STATE_TRUE);
    }

    /**
@@ -4515,6 +4622,10 @@ public class AccessibilityNodeInfo implements Parcelable {
        if (mLeashedParentNodeId != DEFAULT.mLeashedParentNodeId) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        fieldIndex++;
        if (mChecked != DEFAULT.mChecked) {
            nonDefaultFields |= bitAt(fieldIndex);
        }
        int totalFields = fieldIndex;
        parcel.writeLong(nonDefaultFields);

@@ -4683,6 +4794,9 @@ public class AccessibilityNodeInfo implements Parcelable {
        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            parcel.writeLong(mLeashedParentNodeId);
        }
        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            parcel.writeInt(mChecked);
        }

        if (DEBUG) {
            fieldIndex--;
@@ -4771,6 +4885,7 @@ public class AccessibilityNodeInfo implements Parcelable {
        mLeashedChild = other.mLeashedChild;
        mLeashedParent = other.mLeashedParent;
        mLeashedParentNodeId = other.mLeashedParentNodeId;
        mChecked = other.mChecked;
    }

    private void initCopyInfos(AccessibilityNodeInfo other) {
@@ -4960,6 +5075,9 @@ public class AccessibilityNodeInfo implements Parcelable {
        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            mLeashedParentNodeId = parcel.readLong();
        }
        if (isBitSet(nonDefaultFields, fieldIndex++)) {
            mChecked = parcel.readInt();
        }

        mSealed = sealed;
    }
+8 −1
Original line number Diff line number Diff line
@@ -218,6 +218,13 @@ flag {
    bug: "315089687"
}

flag {
    name: "tri_state_checked"
    namespace: "accessibility"
    description: "Feature flag for adding tri-state checked api"
    bug: "333784774"
}

flag {
    name: "warning_use_default_dialog_type"
    namespace: "accessibility"
+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 = 44;
    private static final int NUM_MARSHALLED_PROPERTIES = 45;

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