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

Commit 84f80d15 authored by Mark Renouf's avatar Mark Renouf
Browse files

Quiet down long screenshots logcat output

With this change, a long screen shot flow generates only
the following log entries:

D Screenshot: ScrollCapture: connected to window [com.example/.ExampleActivity]
D Screenshot: onCaptureStarted
D Screenshot: end()
I Screenshot: Completed: LongScreenshot{w=1080, h=5339}

Tags covered:

LongScreenshotActivity
Screenshot
ScrollCaptureConnection
ScrollCaptureInternal
ScrollCaptureViewSupport
ScrollCaptureController
ViewRenderer

Bug: 190399332
Test: observe logcat during long screenshot
Change-Id: Ia2b018224897ad1ca153967ff9f60340a64f4815
parent 82a1baf8
Loading
Loading
Loading
Loading
+3 −24
Original line number Diff line number Diff line
@@ -16,11 +16,6 @@

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

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

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

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

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

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

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

        if (recyclerView.requestChildRectangleOnScreen(anchor, input, true)) {
            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++
            result.scrollDelta = mScrollDelta;
            Log.d(TAG, "requestedContentBounds, (post-request-rect) = " + requestedContentBounds);
        }

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

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

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

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

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

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

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

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

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

    // 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
    private static final boolean DEBUG_VERBOSE = false;
+0 −2
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import android.graphics.Region;
import android.graphics.RenderNode;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.Log;

import androidx.annotation.UiThread;

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

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

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

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

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

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

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

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

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

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

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

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

    private void startExport(PendingAction action) {
        Log.d(TAG, "startExport(action = " + action + ")");
        Drawable drawable = mPreview.getDrawable();
        if (drawable == null) {
            Log.e(TAG, "No drawable, skipping export!");
+47 −24
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ import javax.inject.Inject;
 * Interaction controller between the UI and ScrollCaptureClient.
 */
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 String SETTING_KEY_MAX_PAGES = "screenshot.scroll_max_pages";
@@ -90,7 +90,9 @@ public class ScrollCaptureController {

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

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

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

        if (emptyResult) {
            // Potentially reached a vertical boundary. Extend in the other direction.
            if (mFinishOnBoundary) {
                if (LogConfig.DEBUG_SCROLL) {
                    Log.d(TAG, "Empty: finished!");
                }
                finishCapture();
                return;
            } else {
@@ -212,13 +220,17 @@ public class ScrollCaptureController {
                mImageTileSet.clear();
                mFinishOnBoundary = true;
                mScrollingUp = !mScrollingUp;
                if (LogConfig.DEBUG_SCROLL) {
                    Log.d(TAG, "Empty: cleared, switch direction to finish");
                }
            }
        } else {
            // Got a non-empty result, but may already have enough bitmap data now
            int expectedTiles = mImageTileSet.size() + 1;
            if (expectedTiles >= mSession.getMaxTiles()) {
                if (LogConfig.DEBUG_SCROLL) {
                    Log.d(TAG, "Hit max tiles: finished");
                }
                // 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).
                finishCapture();
@@ -229,7 +241,9 @@ public class ScrollCaptureController {
                    // by IDEAL_PORTION_ABOVE.
                    if (mImageTileSet.getHeight() + result.captured.height()
                            >= mSession.getTargetHeight() * IDEAL_PORTION_ABOVE) {
                        if (LogConfig.DEBUG_SCROLL) {
                            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.
                        mImageTileSet.clear();
                        mScrollingUp = false;
@@ -241,20 +255,25 @@ public class ScrollCaptureController {
        if (!emptyResult) {
            mImageTileSet.addTile(new ImageTile(result.image, result.captured));
        }

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

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

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

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