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

Commit 008af730 authored by Mark Renouf's avatar Mark Renouf Committed by Android (Google) Code Review
Browse files

Merge "Use OnImageAvailableListener to wait for buffer" into sc-dev

parents e0276d9c 6ab3ffa7
Loading
Loading
Loading
Loading
+46 −8
Original line number Diff line number Diff line
@@ -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
+1 −3
Original line number Diff line number Diff line
@@ -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 =