diff options
Diffstat (limited to 'core/java/android/view/ViewRootImpl.java')
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 158 |
1 files changed, 33 insertions, 125 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 6c5091c28708..f81a4c33271a 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -89,9 +89,11 @@ import android.view.accessibility.AccessibilityManager.HighTextContrastChangeLis import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.AccessibilityNodeProvider; +import android.view.accessibility.AccessibilityViewHierarchyState; import android.view.accessibility.AccessibilityWindowInfo; import android.view.accessibility.IAccessibilityInteractionConnection; import android.view.accessibility.IAccessibilityInteractionConnectionCallback; +import android.view.accessibility.ThrottlingAccessibilityEventSender; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.Interpolator; import android.view.inputmethod.InputMethodManager; @@ -113,7 +115,6 @@ import java.io.OutputStream; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.HashSet; import java.util.concurrent.CountDownLatch; /** @@ -460,10 +461,6 @@ public final class ViewRootImpl implements ViewParent, new AccessibilityInteractionConnectionManager(); final HighContrastTextManager mHighContrastTextManager; - SendWindowContentChangedAccessibilityEvent mSendWindowContentChangedAccessibilityEvent; - - HashSet<View> mTempHashSet; - private final int mDensity; private final int mNoncompatDensity; @@ -478,6 +475,8 @@ public final class ViewRootImpl implements ViewParent, private boolean mNeedsRendererSetup; + protected AccessibilityViewHierarchyState mAccessibilityState; + /** * Consistency verifier for debugging purposes. */ @@ -7262,11 +7261,9 @@ public final class ViewRootImpl implements ViewParent, * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}. */ private void postSendWindowContentChangedCallback(View source, int changeType) { - if (mSendWindowContentChangedAccessibilityEvent == null) { - mSendWindowContentChangedAccessibilityEvent = - new SendWindowContentChangedAccessibilityEvent(); - } - mSendWindowContentChangedAccessibilityEvent.runOrPost(source, changeType); + getAccessibilityState() + .getSendWindowContentChangedAccessibilityEvent() + .runOrPost(source, changeType); } /** @@ -7274,9 +7271,18 @@ public final class ViewRootImpl implements ViewParent, * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event. */ private void removeSendWindowContentChangedCallback() { - if (mSendWindowContentChangedAccessibilityEvent != null) { - mHandler.removeCallbacks(mSendWindowContentChangedAccessibilityEvent); + if (mAccessibilityState != null + && mAccessibilityState.isWindowContentChangedEventSenderInitialized()) { + ThrottlingAccessibilityEventSender.cancelIfPending( + mAccessibilityState.getSendWindowContentChangedAccessibilityEvent()); + } + } + + AccessibilityViewHierarchyState getAccessibilityState() { + if (mAccessibilityState == null) { + mAccessibilityState = new AccessibilityViewHierarchyState(); } + return mAccessibilityState; } @Override @@ -7314,12 +7320,8 @@ public final class ViewRootImpl implements ViewParent, return false; } - // Immediately flush pending content changed event (if any) to preserve event order - if (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED - && mSendWindowContentChangedAccessibilityEvent != null - && mSendWindowContentChangedAccessibilityEvent.mSource != null) { - mSendWindowContentChangedAccessibilityEvent.removeCallbacksAndRun(); - } + // Send any pending event to prevent reordering + flushPendingAccessibilityEvents(); // Intercept accessibility focus events fired by virtual nodes to keep // track of accessibility focus position in such nodes. @@ -7363,6 +7365,19 @@ public final class ViewRootImpl implements ViewParent, return true; } + /** @hide */ + public void flushPendingAccessibilityEvents() { + if (mAccessibilityState != null) { + if (mAccessibilityState.isScrollEventSenderInitialized()) { + mAccessibilityState.getSendViewScrolledAccessibilityEvent().sendNowIfPending(); + } + if (mAccessibilityState.isWindowContentChangedEventSenderInitialized()) { + mAccessibilityState.getSendWindowContentChangedAccessibilityEvent() + .sendNowIfPending(); + } + } + } + /** * Updates the focused virtual view, when necessary, in response to a * content changed event. @@ -7497,39 +7512,6 @@ public final class ViewRootImpl implements ViewParent, return View.TEXT_ALIGNMENT_RESOLVED_DEFAULT; } - private View getCommonPredecessor(View first, View second) { - if (mTempHashSet == null) { - mTempHashSet = new HashSet<View>(); - } - HashSet<View> seen = mTempHashSet; - seen.clear(); - View firstCurrent = first; - while (firstCurrent != null) { - seen.add(firstCurrent); - ViewParent firstCurrentParent = firstCurrent.mParent; - if (firstCurrentParent instanceof View) { - firstCurrent = (View) firstCurrentParent; - } else { - firstCurrent = null; - } - } - View secondCurrent = second; - while (secondCurrent != null) { - if (seen.contains(secondCurrent)) { - seen.clear(); - return secondCurrent; - } - ViewParent secondCurrentParent = secondCurrent.mParent; - if (secondCurrentParent instanceof View) { - secondCurrent = (View) secondCurrentParent; - } else { - secondCurrent = null; - } - } - seen.clear(); - return null; - } - void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( @@ -8140,80 +8122,6 @@ public final class ViewRootImpl implements ViewParent, } } - private class SendWindowContentChangedAccessibilityEvent implements Runnable { - private int mChangeTypes = 0; - - public View mSource; - public long mLastEventTimeMillis; - - @Override - public void run() { - // Protect against re-entrant code and attempt to do the right thing in the case that - // we're multithreaded. - View source = mSource; - mSource = null; - if (source == null) { - Log.e(TAG, "Accessibility content change has no source"); - return; - } - // The accessibility may be turned off while we were waiting so check again. - if (AccessibilityManager.getInstance(mContext).isEnabled()) { - mLastEventTimeMillis = SystemClock.uptimeMillis(); - AccessibilityEvent event = AccessibilityEvent.obtain(); - event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); - event.setContentChangeTypes(mChangeTypes); - source.sendAccessibilityEventUnchecked(event); - } else { - mLastEventTimeMillis = 0; - } - // In any case reset to initial state. - source.resetSubtreeAccessibilityStateChanged(); - mChangeTypes = 0; - } - - public void runOrPost(View source, int changeType) { - if (mHandler.getLooper() != Looper.myLooper()) { - CalledFromWrongThreadException e = new CalledFromWrongThreadException("Only the " - + "original thread that created a view hierarchy can touch its views."); - // TODO: Throw the exception - Log.e(TAG, "Accessibility content change on non-UI thread. Future Android " - + "versions will throw an exception.", e); - // Attempt to recover. This code does not eliminate the thread safety issue, but - // it should force any issues to happen near the above log. - mHandler.removeCallbacks(this); - if (mSource != null) { - // Dispatch whatever was pending. It's still possible that the runnable started - // just before we removed the callbacks, and bad things will happen, but at - // least they should happen very close to the logged error. - run(); - } - } - 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(); - if (timeSinceLastMillis >= minEventIntevalMillis) { - removeCallbacksAndRun(); - } else { - mHandler.postDelayed(this, minEventIntevalMillis - timeSinceLastMillis); - } - } - - public void removeCallbacksAndRun() { - mHandler.removeCallbacks(this); - run(); - } - } - private static class KeyFallbackManager { // This is used to ensure that key-fallback events are only dispatched once. We attempt |
