diff options
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java | 54 | ||||
| -rw-r--r-- | packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureClientTest.java | 4 |
2 files changed, 47 insertions, 11 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java index ce6e46937c25..93e5021fd6e0 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java @@ -45,9 +45,12 @@ import androidx.concurrent.futures.CallbackToFutureAdapter; import androidx.concurrent.futures.CallbackToFutureAdapter.Completer; import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.dagger.qualifiers.Background; import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.Executor; + import javax.inject.Inject; /** @@ -63,6 +66,8 @@ public class ScrollCaptureClient { private static final String TAG = LogConfig.logTag(ScrollCaptureClient.class); + private final Executor mBgExecutor; + /** * Represents the connection to a target window and provides a mechanism for requesting tiles. */ @@ -155,8 +160,10 @@ public class ScrollCaptureClient { private IBinder mHostWindowToken; @Inject - public ScrollCaptureClient(@UiContext Context context, IWindowManager windowManagerService) { + public ScrollCaptureClient(IWindowManager windowManagerService, + @Background Executor bgExecutor, @UiContext Context context) { requireNonNull(context.getDisplay(), "context must be associated with a Display!"); + mBgExecutor = bgExecutor; mWindowManagerService = windowManagerService; } @@ -220,21 +227,25 @@ public class ScrollCaptureClient { return ""; } SessionWrapper session = new SessionWrapper(connection, response.getWindowBounds(), - response.getBoundsInWindow(), maxPages); + response.getBoundsInWindow(), maxPages, mBgExecutor); session.start(completer); return "IScrollCaptureCallbacks#onCaptureStarted"; }); } private static class SessionWrapper extends IScrollCaptureCallbacks.Stub implements Session, - IBinder.DeathRecipient { + IBinder.DeathRecipient, ImageReader.OnImageAvailableListener { private IScrollCaptureConnection mConnection; + private final Executor mBgExecutor; + private final Object mLock = new Object(); private ImageReader mReader; private final int mTileHeight; private final int mTileWidth; private Rect mRequestRect; + private Rect mCapturedArea; + private Image mCapturedImage; private boolean mStarted; private final int mTargetHeight; @@ -247,7 +258,8 @@ public class ScrollCaptureClient { private Completer<Void> mEndCompleter; private SessionWrapper(IScrollCaptureConnection connection, Rect windowBounds, - Rect boundsInWindow, float maxPages) throws RemoteException { + Rect boundsInWindow, float maxPages, Executor bgExecutor) + throws RemoteException { mConnection = requireNonNull(connection); mConnection.asBinder().linkToDeath(SessionWrapper.this, 0); mWindowBounds = requireNonNull(windowBounds); @@ -259,7 +271,7 @@ public class ScrollCaptureClient { mTileWidth = mBoundsInWindow.width(); mTileHeight = pxPerTile / mBoundsInWindow.width(); mTargetHeight = (int) (mBoundsInWindow.height() * maxPages); - + mBgExecutor = bgExecutor; if (DEBUG_SCROLL) { Log.d(TAG, "boundsInWindow: " + mBoundsInWindow); Log.d(TAG, "tile size: " + mTileWidth + "x" + mTileHeight); @@ -289,6 +301,7 @@ public class ScrollCaptureClient { mReader = ImageReader.newInstance(mTileWidth, mTileHeight, PixelFormat.RGBA_8888, MAX_TILES, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE); mStartCompleter = completer; + mReader.setOnImageAvailableListenerWithExecutor(this, mBgExecutor); try { mCancellationSignal = mConnection.startCapture(mReader.getSurface(), this); completer.addCancellationListener(() -> { @@ -339,9 +352,34 @@ public class ScrollCaptureClient { @BinderThread @Override - public void onImageRequestCompleted(int flags, Rect contentArea) { - Image image = mReader.acquireLatestImage(); - mTileRequestCompleter.set(new CaptureResult(image, mRequestRect, contentArea)); + public void onImageRequestCompleted(int flagsUnused, Rect contentArea) { + synchronized (mLock) { + mCapturedArea = contentArea; + if (mCapturedImage != null || (mCapturedArea == null || mCapturedArea.isEmpty())) { + completeCaptureRequest(); + } + } + } + + /** @see ImageReader.OnImageAvailableListener */ + @Override + public void onImageAvailable(ImageReader reader) { + synchronized (mLock) { + mCapturedImage = mReader.acquireLatestImage(); + if (mCapturedArea != null) { + completeCaptureRequest(); + } + } + } + + /** Produces a result for the caller as soon as both asynchronous results are received. */ + private void completeCaptureRequest() { + CaptureResult result = + new CaptureResult(mCapturedImage, mRequestRect, mCapturedArea); + mCapturedImage = null; + mRequestRect = null; + mCapturedArea = null; + mTileRequestCompleter.set(result); } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureClientTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureClientTest.java index 3a4bc699b967..670a130d610a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureClientTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureClientTest.java @@ -26,7 +26,6 @@ import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; -import android.content.Context; import android.graphics.Rect; import android.os.RemoteException; import android.testing.AndroidTestingRunner; @@ -36,7 +35,6 @@ import android.view.IWindowManager; import android.view.ScrollCaptureResponse; import androidx.test.filters.SmallTest; -import androidx.test.platform.app.InstrumentationRegistry; import com.android.systemui.SysuiTestCase; import com.android.systemui.screenshot.ScrollCaptureClient.CaptureResult; @@ -83,7 +81,7 @@ public class ScrollCaptureClientTest extends SysuiTestCase { /* taskId */ anyInt(), any(IScrollCaptureResponseListener.class)); // Create client - ScrollCaptureClient client = new ScrollCaptureClient(mContext, mWm); + ScrollCaptureClient client = new ScrollCaptureClient(mWm, Runnable::run, mContext); // Request scroll capture ListenableFuture<ScrollCaptureResponse> requestFuture = |