Loading core/java/android/app/UiAutomation.java +3 −12 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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. Loading @@ -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()) { Loading @@ -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(); Loading core/java/android/view/View.java +151 −75 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } Loading Loading @@ -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); } } Loading Loading @@ -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); } } Loading Loading @@ -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); } /** Loading Loading @@ -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); } /** Loading Loading @@ -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); } /** Loading Loading @@ -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); } } Loading Loading @@ -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); } } Loading Loading @@ -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); } } } Loading Loading @@ -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())) { Loading @@ -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); } } } } Loading @@ -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; } Loading Loading @@ -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; Loading Loading @@ -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); } Loading Loading @@ -13860,7 +13883,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) { dispatchVisibilityAggregated(newVisibility == VISIBLE); } notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -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); } } } Loading Loading @@ -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; Loading Loading @@ -14347,7 +14369,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidateViewProperty(false, true); invalidateParentIfNeededAndWasQuickRejected(); notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -14391,7 +14413,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidateViewProperty(false, true); invalidateParentIfNeededAndWasQuickRejected(); notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -14435,7 +14457,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidateViewProperty(false, true); invalidateParentIfNeededAndWasQuickRejected(); notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -14472,7 +14494,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidateViewProperty(false, true); invalidateParentIfNeededAndWasQuickRejected(); notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -14509,7 +14531,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidateViewProperty(false, true); invalidateParentIfNeededAndWasQuickRejected(); notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -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))) { Loading Loading @@ -15214,7 +15236,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidateViewProperty(false, true); invalidateParentIfNeededAndWasQuickRejected(); notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -15248,7 +15270,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidateViewProperty(false, true); invalidateParentIfNeededAndWasQuickRejected(); notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -15418,7 +15440,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, public void invalidateOutline() { rebuildOutline(); notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); invalidateViewProperty(false, false); } Loading Loading @@ -15613,7 +15635,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } invalidateParentIfNeeded(); } notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -15661,7 +15683,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } invalidateParentIfNeeded(); } notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -20427,7 +20455,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mForegroundInfo.mBoundsChanged = true; } notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } return changed; } Loading Loading @@ -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); } } } Loading Loading @@ -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} Loading Loading @@ -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; } Loading @@ -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) { core/java/android/view/ViewGroup.java +26 −16 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -5088,7 +5098,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } if (child.getVisibility() != View.GONE) { notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } if (mTransientIndices != null) { Loading Loading @@ -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(); Loading Loading @@ -6077,7 +6087,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (invalidate) { invalidateViewProperty(false, false); } notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } @Override Loading Loading
core/java/android/app/UiAutomation.java +3 −12 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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. Loading @@ -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()) { Loading @@ -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(); Loading
core/java/android/view/View.java +151 −75 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } Loading Loading @@ -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); } } Loading Loading @@ -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); } } Loading Loading @@ -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); } /** Loading Loading @@ -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); } /** Loading Loading @@ -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); } /** Loading Loading @@ -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); } } Loading Loading @@ -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); } } Loading Loading @@ -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); } } } Loading Loading @@ -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())) { Loading @@ -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); } } } } Loading @@ -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; } Loading Loading @@ -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; Loading Loading @@ -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); } Loading Loading @@ -13860,7 +13883,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) { dispatchVisibilityAggregated(newVisibility == VISIBLE); } notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -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); } } } Loading Loading @@ -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; Loading Loading @@ -14347,7 +14369,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidateViewProperty(false, true); invalidateParentIfNeededAndWasQuickRejected(); notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -14391,7 +14413,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidateViewProperty(false, true); invalidateParentIfNeededAndWasQuickRejected(); notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -14435,7 +14457,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidateViewProperty(false, true); invalidateParentIfNeededAndWasQuickRejected(); notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -14472,7 +14494,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidateViewProperty(false, true); invalidateParentIfNeededAndWasQuickRejected(); notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -14509,7 +14531,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidateViewProperty(false, true); invalidateParentIfNeededAndWasQuickRejected(); notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -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))) { Loading Loading @@ -15214,7 +15236,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidateViewProperty(false, true); invalidateParentIfNeededAndWasQuickRejected(); notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -15248,7 +15270,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidateViewProperty(false, true); invalidateParentIfNeededAndWasQuickRejected(); notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -15418,7 +15440,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, public void invalidateOutline() { rebuildOutline(); notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); invalidateViewProperty(false, false); } Loading Loading @@ -15613,7 +15635,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } invalidateParentIfNeeded(); } notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -15661,7 +15683,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } invalidateParentIfNeeded(); } notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } } Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -20427,7 +20455,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mForegroundInfo.mBoundsChanged = true; } notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } return changed; } Loading Loading @@ -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); } } } Loading Loading @@ -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} Loading Loading @@ -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; } Loading @@ -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) {
core/java/android/view/ViewGroup.java +26 −16 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -5088,7 +5098,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } if (child.getVisibility() != View.GONE) { notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } if (mTransientIndices != null) { Loading Loading @@ -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(); Loading Loading @@ -6077,7 +6087,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (invalidate) { invalidateViewProperty(false, false); } notifyAccessibilitySubtreeChanged(); notifySubtreeAccessibilityStateChangedIfNeeded(); } @Override Loading