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

Commit 72c510f1 authored by Eugene Susla's avatar Eugene Susla
Browse files

Revert "Move A11y events throttling away from View(RootImpl)"

This reverts commit e4d31b3c.

Fixes: 71904218
Test: presubmit
Change-Id: Id73bde1a0c11696cf561c84cde027cdca4c6a00f
parent f4c5faf9
Loading
Loading
Loading
Loading
+3 −12
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.accessibilityservice.IAccessibilityServiceConnection;
import android.annotation.NonNull;
import android.annotation.TestApi;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
@@ -46,14 +47,10 @@ import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;

import com.android.internal.util.CollectionUtils;

import libcore.io.IoUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeoutException;

@@ -583,8 +580,6 @@ public final class UiAutomation {
        // Execute the command *without* the lock being held.
        command.run();

        List<AccessibilityEvent> eventsReceived = Collections.emptyList();

        // Acquire the lock and wait for the event.
        try {
            // Wait for the event.
@@ -605,14 +600,14 @@ public final class UiAutomation {
                    if (filter.accept(event)) {
                        return event;
                    }
                    eventsReceived = CollectionUtils.add(eventsReceived, event);
                    event.recycle();
                }
                // Check if timed out and if not wait.
                final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
                final long remainingTimeMillis = timeoutMillis - elapsedTimeMillis;
                if (remainingTimeMillis <= 0) {
                    throw new TimeoutException("Expected event not received within: "
                            + timeoutMillis + " ms, among " + eventsReceived);
                            + timeoutMillis + " ms.");
                }
                synchronized (mLock) {
                    if (mEventQueue.isEmpty()) {
@@ -625,10 +620,6 @@ public final class UiAutomation {
                }
            }
        } finally {
            for (int i = 0; i < CollectionUtils.size(eventsReceived); i++) {
                AccessibilityEvent event = eventsReceived.get(i);
                event.recycle();
            }
            synchronized (mLock) {
                mWaitingForEventDelivery = false;
                mEventQueue.clear();
+151 −75
Original line number Diff line number Diff line
@@ -4442,6 +4442,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    private CheckForLongPress mPendingCheckForLongPress;
    private CheckForTap mPendingCheckForTap = null;
    private PerformClick mPerformClick;
    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
    private UnsetPressedState mUnsetPressedState;
@@ -7201,7 +7202,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        if (gainFocus) {
            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
        } else {
            notifyAccessibilityStateChanged(
            notifyViewAccessibilityStateChangedIfNeeded(
                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
        }
@@ -7271,7 +7272,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    public void setAccessibilityPaneTitle(CharSequence accessibilityPaneTitle) {
        if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) {
            mAccessibilityPaneTitle = accessibilityPaneTitle;
            notifyAccessibilityStateChanged(AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
            notifyViewAccessibilityStateChangedIfNeeded(
                    AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
        }
    }
@@ -8924,9 +8926,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
            notifyAccessibilitySubtreeChanged();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        } else {
            notifyAccessibilityStateChanged(
            notifyViewAccessibilityStateChangedIfNeeded(
                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
        }
    }
@@ -8959,7 +8961,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            return;
        }
        mAccessibilityTraversalBeforeId = beforeId;
        notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
        notifyViewAccessibilityStateChangedIfNeeded(
                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
    }
    /**
@@ -9002,7 +9005,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            return;
        }
        mAccessibilityTraversalAfterId = afterId;
        notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
        notifyViewAccessibilityStateChangedIfNeeded(
                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
    }
    /**
@@ -9044,7 +9048,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                && mID == View.NO_ID) {
            mID = generateViewId();
        }
        notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
        notifyViewAccessibilityStateChangedIfNeeded(
                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
    }
    /**
@@ -10544,7 +10549,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        if (pflags3 != mPrivateFlags3) {
            mPrivateFlags3 = pflags3;
            notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
            notifyViewAccessibilityStateChangedIfNeeded(
                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
        }
    }
@@ -11374,7 +11380,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
            notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
            notifyViewAccessibilityStateChangedIfNeeded(
                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
        }
    }
@@ -11431,9 +11438,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
                notifyAccessibilitySubtreeChanged();
                notifySubtreeAccessibilityStateChangedIfNeeded();
            } else {
                notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
                notifyViewAccessibilityStateChangedIfNeeded(
                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
            }
        }
    }
@@ -11609,32 +11617,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     *
     * @hide
     */
    public void notifyAccessibilityStateChanged(int changeType) {
        notifyAccessibilityStateChanged(this, changeType);
    }
    /**
     * Notifies that the accessibility state of this view changed. The change
     * is *not* local to this view and does represent structural changes such
     * as children and parent. For example, the view size changed. The
     * notification is at at most once every
     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
     * to avoid unnecessary load to the system. Also once a view has a pending
     * notification this method is a NOP until the notification has been sent.
     *
     * @hide
     */
    public void notifyAccessibilitySubtreeChanged() {
        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
            notifyAccessibilityStateChanged(AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
        }
    }
    void notifyAccessibilityStateChanged(View source, int changeType) {
    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
            return;
        }
        // Changes to views with a pane title count as window state changes, as the pane title
        // marks them as significant parts of the UI.
        if (!TextUtils.isEmpty(getAccessibilityPaneTitle())) {
@@ -11652,12 +11639,49 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            }
        }
        // If this is a live region, we should send a subtree change event
        // from this view immediately. Otherwise, we can let it propagate up.
        if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
            final AccessibilityEvent event = AccessibilityEvent.obtain();
            event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
            event.setContentChangeTypes(changeType);
            sendAccessibilityEventUnchecked(event);
        } else if (mParent != null) {
            try {
                mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
            } catch (AbstractMethodError e) {
                Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                        " does not fully implement ViewParent", e);
            }
        }
    }
    /**
     * Notifies that the accessibility state of this view changed. The change
     * is *not* local to this view and does represent structural changes such
     * as children and parent. For example, the view size changed. The
     * notification is at at most once every
     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
     * to avoid unnecessary load to the system. Also once a view has a pending
     * notification this method is a NOP until the notification has been sent.
     *
     * @hide
     */
    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
            return;
        }
        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
            if (mParent != null) {
                try {
                mParent.notifySubtreeAccessibilityStateChanged(this, source, changeType);
                    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);
                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                            " does not fully implement ViewParent", e);
                }
            }
        }
    }
@@ -11679,10 +11703,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    /**
     * Reset the flag indicating the accessibility state of the subtree rooted
     * at this view changed.
     *
     * @hide
     */
    public void resetSubtreeAccessibilityStateChanged() {
    void resetSubtreeAccessibilityStateChanged() {
        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
    }
@@ -11843,7 +11865,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                        || getAccessibilitySelectionEnd() != end)
                        && (start == end)) {
                    setAccessibilitySelection(start, end);
                    notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
                    notifyViewAccessibilityStateChangedIfNeeded(
                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
                    return true;
                }
            } break;
@@ -12643,7 +12666,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        }
        if (!TextUtils.isEmpty(getAccessibilityPaneTitle())) {
            if (isVisible != oldVisible) {
                notifyAccessibilityStateChanged(isVisible
                notifyViewAccessibilityStateChangedIfNeeded(isVisible
                        ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
                        : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
            }
@@ -13860,7 +13883,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
                }
                notifyAccessibilitySubtreeChanged();
                notifySubtreeAccessibilityStateChangedIfNeeded();
            }
        }
@@ -13906,12 +13929,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
                    || (changed & CONTEXT_CLICKABLE) != 0) {
                if (oldIncludeForAccessibility != includeForAccessibility()) {
                    notifyAccessibilitySubtreeChanged();
                    notifySubtreeAccessibilityStateChangedIfNeeded();
                } else {
                    notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
                    notifyViewAccessibilityStateChangedIfNeeded(
                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
                }
            } else if ((changed & ENABLED_MASK) != 0) {
                notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
                notifyViewAccessibilityStateChangedIfNeeded(
                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
            }
        }
    }
@@ -13945,13 +13970,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @param oldt Previous vertical scroll origin.
     */
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        notifyAccessibilitySubtreeChanged();
        notifySubtreeAccessibilityStateChangedIfNeeded();
        ViewRootImpl root = getViewRootImpl();
        if (root != null) {
            root.getAccessibilityState()
                    .getSendViewScrolledAccessibilityEvent()
                    .post(this, /* dx */ l - oldl, /* dy */ t - oldt);
        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
            postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt);
        }
        mBackgroundSizeChanged = true;
@@ -14347,7 +14369,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
            notifyAccessibilitySubtreeChanged();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
@@ -14391,7 +14413,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
            notifyAccessibilitySubtreeChanged();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
@@ -14435,7 +14457,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
            notifyAccessibilitySubtreeChanged();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
@@ -14472,7 +14494,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
            notifyAccessibilitySubtreeChanged();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
@@ -14509,7 +14531,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
            notifyAccessibilitySubtreeChanged();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
@@ -14712,7 +14734,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        if (mTransformationInfo.mAlpha != alpha) {
            // Report visibility changes, which can affect children, to accessibility
            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
                notifyAccessibilitySubtreeChanged();
                notifySubtreeAccessibilityStateChangedIfNeeded();
            }
            mTransformationInfo.mAlpha = alpha;
            if (onSetAlpha((int) (alpha * 255))) {
@@ -15214,7 +15236,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
            notifyAccessibilitySubtreeChanged();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
@@ -15248,7 +15270,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            invalidateViewProperty(false, true);
            invalidateParentIfNeededAndWasQuickRejected();
            notifyAccessibilitySubtreeChanged();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
@@ -15418,7 +15440,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    public void invalidateOutline() {
        rebuildOutline();
        notifyAccessibilitySubtreeChanged();
        notifySubtreeAccessibilityStateChangedIfNeeded();
        invalidateViewProperty(false, false);
    }
@@ -15613,7 +15635,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                }
                invalidateParentIfNeeded();
            }
            notifyAccessibilitySubtreeChanged();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
@@ -15661,7 +15683,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                }
                invalidateParentIfNeeded();
            }
            notifyAccessibilitySubtreeChanged();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }
@@ -16538,6 +16560,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        }
    }
    /**
     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
     * This event is sent at most once every
     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
     */
    private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) {
        if (mSendViewScrolledAccessibilityEvent == null) {
            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
        }
        mSendViewScrolledAccessibilityEvent.post(dx, dy);
    }
    /**
     * Called by a parent to request that a child update its values for mScrollX
     * and mScrollY if necessary. This will typically be done if the child is
@@ -17793,13 +17827,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        removeUnsetPressCallback();
        removeLongPressCallback();
        removePerformClickCallback();
        if (mAttachInfo != null
                && mAttachInfo.mViewRootImpl.mAccessibilityState != null
                && mAttachInfo.mViewRootImpl.mAccessibilityState.isScrollEventSenderInitialized()) {
            mAttachInfo.mViewRootImpl.mAccessibilityState
                    .getSendViewScrolledAccessibilityEvent()
                    .cancelIfPendingFor(this);
        }
        cancel(mSendViewScrolledAccessibilityEvent);
        stopNestedScroll();
        // Anything that started animating right before detach should already
@@ -20427,7 +20455,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                mForegroundInfo.mBoundsChanged = true;
            }
            notifyAccessibilitySubtreeChanged();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
        return changed;
    }
@@ -21871,7 +21899,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            if (selected) {
                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
            } else {
                notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
                notifyViewAccessibilityStateChangedIfNeeded(
                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
            }
        }
    }
@@ -26457,6 +26486,53 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        }
    }
    /**
     * Resuable callback for sending
     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
     */
    private class SendViewScrolledAccessibilityEvent implements Runnable {
        public volatile boolean mIsPending;
        public int mDeltaX;
        public int mDeltaY;
        public void post(int dx, int dy) {
            mDeltaX += dx;
            mDeltaY += dy;
            if (!mIsPending) {
                mIsPending = true;
                postDelayed(this, ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
            }
        }
        @Override
        public void run() {
            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
                AccessibilityEvent event = AccessibilityEvent.obtain(
                        AccessibilityEvent.TYPE_VIEW_SCROLLED);
                event.setScrollDeltaX(mDeltaX);
                event.setScrollDeltaY(mDeltaY);
                sendAccessibilityEventUnchecked(event);
            }
            reset();
        }
        private void reset() {
            mIsPending = false;
            mDeltaX = 0;
            mDeltaY = 0;
        }
    }
    /**
     * Remove the pending callback for sending a
     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
     */
    private void cancel(@Nullable SendViewScrolledAccessibilityEvent callback) {
        if (callback == null || !callback.mIsPending) return;
        removeCallbacks(callback);
        callback.reset();
    }
    /**
     * <p>
     * This class represents a delegate that can be registered in a {@link View}
@@ -27074,7 +27150,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
        mAttachInfo.mTooltipHost = this;
        // The available accessibility actions have changed
        notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
        notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
        return true;
    }
@@ -27094,7 +27170,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            mAttachInfo.mTooltipHost = null;
        }
        // The available accessibility actions have changed
        notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
        notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
    }
    private boolean showLongClickTooltip(int x, int y) {
+26 −16
Original line number Diff line number Diff line
@@ -3649,34 +3649,44 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        return ViewGroup.class.getName();
    }

    @Override
    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(
                    AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
        } else if (mParent != null) {
            try {
                mParent.notifySubtreeAccessibilityStateChanged(this, source, changeType);
            } catch (AbstractMethodError e) {
                Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                        " does not fully implement ViewParent", e);
            }
        }
    }

    /** @hide */
    @Override
    public void notifyAccessibilitySubtreeChanged() {
    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
            return;
        }
        // If something important for a11y is happening in this subtree, make sure it's dispatched
        // from a view that is important for a11y so it doesn't get lost.
        if (getImportantForAccessibility() != IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
                && !isImportantForAccessibility()
                && getChildCount() > 0) {
        if ((getImportantForAccessibility() != IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
                && !isImportantForAccessibility() && (getChildCount() > 0)) {
            ViewParent a11yParent = getParentForAccessibility();
            if (a11yParent instanceof View) {
                ((View) a11yParent).notifyAccessibilitySubtreeChanged();
                ((View) a11yParent).notifySubtreeAccessibilityStateChangedIfNeeded();
                return;
            }
        }
        super.notifyAccessibilitySubtreeChanged();
        super.notifySubtreeAccessibilityStateChangedIfNeeded();
    }

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

    /** @hide */
    @Override
    public void resetSubtreeAccessibilityStateChanged() {
    void resetSubtreeAccessibilityStateChanged() {
        super.resetSubtreeAccessibilityStateChanged();
        View[] children = mChildren;
        final int childCount = mChildrenCount;
@@ -5088,7 +5098,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        }

        if (child.getVisibility() != View.GONE) {
            notifyAccessibilitySubtreeChanged();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }

        if (mTransientIndices != null) {
@@ -5358,7 +5368,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        dispatchViewRemoved(view);

        if (view.getVisibility() != View.GONE) {
            notifyAccessibilitySubtreeChanged();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }

        int transientCount = mTransientIndices == null ? 0 : mTransientIndices.size();
@@ -6077,7 +6087,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        if (invalidate) {
            invalidateViewProperty(false, false);
        }
        notifyAccessibilitySubtreeChanged();
        notifySubtreeAccessibilityStateChangedIfNeeded();
    }

    @Override
Loading