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

Commit 2a65a283 authored by Alan Viverette's avatar Alan Viverette Committed by Android (Google) Code Review
Browse files

Merge "Add live region politeness to View, AccessibilityNodeInfo" into klp-dev

parents b72ff5aa 77e9a28e
Loading
Loading
Loading
Loading
+16 −12
Original line number Diff line number Diff line
@@ -228,6 +228,7 @@ package android {
    field public static final int accessibilityEventTypes = 16843648; // 0x1010380
    field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
    field public static final int accessibilityFlags = 16843652; // 0x1010384
    field public static final int accessibilityLiveRegion = 16843758; // 0x10103ee
    field public static final int accountPreferences = 16843423; // 0x101029f
    field public static final int accountType = 16843407; // 0x101028f
    field public static final int action = 16842797; // 0x101002d
@@ -27481,6 +27482,7 @@ package android.view {
    method public android.view.View focusSearch(int);
    method public void forceLayout();
    method public static int generateViewId();
    method public int getAccessibilityLiveRegion();
    method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider();
    method public float getAlpha();
    method public android.view.animation.Animation getAnimation();
@@ -27742,6 +27744,7 @@ package android.view {
    method public void sendAccessibilityEvent(int);
    method public void sendAccessibilityEventUnchecked(android.view.accessibility.AccessibilityEvent);
    method public void setAccessibilityDelegate(android.view.View.AccessibilityDelegate);
    method public void setAccessibilityLiveRegion(int);
    method public void setActivated(boolean);
    method public void setAlpha(float);
    method public void setAnimation(android.view.animation.Animation);
@@ -27847,6 +27850,9 @@ package android.view {
    method protected boolean verifyDrawable(android.graphics.drawable.Drawable);
    method public boolean willNotCacheDrawing();
    method public boolean willNotDraw();
    field public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 2; // 0x2
    field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
    field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
    field public static final android.util.Property ALPHA;
    field public static final int DRAWING_CACHE_QUALITY_AUTO = 0; // 0x0
    field public static final int DRAWING_CACHE_QUALITY_HIGH = 1048576; // 0x100000
@@ -28155,7 +28161,6 @@ package android.view {
    method public void bringChildToFront(android.view.View);
    method protected boolean canAnimate();
    method protected boolean checkLayoutParams(android.view.ViewGroup.LayoutParams);
    method public void childAccessibilityStateChanged(android.view.View);
    method public void childDrawableStateChanged(android.view.View);
    method public void childHasTransientStateChanged(android.view.View, boolean);
    method protected void cleanupLayoutState(android.view.View);
@@ -28204,6 +28209,7 @@ package android.view {
    method protected void measureChild(android.view.View, int, int);
    method protected void measureChildWithMargins(android.view.View, int, int, int, int);
    method protected void measureChildren(int, int);
    method public void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
    method public final void offsetDescendantRectToMyCoords(android.view.View, android.graphics.Rect);
    method public final void offsetRectIntoDescendantCoords(android.view.View, android.graphics.Rect);
    method public boolean onInterceptHoverEvent(android.view.MotionEvent);
@@ -28321,7 +28327,6 @@ package android.view {
    method public abstract boolean canResolveLayoutDirection();
    method public abstract boolean canResolveTextAlignment();
    method public abstract boolean canResolveTextDirection();
    method public abstract void childAccessibilityStateChanged(android.view.View);
    method public abstract void childDrawableStateChanged(android.view.View);
    method public abstract void childHasTransientStateChanged(android.view.View, boolean);
    method public abstract void clearChildFocus(android.view.View);
@@ -28340,6 +28345,7 @@ package android.view {
    method public abstract boolean isLayoutRequested();
    method public abstract boolean isTextAlignmentResolved();
    method public abstract boolean isTextDirectionResolved();
    method public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
    method public abstract void recomputeViewAttributes(android.view.View);
    method public abstract void requestChildFocus(android.view.View, android.view.View);
    method public abstract boolean requestChildRectangleOnScreen(android.view.View, android.graphics.Rect, boolean);
@@ -28765,7 +28771,7 @@ package android.view.accessibility {
    method public int describeContents();
    method public static java.lang.String eventTypeToString(int);
    method public int getAction();
    method public int getContentChangeType();
    method public int getContentChangeTypes();
    method public long getEventTime();
    method public int getEventType();
    method public int getMovementGranularity();
@@ -28777,14 +28783,16 @@ package android.view.accessibility {
    method public static android.view.accessibility.AccessibilityEvent obtain(android.view.accessibility.AccessibilityEvent);
    method public static android.view.accessibility.AccessibilityEvent obtain();
    method public void setAction(int);
    method public void setContentChangeType(int);
    method public void setContentChangeTypes(int);
    method public void setEventTime(long);
    method public void setEventType(int);
    method public void setMovementGranularity(int);
    method public void setPackageName(java.lang.CharSequence);
    method public void writeToParcel(android.os.Parcel, int);
    field public static final int CONTENT_CHANGE_TYPE_NODE = 1; // 0x1
    field public static final int CONTENT_CHANGE_TYPE_SUBTREE = 0; // 0x0
    field public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 4; // 0x4
    field public static final int CONTENT_CHANGE_TYPE_SUBTREE = 1; // 0x1
    field public static final int CONTENT_CHANGE_TYPE_TEXT = 2; // 0x2
    field public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0; // 0x0
    field public static final android.os.Parcelable.Creator CREATOR;
    field public static final int INVALID_POSITION = -1; // 0xffffffff
    field public static final deprecated int MAX_TEXT_LENGTH = 500; // 0x1f4
@@ -28857,6 +28865,7 @@ package android.view.accessibility {
    method public int getInputType();
    method public android.view.accessibility.AccessibilityNodeInfo getLabelFor();
    method public android.view.accessibility.AccessibilityNodeInfo getLabeledBy();
    method public int getLiveRegion();
    method public int getMovementGranularities();
    method public java.lang.CharSequence getPackageName();
    method public android.view.accessibility.AccessibilityNodeInfo getParent();
@@ -28874,11 +28883,8 @@ package android.view.accessibility {
    method public boolean isDismissable();
    method public boolean isEditable();
    method public boolean isEnabled();
    method public boolean isExpandable();
    method public boolean isExpanded();
    method public boolean isFocusable();
    method public boolean isFocused();
    method public boolean isLiveRegion();
    method public boolean isLongClickable();
    method public boolean isMultiLine();
    method public boolean isPassword();
@@ -28908,8 +28914,6 @@ package android.view.accessibility {
    method public void setDismissable(boolean);
    method public void setEditable(boolean);
    method public void setEnabled(boolean);
    method public void setExpandable(boolean);
    method public void setExpanded(boolean);
    method public void setFocusable(boolean);
    method public void setFocused(boolean);
    method public void setInputType(int);
@@ -28917,7 +28921,7 @@ package android.view.accessibility {
    method public void setLabelFor(android.view.View, int);
    method public void setLabeledBy(android.view.View);
    method public void setLabeledBy(android.view.View, int);
    method public void setLiveRegion(boolean);
    method public void setLiveRegion(int);
    method public void setLongClickable(boolean);
    method public void setMovementGranularities(int);
    method public void setMultiLine(boolean);
+164 −16
Original line number Diff line number Diff line
@@ -2133,6 +2133,50 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO)
        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
    /**
     * Shift for the bits in {@link #mPrivateFlags2} related to the
     * "accessibilityLiveRegion" attribute.
     */
    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 22;
    /**
     * Live region mode specifying that accessibility services should not
     * automatically announce changes to this view. This is the default live
     * region mode for most views.
     * <p>
     * Use with {@link #setAccessibilityLiveRegion(int)}.
     */
    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
    /**
     * Live region mode specifying that accessibility services should announce
     * changes to this view.
     * <p>
     * Use with {@link #setAccessibilityLiveRegion(int)}.
     */
    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
    /**
     * Live region mode specifying that accessibility services should interrupt
     * ongoing speech to immediately announce changes to this view.
     * <p>
     * Use with {@link #setAccessibilityLiveRegion(int)}.
     */
    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
    /**
     * The default whether the view is important for accessibility.
     */
    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
    /**
     * Mask for obtaining the bits which specify a view's accessibility live
     * region mode.
     */
    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
    /**
     * Flag indicating whether a view has accessibility focus.
     */
@@ -3763,6 +3807,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                    setImportantForAccessibility(a.getInt(attr,
                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
                    break;
                case R.styleable.View_accessibilityLiveRegion:
                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
                    break;
            }
        }
@@ -4710,7 +4757,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        if (gainFocus) {
            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
        } else {
            notifyViewAccessibilityStateChangedIfNeeded();
            notifyViewAccessibilityStateChangedIfNeeded(
                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
        }
        InputMethodManager imm = InputMethodManager.peekInstance();
@@ -5431,7 +5479,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
            notifySubtreeAccessibilityStateChangedIfNeeded();
        } else {
            notifyViewAccessibilityStateChangedIfNeeded();
            notifyViewAccessibilityStateChangedIfNeeded(
                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
        }
    }
@@ -6953,6 +7002,58 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
    }
    /**
     * Sets the live region mode for this view. This indicates to accessibility
     * services whether they should automatically notify the user about changes
     * to the view's content description or text, or to the content descriptions
     * or text of the view's children (where applicable).
     * <p>
     * For example, in a login screen with a TextView that displays an "incorrect
     * password" notification, that view should be marked as a live region with
     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
     * <p>
     * To disable change notifications for this view, use
     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
     * mode for most views.
     * <p>
     * To indicate that the user should be notified of changes, use
     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
     * <p>
     * If the view's changes should interrupt ongoing speech and notify the user
     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
     *
     * @param mode The live region mode for this view, one of:
     *        <ul>
     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
     *        </ul>
     * @attr ref android.R.styleable#View_accessibilityLiveRegion
     */
    public void setAccessibilityLiveRegion(int mode) {
        if (mode != getAccessibilityLiveRegion()) {
            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
            notifyViewAccessibilityStateChangedIfNeeded(
                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
        }
    }
    /**
     * Gets the live region mode for this View.
     *
     * @return The live region mode for the view.
     *
     * @attr ref android.R.styleable#View_accessibilityLiveRegion
     *
     * @see #setAccessibilityLiveRegion(int)
     */
    public int getAccessibilityLiveRegion() {
        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
    }
    /**
     * Sets how to determine whether this view is important for accessibility
     * which is if it fires accessibility events and if it is reported to
@@ -6975,7 +7076,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            if (oldIncludeForAccessibility != includeForAccessibility()) {
                notifySubtreeAccessibilityStateChangedIfNeeded();
            } else {
                notifyViewAccessibilityStateChangedIfNeeded();
                notifyViewAccessibilityStateChangedIfNeeded(
                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
            }
        }
    }
@@ -6997,7 +7099,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                return false;
            case IMPORTANT_FOR_ACCESSIBILITY_AUTO:
                return isActionableForAccessibility() || hasListenersForAccessibility()
                        || getAccessibilityNodeProvider() != null;
                        || getAccessibilityNodeProvider() != null
                        || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
            default:
                throw new IllegalArgumentException("Unknow important for accessibility mode: "
                        + mode);
@@ -7094,7 +7197,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     *
     * @hide
     */
    public void notifyViewAccessibilityStateChangedIfNeeded() {
    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
            return;
        }
@@ -7102,7 +7205,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            mSendViewStateChangedAccessibilityEvent =
                    new SendViewStateChangedAccessibilityEvent();
        }
        mSendViewStateChangedAccessibilityEvent.runOrPost();
        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
    }
    /**
@@ -7124,7 +7227,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
            if (mParent != null) {
                try {
                    mParent.childAccessibilityStateChanged(this);
                    mParent.notifySubtreeAccessibilityStateChanged(
                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
                } catch (AbstractMethodError e) {
                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                            " does not fully implement ViewParent", e);
@@ -7251,7 +7355,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                        || getAccessibilitySelectionEnd() != end)
                        && (start == end)) {
                    setAccessibilitySelection(start, end);
                    notifyViewAccessibilityStateChangedIfNeeded();
                    notifyViewAccessibilityStateChangedIfNeeded(
                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
                    return true;
                }
            } break;
@@ -8825,11 +8930,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                if (oldIncludeForAccessibility != includeForAccessibility()) {
                    notifySubtreeAccessibilityStateChangedIfNeeded();
                } else {
                    notifyViewAccessibilityStateChangedIfNeeded();
                    notifyViewAccessibilityStateChangedIfNeeded(
                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
                }
            }
            if ((changed & ENABLED_MASK) != 0) {
                notifyViewAccessibilityStateChangedIfNeeded();
            } else if ((changed & ENABLED_MASK) != 0) {
                notifyViewAccessibilityStateChangedIfNeeded(
                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
            }
        }
    }
@@ -15430,7 +15536,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            invalidate(true);
            refreshDrawableState();
            dispatchSetSelected(selected);
            notifyViewAccessibilityStateChangedIfNeeded();
            notifyViewAccessibilityStateChangedIfNeeded(
                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
        }
    }
@@ -19172,21 +19279,44 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    }
    private class SendViewStateChangedAccessibilityEvent implements Runnable {
        private int mChangeTypes = 0;
        private boolean mPosted;
        private boolean mPostedWithDelay;
        private long mLastEventTimeMillis;
        @Override
        public void run() {
            mPosted = false;
            mPostedWithDelay = false;
            mLastEventTimeMillis = SystemClock.uptimeMillis();
            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
                AccessibilityEvent event = AccessibilityEvent.obtain();
                final AccessibilityEvent event = AccessibilityEvent.obtain();
                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
                event.setContentChangeType(AccessibilityEvent.CONTENT_CHANGE_TYPE_NODE);
                event.setContentChangeTypes(mChangeTypes);
                sendAccessibilityEventUnchecked(event);
            }
            mChangeTypes = 0;
        }
        public void runOrPost(int changeType) {
            mChangeTypes |= changeType;
            // If this is a live region or the child of a live region, collect
            // all events from this frame and send them on the next frame.
            if (inLiveRegion()) {
                // If we're already posted with a delay, remove that.
                if (mPostedWithDelay) {
                    removeCallbacks(this);
                    mPostedWithDelay = false;
                }
                // Only post if we're not already posted.
                if (!mPosted) {
                    post(this);
                    mPosted = true;
                }
                return;
            }
        public void runOrPost() {
            if (mPosted) {
                return;
            }
@@ -19199,8 +19329,26 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            } else {
                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
                mPosted = true;
                mPostedWithDelay = true;
            }
        }
    }
    private boolean inLiveRegion() {
        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
            return true;
        }
        ViewParent parent = getParent();
        while (parent instanceof View) {
            if (((View) parent).getAccessibilityLiveRegion()
                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
                return true;
            }
            parent = parent.getParent();
        }
        return false;
    }
    /**
+8 −3
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import android.util.Log;
import android.util.Pools.SynchronizedPool;
import android.util.SparseArray;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
@@ -2528,10 +2529,14 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
    }

    @Override
    public void childAccessibilityStateChanged(View root) {
        if (mParent != null) {
    public void notifySubtreeAccessibilityStateChanged(View child, View source, int changeType) {
        // If this is a live region, we should send a subtree change event
        // from this view. Otherwise, we can let it propagate up.
        if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
            notifyViewAccessibilityStateChangedIfNeeded(changeType);
        } else if (mParent != null) {
            try {
                mParent.childAccessibilityStateChanged(root);
                mParent.notifySubtreeAccessibilityStateChanged(this, source, changeType);
            } catch (AbstractMethodError e) {
                Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                        " does not fully implement ViewParent", e);
+15 −6
Original line number Diff line number Diff line
@@ -309,12 +309,21 @@ public interface ViewParent {
    public ViewParent getParentForAccessibility();

    /**
     * A child notifies its parent that the accessibility state of a subtree rooted
     * at a given node changed. That is the structure of the subtree is different.
     *
     * @param root The root of the changed subtree.
     * Notifies a view parent that the accessibility state of one of its
     * descendants has changed and that the structure of the subtree is
     * different.
     * @param child The direct child whose subtree has changed.
     * @param source The descendant view that changed.
     * @param changeType A bit mask of the types of changes that occurred. One
     *            or more of:
     *            <ul>
     *            <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION}
     *            <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_SUBTREE}
     *            <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_TEXT}
     *            <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_UNDEFINED}
     *            </ul>
     */
    public void childAccessibilityStateChanged(View root);
    public void notifySubtreeAccessibilityStateChanged(View child, View source, int changeType);

    /**
     * Tells if this view parent can resolve the layout direction.
+11 −6
Original line number Diff line number Diff line
@@ -5807,12 +5807,12 @@ public final class ViewRootImpl implements ViewParent,
     * This event is send at most once every
     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
     */
    private void postSendWindowContentChangedCallback(View source) {
    private void postSendWindowContentChangedCallback(View source, int changeType) {
        if (mSendWindowContentChangedAccessibilityEvent == null) {
            mSendWindowContentChangedAccessibilityEvent =
                new SendWindowContentChangedAccessibilityEvent();
        }
        mSendWindowContentChangedAccessibilityEvent.runOrPost(source);
        mSendWindowContentChangedAccessibilityEvent.runOrPost(source, changeType);
    }

    /**
@@ -5884,8 +5884,8 @@ public final class ViewRootImpl implements ViewParent,
    }

    @Override
    public void childAccessibilityStateChanged(View child) {
        postSendWindowContentChangedCallback(child);
    public void notifySubtreeAccessibilityStateChanged(View child, View source, int changeType) {
        postSendWindowContentChangedCallback(source, changeType);
    }

    @Override
@@ -6538,6 +6538,8 @@ public final class ViewRootImpl implements ViewParent,
    }

    private class SendWindowContentChangedAccessibilityEvent implements Runnable {
        private int mChangeTypes = 0;

        public View mSource;
        public long mLastEventTimeMillis;

@@ -6548,7 +6550,7 @@ public final class ViewRootImpl implements ViewParent,
                mLastEventTimeMillis = SystemClock.uptimeMillis();
                AccessibilityEvent event = AccessibilityEvent.obtain();
                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
                event.setContentChangeType(AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
                event.setContentChangeTypes(mChangeTypes);
                mSource.sendAccessibilityEventUnchecked(event);
            } else {
                mLastEventTimeMillis = 0;
@@ -6556,17 +6558,20 @@ public final class ViewRootImpl implements ViewParent,
            // In any case reset to initial state.
            mSource.resetSubtreeAccessibilityStateChanged();
            mSource = null;
            mChangeTypes = 0;
        }

        public void runOrPost(View source) {
        public void runOrPost(View source, int changeType) {
            if (mSource != null) {
                // If there is no common predecessor, then mSource points to
                // a removed view, hence in this case always prefer the source.
                View predecessor = getCommonPredecessor(mSource, source);
                mSource = (predecessor != null) ? predecessor : source;
                mChangeTypes |= changeType;
                return;
            }
            mSource = source;
            mChangeTypes = changeType;
            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
            final long minEventIntevalMillis =
                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
Loading