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

Commit 1ac5b4b4 authored by Mark Renouf's avatar Mark Renouf Committed by Automerger Merge Worker
Browse files

Merge "Quiet down long screenshots logcat output" into sc-dev am: a7af7f83

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15236057

Change-Id: Ia18a598dc9879764c4ed1ae134dec0162efcc2ff
parents 650e7203 a7af7f83
Loading
Loading
Loading
Loading
+3 −24
Original line number Original line Diff line number Diff line
@@ -16,11 +16,6 @@


package com.android.internal.view;
package com.android.internal.view;


import static com.android.internal.view.ScrollCaptureViewSupport.computeScrollAmount;
import static com.android.internal.view.ScrollCaptureViewSupport.findScrollingReferenceView;
import static com.android.internal.view.ScrollCaptureViewSupport.transformFromContainerToRequest;
import static com.android.internal.view.ScrollCaptureViewSupport.transformFromRequestToContainer;

import android.annotation.NonNull;
import android.annotation.NonNull;
import android.graphics.Rect;
import android.graphics.Rect;
import android.util.Log;
import android.util.Log;
@@ -43,6 +38,7 @@ import android.view.ViewParent;
 */
 */
public class RecyclerViewCaptureHelper implements ScrollCaptureViewHelper<ViewGroup> {
public class RecyclerViewCaptureHelper implements ScrollCaptureViewHelper<ViewGroup> {
    private static final String TAG = "RVCaptureHelper";
    private static final String TAG = "RVCaptureHelper";

    private int mScrollDelta;
    private int mScrollDelta;
    private boolean mScrollBarWasEnabled;
    private boolean mScrollBarWasEnabled;
    private int mOverScrollMode;
    private int mOverScrollMode;
@@ -66,7 +62,6 @@ public class RecyclerViewCaptureHelper implements ScrollCaptureViewHelper<ViewGr
        result.scrollDelta = mScrollDelta;
        result.scrollDelta = mScrollDelta;
        result.availableArea = new Rect(); // empty
        result.availableArea = new Rect(); // empty


        Log.d(TAG, "current scrollDelta: " + mScrollDelta);
        if (!recyclerView.isVisibleToUser() || recyclerView.getChildCount() == 0) {
        if (!recyclerView.isVisibleToUser() || recyclerView.getChildCount() == 0) {
            Log.w(TAG, "recyclerView is empty or not visible, cannot continue");
            Log.w(TAG, "recyclerView is empty or not visible, cannot continue");
            return result; // result.availableArea == empty Rect
            return result; // result.availableArea == empty Rect
@@ -76,22 +71,18 @@ public class RecyclerViewCaptureHelper implements ScrollCaptureViewHelper<ViewGr
        Rect requestedContainerBounds = new Rect(requestRect);
        Rect requestedContainerBounds = new Rect(requestRect);
        requestedContainerBounds.offset(0, -mScrollDelta);
        requestedContainerBounds.offset(0, -mScrollDelta);
        requestedContainerBounds.offset(scrollBounds.left, scrollBounds.top);
        requestedContainerBounds.offset(scrollBounds.left, scrollBounds.top);

        // requestedContainerBounds is now in recyclerview-local coordinates
        // requestedContainerBounds is now in recyclerview-local coordinates
        Log.d(TAG, "requestedContainerBounds: " + requestedContainerBounds);


        // Save a copy for later
        // Save a copy for later
        View anchor = findChildNearestTarget(recyclerView, requestedContainerBounds);
        View anchor = findChildNearestTarget(recyclerView, requestedContainerBounds);
        if (anchor == null) {
        if (anchor == null) {
            Log.d(TAG, "Failed to locate anchor view");
            Log.w(TAG, "Failed to locate anchor view");
            return result; // result.availableArea == null
            return result; // result.availableArea == empty rect
        }
        }


        Log.d(TAG, "Anchor view:" + anchor);
        Rect requestedContentBounds = new Rect(requestedContainerBounds);
        Rect requestedContentBounds = new Rect(requestedContainerBounds);
        recyclerView.offsetRectIntoDescendantCoords(anchor, requestedContentBounds);
        recyclerView.offsetRectIntoDescendantCoords(anchor, requestedContentBounds);


        Log.d(TAG, "requestedContentBounds = " + requestedContentBounds);
        int prevAnchorTop = anchor.getTop();
        int prevAnchorTop = anchor.getTop();
        // Note: requestChildRectangleOnScreen may modify rectangle, must pass pass in a copy here
        // Note: requestChildRectangleOnScreen may modify rectangle, must pass pass in a copy here
        Rect input = new Rect(requestedContentBounds);
        Rect input = new Rect(requestedContentBounds);
@@ -101,34 +92,27 @@ public class RecyclerViewCaptureHelper implements ScrollCaptureViewHelper<ViewGr
        if (remainingHeight > 0) {
        if (remainingHeight > 0) {
            input.inset(0, -remainingHeight / 2);
            input.inset(0, -remainingHeight / 2);
        }
        }
        Log.d(TAG, "input (post center adjustment) = " + input);


        if (recyclerView.requestChildRectangleOnScreen(anchor, input, true)) {
        if (recyclerView.requestChildRectangleOnScreen(anchor, input, true)) {
            int scrolled = prevAnchorTop - anchor.getTop(); // inverse of movement
            int scrolled = prevAnchorTop - anchor.getTop(); // inverse of movement
            Log.d(TAG, "RecyclerView scrolled by " + scrolled + " px");
            mScrollDelta += scrolled; // view.top-- is equivalent to parent.scrollY++
            mScrollDelta += scrolled; // view.top-- is equivalent to parent.scrollY++
            result.scrollDelta = mScrollDelta;
            result.scrollDelta = mScrollDelta;
            Log.d(TAG, "requestedContentBounds, (post-request-rect) = " + requestedContentBounds);
        }
        }


        requestedContainerBounds.set(requestedContentBounds);
        requestedContainerBounds.set(requestedContentBounds);
        recyclerView.offsetDescendantRectToMyCoords(anchor, requestedContainerBounds);
        recyclerView.offsetDescendantRectToMyCoords(anchor, requestedContainerBounds);
        Log.d(TAG, "requestedContainerBounds, (post-scroll): " + requestedContainerBounds);


        Rect recyclerLocalVisible = new Rect(scrollBounds);
        Rect recyclerLocalVisible = new Rect(scrollBounds);
        recyclerView.getLocalVisibleRect(recyclerLocalVisible);
        recyclerView.getLocalVisibleRect(recyclerLocalVisible);
        Log.d(TAG, "recyclerLocalVisible: " + recyclerLocalVisible);


        if (!requestedContainerBounds.intersect(recyclerLocalVisible)) {
        if (!requestedContainerBounds.intersect(recyclerLocalVisible)) {
            // Requested area is still not visible
            // Requested area is still not visible
            Log.d(TAG, "requested bounds not visible!");
            return result;
            return result;
        }
        }
        Rect available = new Rect(requestedContainerBounds);
        Rect available = new Rect(requestedContainerBounds);
        available.offset(-scrollBounds.left, -scrollBounds.top);
        available.offset(-scrollBounds.left, -scrollBounds.top);
        available.offset(0, mScrollDelta);
        available.offset(0, mScrollDelta);
        result.availableArea = available;
        result.availableArea = available;
        Log.d(TAG, "availableArea: " + result.availableArea);
        return result;
        return result;
    }
    }


@@ -154,22 +138,17 @@ public class RecyclerViewCaptureHelper implements ScrollCaptureViewHelper<ViewGr


        Rect parentLocalVis = new Rect();
        Rect parentLocalVis = new Rect();
        parent.getLocalVisibleRect(parentLocalVis);
        parent.getLocalVisibleRect(parentLocalVis);
        Log.d(TAG, "findChildNearestTarget: parentVis=" + parentLocalVis
                + " targetRect=" + targetRect);


        Rect frame = new Rect();
        Rect frame = new Rect();
        for (int i = 0; i < parent.getChildCount(); i++) {
        for (int i = 0; i < parent.getChildCount(); i++) {
            final View child = parent.getChildAt(i);
            final View child = parent.getChildAt(i);
            child.getHitRect(frame);
            child.getHitRect(frame);
            Log.d(TAG, "child #" + i + " hitRect=" + frame);


            if (child.getVisibility() != View.VISIBLE) {
            if (child.getVisibility() != View.VISIBLE) {
                Log.d(TAG, "child #" + i + " is not visible");
                continue;
                continue;
            }
            }


            int centerDistance = Math.abs(targetRect.centerY() - frame.centerY());
            int centerDistance = Math.abs(targetRect.centerY() - frame.centerY());
            Log.d(TAG, "child #" + i + " : center to center: " + centerDistance + "px");


            if (centerDistance < minCenterDistance) {
            if (centerDistance < minCenterDistance) {
                // closer to center
                // closer to center
+1 −1
Original line number Original line Diff line number Diff line
@@ -34,7 +34,7 @@ public class ScrollCaptureInternal {
    private static final String TAG = "ScrollCaptureInternal";
    private static final String TAG = "ScrollCaptureInternal";


    // Log found scrolling views
    // Log found scrolling views
    private static final boolean DEBUG = true;
    private static final boolean DEBUG = false;


    // Log all investigated views, as well as heuristic checks
    // Log all investigated views, as well as heuristic checks
    private static final boolean DEBUG_VERBOSE = false;
    private static final boolean DEBUG_VERBOSE = false;
+0 −2
Original line number Original line Diff line number Diff line
@@ -24,7 +24,6 @@ import android.graphics.Region;
import android.graphics.RenderNode;
import android.graphics.RenderNode;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Handler;
import android.util.Log;


import androidx.annotation.UiThread;
import androidx.annotation.UiThread;


@@ -140,7 +139,6 @@ class ImageTileSet {
     *               getHeight()).
     *               getHeight()).
     */
     */
    Bitmap toBitmap(Rect bounds) {
    Bitmap toBitmap(Rect bounds) {
        Log.d(TAG, "exporting with bounds: " + bounds);
        if (mTiles.isEmpty()) {
        if (mTiles.isEmpty()) {
            return null;
            return null;
        }
        }
+2 −21
Original line number Original line Diff line number Diff line
@@ -63,7 +63,7 @@ import javax.inject.Inject;
 * and bottom before saving/sharing/editing.
 * and bottom before saving/sharing/editing.
 */
 */
public class LongScreenshotActivity extends Activity {
public class LongScreenshotActivity extends Activity {
    private static final String TAG = "LongScreenshotActivity";
    private static final String TAG = LogConfig.logTag(LongScreenshotActivity.class);


    public static final String EXTRA_CAPTURE_RESPONSE = "capture-response";
    public static final String EXTRA_CAPTURE_RESPONSE = "capture-response";
    private static final String KEY_SAVED_IMAGE_PATH = "saved-image-path";
    private static final String KEY_SAVED_IMAGE_PATH = "saved-image-path";
@@ -113,7 +113,6 @@ public class LongScreenshotActivity extends Activity {


    @Override
    @Override
    public void onCreate(Bundle savedInstanceState) {
    public void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "onCreate(savedInstanceState = " + savedInstanceState + ")");
        super.onCreate(savedInstanceState);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.long_screenshot);
        setContentView(R.layout.long_screenshot);


@@ -161,7 +160,6 @@ public class LongScreenshotActivity extends Activity {


    @Override
    @Override
    public void onStart() {
    public void onStart() {
        Log.d(TAG, "onStart");
        super.onStart();
        super.onStart();


        if (mCacheLoadFuture != null) {
        if (mCacheLoadFuture != null) {
@@ -194,7 +192,7 @@ public class LongScreenshotActivity extends Activity {
    }
    }


    private void onLongScreenshotReceived(LongScreenshot longScreenshot) {
    private void onLongScreenshotReceived(LongScreenshot longScreenshot) {
        Log.d(TAG, "onLongScreenshotReceived(longScreenshot=" + longScreenshot + ")");
        Log.i(TAG, "Completed: " + longScreenshot);
        mLongScreenshot = longScreenshot;
        mLongScreenshot = longScreenshot;
        Drawable drawable = mLongScreenshot.getDrawable();
        Drawable drawable = mLongScreenshot.getDrawable();
        mPreview.setImageDrawable(drawable);
        mPreview.setImageDrawable(drawable);
@@ -249,7 +247,6 @@ public class LongScreenshotActivity extends Activity {
    }
    }


    private void onCachedImageLoaded(ImageLoader.Result imageResult) {
    private void onCachedImageLoaded(ImageLoader.Result imageResult) {
        Log.d(TAG, "onCachedImageLoaded(imageResult=" + imageResult + ")");
        BitmapDrawable drawable = new BitmapDrawable(getResources(), imageResult.bitmap);
        BitmapDrawable drawable = new BitmapDrawable(getResources(), imageResult.bitmap);
        mPreview.setImageDrawable(drawable);
        mPreview.setImageDrawable(drawable);
        mPreview.setAlpha(1f);
        mPreview.setAlpha(1f);
@@ -274,22 +271,14 @@ public class LongScreenshotActivity extends Activity {


    @Override
    @Override
    protected void onSaveInstanceState(Bundle outState) {
    protected void onSaveInstanceState(Bundle outState) {
        Log.d(TAG, "onSaveInstanceState");
        super.onSaveInstanceState(outState);
        super.onSaveInstanceState(outState);
        if (mSavedImagePath != null) {
        if (mSavedImagePath != null) {
            outState.putString(KEY_SAVED_IMAGE_PATH, mSavedImagePath.getPath());
            outState.putString(KEY_SAVED_IMAGE_PATH, mSavedImagePath.getPath());
        }
        }
    }
    }


    @Override
    protected void onPause() {
        Log.d(TAG, "onPause");
        super.onPause();
    }

    @Override
    @Override
    protected void onStop() {
    protected void onStop() {
        Log.d(TAG, "onStop finishing=" + isFinishing());
        super.onStop();
        super.onStop();
        if (mTransitionStarted) {
        if (mTransitionStarted) {
            finish();
            finish();
@@ -311,19 +300,12 @@ public class LongScreenshotActivity extends Activity {
            mCacheSaveFuture.cancel(true);
            mCacheSaveFuture.cancel(true);
        }
        }
        if (mSavedImagePath != null) {
        if (mSavedImagePath != null) {
            Log.d(TAG, "Deleting " + mSavedImagePath);
            //noinspection ResultOfMethodCallIgnored
            //noinspection ResultOfMethodCallIgnored
            mSavedImagePath.delete();
            mSavedImagePath.delete();
            mSavedImagePath = null;
            mSavedImagePath = null;
        }
        }
    }
    }


    @Override
    protected void onDestroy() {
        Log.d(TAG, "onDestroy");
        super.onDestroy();
    }

    private void setButtonsEnabled(boolean enabled) {
    private void setButtonsEnabled(boolean enabled) {
        mSave.setEnabled(enabled);
        mSave.setEnabled(enabled);
        mEdit.setEnabled(enabled);
        mEdit.setEnabled(enabled);
@@ -392,7 +374,6 @@ public class LongScreenshotActivity extends Activity {
    }
    }


    private void startExport(PendingAction action) {
    private void startExport(PendingAction action) {
        Log.d(TAG, "startExport(action = " + action + ")");
        Drawable drawable = mPreview.getDrawable();
        Drawable drawable = mPreview.getDrawable();
        if (drawable == null) {
        if (drawable == null) {
            Log.e(TAG, "No drawable, skipping export!");
            Log.e(TAG, "No drawable, skipping export!");
+47 −24
Original line number Original line Diff line number Diff line
@@ -43,7 +43,7 @@ import javax.inject.Inject;
 * Interaction controller between the UI and ScrollCaptureClient.
 * Interaction controller between the UI and ScrollCaptureClient.
 */
 */
public class ScrollCaptureController {
public class ScrollCaptureController {
    private static final String TAG = "ScrollCaptureController";
    private static final String TAG = LogConfig.logTag(ScrollCaptureController.class);
    private static final float MAX_PAGES_DEFAULT = 3f;
    private static final float MAX_PAGES_DEFAULT = 3f;


    private static final String SETTING_KEY_MAX_PAGES = "screenshot.scroll_max_pages";
    private static final String SETTING_KEY_MAX_PAGES = "screenshot.scroll_max_pages";
@@ -90,7 +90,9 @@ public class ScrollCaptureController {


        /** Releases image resources from the screenshot. */
        /** Releases image resources from the screenshot. */
        public void release() {
        public void release() {
            if (LogConfig.DEBUG_SCROLL) {
                Log.d(TAG, "LongScreenshot :: release()");
                Log.d(TAG, "LongScreenshot :: release()");
            }
            mImageTileSet.clear();
            mImageTileSet.clear();
            mSession.release();
            mSession.release();
        }
        }
@@ -153,15 +155,11 @@ public class ScrollCaptureController {
     * @return a future ImageTile set containing the result
     * @return a future ImageTile set containing the result
     */
     */
    ListenableFuture<LongScreenshot> run(ScrollCaptureResponse response) {
    ListenableFuture<LongScreenshot> run(ScrollCaptureResponse response) {
        Log.d(TAG, "run: " + response);
        return CallbackToFutureAdapter.getFuture(completer -> {
        return CallbackToFutureAdapter.getFuture(completer -> {
            Log.d(TAG, "getFuture(ImageTileSet) ");
            mCaptureCompleter = completer;
            mCaptureCompleter = completer;
            mBgExecutor.execute(() -> {
            mBgExecutor.execute(() -> {
                Log.d(TAG, "bgExecutor.execute");
                float maxPages = Settings.Secure.getFloat(mContext.getContentResolver(),
                float maxPages = Settings.Secure.getFloat(mContext.getContentResolver(),
                        SETTING_KEY_MAX_PAGES, MAX_PAGES_DEFAULT);
                        SETTING_KEY_MAX_PAGES, MAX_PAGES_DEFAULT);
                Log.d(TAG, "client start, maxPages=" + maxPages);
                mSessionFuture = mClient.start(response, maxPages);
                mSessionFuture = mClient.start(response, maxPages);
                mSessionFuture.addListener(this::onStartComplete, mContext.getMainExecutor());
                mSessionFuture.addListener(this::onStartComplete, mContext.getMainExecutor());
            });
            });
@@ -172,21 +170,27 @@ public class ScrollCaptureController {
    private void onStartComplete() {
    private void onStartComplete() {
        try {
        try {
            mSession = mSessionFuture.get();
            mSession = mSessionFuture.get();
            if (LogConfig.DEBUG_SCROLL) {
                Log.d(TAG, "got session " + mSession);
                Log.d(TAG, "got session " + mSession);
            }
            requestNextTile(0);
            requestNextTile(0);
        } catch (InterruptedException | ExecutionException e) {
        } catch (InterruptedException | ExecutionException e) {
            // Failure to start, propagate to caller
            // Failure to start, propagate to caller
            Log.d(TAG, "session start failed!");
            Log.e(TAG, "session start failed!");
            mCaptureCompleter.setException(e);
            mCaptureCompleter.setException(e);
        }
        }
    }
    }


    private void requestNextTile(int topPx) {
    private void requestNextTile(int topPx) {
        if (LogConfig.DEBUG_SCROLL) {
            Log.d(TAG, "requestNextTile: " + topPx);
            Log.d(TAG, "requestNextTile: " + topPx);
        }
        mTileFuture = mSession.requestTile(topPx);
        mTileFuture = mSession.requestTile(topPx);
        mTileFuture.addListener(() -> {
        mTileFuture.addListener(() -> {
            try {
            try {
                if (LogConfig.DEBUG_SCROLL) {
                    Log.d(TAG, "onCaptureResult");
                    Log.d(TAG, "onCaptureResult");
                }
                onCaptureResult(mTileFuture.get());
                onCaptureResult(mTileFuture.get());
            } catch (InterruptedException | ExecutionException e) {
            } catch (InterruptedException | ExecutionException e) {
                Log.e(TAG, "requestTile failed!", e);
                Log.e(TAG, "requestTile failed!", e);
@@ -196,14 +200,18 @@ public class ScrollCaptureController {
    }
    }


    private void onCaptureResult(CaptureResult result) {
    private void onCaptureResult(CaptureResult result) {
        if (LogConfig.DEBUG_SCROLL) {
            Log.d(TAG, "onCaptureResult: " + result + " scrolling " + (mScrollingUp ? "UP" : "DOWN")
            Log.d(TAG, "onCaptureResult: " + result + " scrolling " + (mScrollingUp ? "UP" : "DOWN")
                    + " finish on boundary: " + mFinishOnBoundary);
                    + " finish on boundary: " + mFinishOnBoundary);
        }
        boolean emptyResult = result.captured.height() == 0;
        boolean emptyResult = result.captured.height() == 0;


        if (emptyResult) {
        if (emptyResult) {
            // Potentially reached a vertical boundary. Extend in the other direction.
            // Potentially reached a vertical boundary. Extend in the other direction.
            if (mFinishOnBoundary) {
            if (mFinishOnBoundary) {
                if (LogConfig.DEBUG_SCROLL) {
                    Log.d(TAG, "Empty: finished!");
                    Log.d(TAG, "Empty: finished!");
                }
                finishCapture();
                finishCapture();
                return;
                return;
            } else {
            } else {
@@ -212,13 +220,17 @@ public class ScrollCaptureController {
                mImageTileSet.clear();
                mImageTileSet.clear();
                mFinishOnBoundary = true;
                mFinishOnBoundary = true;
                mScrollingUp = !mScrollingUp;
                mScrollingUp = !mScrollingUp;
                if (LogConfig.DEBUG_SCROLL) {
                    Log.d(TAG, "Empty: cleared, switch direction to finish");
                    Log.d(TAG, "Empty: cleared, switch direction to finish");
                }
                }
            }
        } else {
        } else {
            // Got a non-empty result, but may already have enough bitmap data now
            // Got a non-empty result, but may already have enough bitmap data now
            int expectedTiles = mImageTileSet.size() + 1;
            int expectedTiles = mImageTileSet.size() + 1;
            if (expectedTiles >= mSession.getMaxTiles()) {
            if (expectedTiles >= mSession.getMaxTiles()) {
                if (LogConfig.DEBUG_SCROLL) {
                    Log.d(TAG, "Hit max tiles: finished");
                    Log.d(TAG, "Hit max tiles: finished");
                }
                // If we ever hit the max tiles, we've got enough bitmap data to finish
                // If we ever hit the max tiles, we've got enough bitmap data to finish
                // (even if we weren't sure we'd finish on this pass).
                // (even if we weren't sure we'd finish on this pass).
                finishCapture();
                finishCapture();
@@ -229,7 +241,9 @@ public class ScrollCaptureController {
                    // by IDEAL_PORTION_ABOVE.
                    // by IDEAL_PORTION_ABOVE.
                    if (mImageTileSet.getHeight() + result.captured.height()
                    if (mImageTileSet.getHeight() + result.captured.height()
                            >= mSession.getTargetHeight() * IDEAL_PORTION_ABOVE) {
                            >= mSession.getTargetHeight() * IDEAL_PORTION_ABOVE) {
                        if (LogConfig.DEBUG_SCROLL) {
                            Log.d(TAG, "Hit ideal portion above: clear and switch direction");
                            Log.d(TAG, "Hit ideal portion above: clear and switch direction");
                        }
                        // We got enough above the start point, now see how far down it can go.
                        // We got enough above the start point, now see how far down it can go.
                        mImageTileSet.clear();
                        mImageTileSet.clear();
                        mScrollingUp = false;
                        mScrollingUp = false;
@@ -241,20 +255,25 @@ public class ScrollCaptureController {
        if (!emptyResult) {
        if (!emptyResult) {
            mImageTileSet.addTile(new ImageTile(result.image, result.captured));
            mImageTileSet.addTile(new ImageTile(result.image, result.captured));
        }
        }

        if (LogConfig.DEBUG_SCROLL) {
            Log.d(TAG, "bounds: " + mImageTileSet.getLeft() + "," + mImageTileSet.getTop()
            Log.d(TAG, "bounds: " + mImageTileSet.getLeft() + "," + mImageTileSet.getTop()
                    + " - " + mImageTileSet.getRight() + "," + mImageTileSet.getBottom()
                    + " - " + mImageTileSet.getRight() + "," + mImageTileSet.getBottom()
                    + " (" + mImageTileSet.getWidth() + "x" + mImageTileSet.getHeight() + ")");
                    + " (" + mImageTileSet.getWidth() + "x" + mImageTileSet.getHeight() + ")");
        }


        Rect gapBounds = mImageTileSet.getGaps();
        Rect gapBounds = mImageTileSet.getGaps();
        if (!gapBounds.isEmpty()) {
        if (!gapBounds.isEmpty()) {
            if (LogConfig.DEBUG_SCROLL) {
                Log.d(TAG, "Found gaps in tileset: " + gapBounds + ", requesting " + gapBounds.top);
                Log.d(TAG, "Found gaps in tileset: " + gapBounds + ", requesting " + gapBounds.top);
            }
            requestNextTile(gapBounds.top);
            requestNextTile(gapBounds.top);
            return;
            return;
        }
        }


        if (mImageTileSet.getHeight() >= mSession.getTargetHeight()) {
        if (mImageTileSet.getHeight() >= mSession.getTargetHeight()) {
            if (LogConfig.DEBUG_SCROLL) {
                Log.d(TAG, "Target height reached.");
                Log.d(TAG, "Target height reached.");
            }
            finishCapture();
            finishCapture();
            return;
            return;
        }
        }
@@ -275,10 +294,14 @@ public class ScrollCaptureController {
    }
    }


    private void finishCapture() {
    private void finishCapture() {
        if (LogConfig.DEBUG_SCROLL) {
            Log.d(TAG, "finishCapture()");
            Log.d(TAG, "finishCapture()");
        }
        mEndFuture = mSession.end();
        mEndFuture = mSession.end();
        mEndFuture.addListener(() -> {
        mEndFuture.addListener(() -> {
            if (LogConfig.DEBUG_SCROLL) {
                Log.d(TAG, "endCapture completed");
                Log.d(TAG, "endCapture completed");
            }
            // Provide result to caller and complete the top-level future
            // Provide result to caller and complete the top-level future
            // Caller is responsible for releasing this resource (ImageReader/HardwareBuffers)
            // Caller is responsible for releasing this resource (ImageReader/HardwareBuffers)
            mCaptureCompleter.set(new LongScreenshot(mSession, mImageTileSet));
            mCaptureCompleter.set(new LongScreenshot(mSession, mImageTileSet));