diff options
Diffstat (limited to 'core/java/android/view/ViewRootImpl.java')
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 138 |
1 files changed, 86 insertions, 52 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 1abcb15ca7a3..4f6679b2bc97 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -141,6 +141,7 @@ import android.util.AndroidRuntimeException; import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.EventLog; +import android.util.IndentingPrintWriter; import android.util.Log; import android.util.LongArray; import android.util.MergedConfiguration; @@ -202,6 +203,7 @@ import com.android.internal.view.SurfaceCallbackHelper; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; +import java.io.StringWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashSet; @@ -274,6 +276,11 @@ public final class ViewRootImpl implements ViewParent, */ private static final int CONTENT_CAPTURE_ENABLED_FALSE = 2; + /** + * Maximum time to wait for {@link View#dispatchScrollCaptureSearch} to complete. + */ + private static final int SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS = 2500; + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) static final ThreadLocal<HandlerActionQueue> sRunQueues = new ThreadLocal<HandlerActionQueue>(); @@ -668,8 +675,6 @@ public final class ViewRootImpl implements ViewParent, private final InsetsController mInsetsController; private final ImeFocusController mImeFocusController; - private ScrollCaptureConnection mScrollCaptureConnection; - private boolean mIsSurfaceOpaque; private final BackgroundBlurDrawable.Aggregator mBlurRegionAggregator = @@ -683,12 +688,6 @@ public final class ViewRootImpl implements ViewParent, return mImeFocusController; } - /** @return The current {@link ScrollCaptureConnection} for this instance, if any is active. */ - @Nullable - public ScrollCaptureConnection getScrollCaptureConnection() { - return mScrollCaptureConnection; - } - private final GestureExclusionTracker mGestureExclusionTracker = new GestureExclusionTracker(); private IAccessibilityEmbeddedConnection mAccessibilityEmbeddedConnection; @@ -730,6 +729,8 @@ public final class ViewRootImpl implements ViewParent, private HashSet<ScrollCaptureCallback> mRootScrollCaptureCallbacks; + private long mScrollCaptureRequestTimeout = SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS; + /** * Increment this value when the surface has been replaced. */ @@ -817,6 +818,8 @@ public final class ViewRootImpl implements ViewParent, mImeFocusController = new ImeFocusController(this); AudioManager audioManager = mContext.getSystemService(AudioManager.class); mFastScrollSoundEffectsEnabled = audioManager.areNavigationRepeatSoundEffectsEnabled(); + + mScrollCaptureRequestTimeout = SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS; } public static void addFirstDrawHandler(Runnable callback) { @@ -9223,9 +9226,9 @@ public final class ViewRootImpl implements ViewParent, * Collect and include any ScrollCaptureCallback instances registered with the window. * * @see #addScrollCaptureCallback(ScrollCaptureCallback) - * @param targets the search queue for targets + * @param results an object to collect the results of the search */ - private void collectRootScrollCaptureTargets(Queue<ScrollCaptureTarget> targets) { + private void collectRootScrollCaptureTargets(ScrollCaptureSearchResults results) { if (mRootScrollCaptureCallbacks == null) { return; } @@ -9233,26 +9236,45 @@ public final class ViewRootImpl implements ViewParent, // Add to the list for consideration Point offset = new Point(mView.getLeft(), mView.getTop()); Rect rect = new Rect(0, 0, mView.getWidth(), mView.getHeight()); - targets.add(new ScrollCaptureTarget(mView, rect, offset, cb)); + results.addTarget(new ScrollCaptureTarget(mView, rect, offset, cb)); } } /** - * Handles an inbound request for scroll capture from the system. If a client is not already - * active, a search will be dispatched through the view tree to locate scrolling content. + * Update the timeout for scroll capture requests. Only affects this view root. + * The default value is {@link #SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS}. + * + * @param timeMillis the new timeout in milliseconds + */ + public void setScrollCaptureRequestTimeout(int timeMillis) { + mScrollCaptureRequestTimeout = timeMillis; + } + + /** + * Get the current timeout for scroll capture requests. + * + * @return the timeout in milliseconds + */ + public long getScrollCaptureRequestTimeout() { + return mScrollCaptureRequestTimeout; + } + + /** + * Handles an inbound request for scroll capture from the system. A search will be + * dispatched through the view tree to locate scrolling content. * <p> - * Either {@link IScrollCaptureCallbacks#onConnected(IScrollCaptureConnection, Rect, - * Point)} or {@link IScrollCaptureCallbacks#onUnavailable()} will be returned - * depending on the results of the search. + * A call to {@link IScrollCaptureCallbacks#onScrollCaptureResponse(ScrollCaptureResponse)} + * will follow. * * @param callbacks to receive responses - * @see ScrollCaptureTargetResolver + * @see ScrollCaptureTargetSelector */ public void handleScrollCaptureRequest(@NonNull IScrollCaptureCallbacks callbacks) { - LinkedList<ScrollCaptureTarget> targetList = new LinkedList<>(); + ScrollCaptureSearchResults results = + new ScrollCaptureSearchResults(mContext.getMainExecutor()); // Window (root) level callbacks - collectRootScrollCaptureTargets(targetList); + collectRootScrollCaptureTargets(results); // Search through View-tree View rootView = getView(); @@ -9260,58 +9282,70 @@ public final class ViewRootImpl implements ViewParent, Point point = new Point(); Rect rect = new Rect(0, 0, rootView.getWidth(), rootView.getHeight()); getChildVisibleRect(rootView, rect, point); - rootView.dispatchScrollCaptureSearch(rect, point, targetList); + rootView.dispatchScrollCaptureSearch(rect, point, results::addTarget); } - - // No-op path. Scroll capture not offered for this window. - if (targetList.isEmpty()) { - dispatchScrollCaptureSearchResult(callbacks, null); - return; + Runnable onComplete = () -> dispatchScrollCaptureSearchResult(callbacks, results); + results.setOnCompleteListener(onComplete); + if (!results.isComplete()) { + mHandler.postDelayed(results::finish, getScrollCaptureRequestTimeout()); } - - // Request scrollBounds from each of the targets. - // Continues with the consumer once all responses are consumed, or the timeout expires. - ScrollCaptureTargetResolver resolver = new ScrollCaptureTargetResolver(targetList); - resolver.start(mHandler, 1000, - (selected) -> dispatchScrollCaptureSearchResult(callbacks, selected)); } /** Called by {@link #handleScrollCaptureRequest} when a result is returned */ private void dispatchScrollCaptureSearchResult( @NonNull IScrollCaptureCallbacks callbacks, - @Nullable ScrollCaptureTarget selectedTarget) { + @NonNull ScrollCaptureSearchResults results) { + + ScrollCaptureTarget selectedTarget = results.getTopResult(); + + ScrollCaptureResponse.Builder response = new ScrollCaptureResponse.Builder(); + response.setWindowTitle(getTitle().toString()); + + StringWriter writer = new StringWriter(); + IndentingPrintWriter pw = new IndentingPrintWriter(writer); + results.dump(pw); + pw.flush(); + response.addMessage(writer.toString()); - // If timeout or no eligible targets found. if (selectedTarget == null) { + response.setDescription("No scrollable targets found in window"); try { - if (DEBUG_SCROLL_CAPTURE) { - Log.d(TAG, "scrollCaptureSearch returned no targets available."); - } - callbacks.onUnavailable(); + callbacks.onScrollCaptureResponse(response.build()); } catch (RemoteException e) { - if (DEBUG_SCROLL_CAPTURE) { - Log.w(TAG, "Failed to send scroll capture search result.", e); - } + Log.e(TAG, "Failed to send scroll capture search result", e); } return; } - // Create a client instance and return it to the caller - mScrollCaptureConnection = new ScrollCaptureConnection(selectedTarget, callbacks); + response.setDescription("Connected"); + + // Compute area covered by scrolling content within window + Rect boundsInWindow = new Rect(); + View containingView = selectedTarget.getContainingView(); + containingView.getLocationInWindow(mAttachInfo.mTmpLocation); + boundsInWindow.set(selectedTarget.getScrollBounds()); + boundsInWindow.offset(mAttachInfo.mTmpLocation[0], mAttachInfo.mTmpLocation[1]); + response.setBoundsInWindow(boundsInWindow); + + // Compute the area on screen covered by the window + Rect boundsOnScreen = new Rect(); + mView.getLocationOnScreen(mAttachInfo.mTmpLocation); + boundsOnScreen.set(0, 0, mView.getWidth(), mView.getHeight()); + boundsOnScreen.offset(mAttachInfo.mTmpLocation[0], mAttachInfo.mTmpLocation[1]); + response.setWindowBounds(boundsOnScreen); + + // Create a connection and return it to the caller + ScrollCaptureConnection connection = new ScrollCaptureConnection( + mView.getContext().getMainExecutor(), selectedTarget, callbacks); + response.setConnection(connection); + try { - if (DEBUG_SCROLL_CAPTURE) { - Log.d(TAG, "scrollCaptureSearch returning client: " + getScrollCaptureConnection()); - } - callbacks.onConnected( - mScrollCaptureConnection, - selectedTarget.getScrollBounds(), - selectedTarget.getPositionInWindow()); + callbacks.onScrollCaptureResponse(response.build()); } catch (RemoteException e) { if (DEBUG_SCROLL_CAPTURE) { - Log.w(TAG, "Failed to send scroll capture search result.", e); + Log.w(TAG, "Failed to send scroll capture search response.", e); } - mScrollCaptureConnection.disconnect(); - mScrollCaptureConnection = null; + connection.close(); } } |
