Loading packages/SystemUI/src/com/android/systemui/screenshot/ImageTileSet.java +19 −47 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.graphics.Bitmap; import android.graphics.HardwareRenderer; import android.graphics.RecordingCanvas; import android.graphics.Rect; import android.graphics.Region; import android.graphics.RenderNode; import android.graphics.drawable.Drawable; import android.os.Handler; Loading @@ -46,7 +47,6 @@ class ImageTileSet { private static final String TAG = "ImageTileSet"; private CallbackRegistry<OnBoundsChangedListener, ImageTileSet, Rect> mOnBoundsListeners; private CallbackRegistry<OnContentChangedListener, ImageTileSet, Rect> mContentListeners; @Inject Loading @@ -54,14 +54,6 @@ class ImageTileSet { mHandler = handler; } interface OnBoundsChangedListener { /** * Reports an update to the bounding box that contains all active tiles. These are virtual * (capture) coordinates which can be either negative or positive. */ void onBoundsChanged(int left, int top, int right, int bottom); } interface OnContentChangedListener { /** * Mark as dirty and rebuild display list. Loading @@ -70,25 +62,9 @@ class ImageTileSet { } private final List<ImageTile> mTiles = new ArrayList<>(); private final Rect mBounds = new Rect(); private final Region mRegion = new Region(); private final Handler mHandler; void addOnBoundsChangedListener(OnBoundsChangedListener listener) { if (mOnBoundsListeners == null) { mOnBoundsListeners = new CallbackRegistry<>( new NotifierCallback<OnBoundsChangedListener, ImageTileSet, Rect>() { @Override public void onNotifyCallback(OnBoundsChangedListener callback, ImageTileSet sender, int arg, Rect newBounds) { callback.onBoundsChanged(newBounds.left, newBounds.top, newBounds.right, newBounds.bottom); } }); } mOnBoundsListeners.add(listener); } void addOnContentChangedListener(OnContentChangedListener listener) { if (mContentListeners == null) { mContentListeners = new CallbackRegistry<>( Loading @@ -110,14 +86,8 @@ class ImageTileSet { mHandler.post(() -> addTile(tile)); return; } final Rect newBounds = new Rect(mBounds); final Rect newRect = tile.getLocation(); mTiles.add(tile); newBounds.union(newRect); if (!newBounds.equals(mBounds)) { mBounds.set(newBounds); notifyBoundsChanged(mBounds); } mRegion.op(tile.getLocation(), mRegion, Region.Op.UNION); notifyContentChanged(); } Loading @@ -127,12 +97,6 @@ class ImageTileSet { } } private void notifyBoundsChanged(Rect bounds) { if (mOnBoundsListeners != null) { mOnBoundsListeners.notifyCallbacks(this, 0, bounds); } } /** * Returns a drawable to paint the combined contents of the tiles. Drawable dimensions are * zero-based and map directly to {@link #getLeft()}, {@link #getTop()}, {@link #getRight()}, Loading @@ -153,6 +117,15 @@ class ImageTileSet { return mTiles.size(); } /** * @return the bounding rect around any gaps in the tiles. */ Rect getGaps() { Region difference = new Region(); difference.op(mRegion.getBounds(), mRegion, Region.Op.DIFFERENCE); return difference.getBounds(); } ImageTile get(int i) { return mTiles.get(i); } Loading Loading @@ -182,41 +155,40 @@ class ImageTileSet { } int getLeft() { return mBounds.left; return mRegion.getBounds().left; } int getTop() { return mBounds.top; return mRegion.getBounds().top; } int getRight() { return mBounds.right; return mRegion.getBounds().right; } int getBottom() { return mBounds.bottom; return mRegion.getBounds().bottom; } int getWidth() { return mBounds.width(); return mRegion.getBounds().width(); } int getHeight() { return mBounds.height(); return mRegion.getBounds().height(); } void clear() { if (mTiles.isEmpty()) { return; } mBounds.setEmpty(); mRegion.setEmpty(); Iterator<ImageTile> i = mTiles.iterator(); while (i.hasNext()) { ImageTile next = i.next(); next.close(); i.remove(); } notifyBoundsChanged(mBounds); notifyContentChanged(); } } packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java +15 −8 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import javax.inject.Inject; public class ScrollCaptureClient { private static final int TILE_SIZE_PX_MAX = 4 * (1024 * 1024); private static final int TILES_PER_PAGE = 2; // increase once b/174571735 is addressed private static final int MAX_TILES = 30; @VisibleForTesting static final int MATCH_ANY_TASK = ActivityTaskManager.INVALID_TASK_ID; Loading Loading @@ -83,11 +84,12 @@ public class ScrollCaptureClient { int getMaxTiles(); /** * @return the maximum combined capture height for this session, in pixels. * Target pixel height for acquisition this session. Session may yield more or less data * than this, but acquiring this height is considered sufficient for completion. * * @return target height in pixels. */ default int getMaxHeight() { return getMaxTiles() * getTileHeight(); } int getTargetHeight(); /** * @return the height of each image tile Loading Loading @@ -234,11 +236,11 @@ public class ScrollCaptureClient { private final int mTileWidth; private Rect mRequestRect; private boolean mStarted; private final int mTargetHeight; private ICancellationSignal mCancellationSignal; private final Rect mWindowBounds; private final Rect mBoundsInWindow; private final int mMaxTiles; private Completer<Session> mStartCompleter; private Completer<CaptureResult> mTileRequestCompleter; Loading @@ -256,7 +258,7 @@ public class ScrollCaptureClient { mTileWidth = mBoundsInWindow.width(); mTileHeight = pxPerTile / mBoundsInWindow.width(); mMaxTiles = (int) Math.ceil(maxPages * TILES_PER_PAGE); mTargetHeight = (int) (mBoundsInWindow.height() * maxPages); if (DEBUG_SCROLL) { Log.d(TAG, "boundsInWindow: " + mBoundsInWindow); Loading Loading @@ -285,7 +287,7 @@ public class ScrollCaptureClient { private void start(Completer<Session> completer) { mReader = ImageReader.newInstance(mTileWidth, mTileHeight, PixelFormat.RGBA_8888, mMaxTiles, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE); MAX_TILES, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE); mStartCompleter = completer; try { mCancellationSignal = mConnection.startCapture(mReader.getSurface(), this); Loading Loading @@ -409,9 +411,14 @@ public class ScrollCaptureClient { return new Rect(mBoundsInWindow); } @Override public int getTargetHeight() { return mTargetHeight; } @Override public int getMaxTiles() { return mMaxTiles; return MAX_TILES; } } } packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java +17 −17 Original line number Diff line number Diff line Loading @@ -199,22 +199,20 @@ public class ScrollCaptureController { Log.d(TAG, "onCaptureResult: " + result + " scrolling " + (mScrollingUp ? "UP" : "DOWN") + " finish on boundary: " + mFinishOnBoundary); boolean emptyResult = result.captured.height() == 0; boolean partialResult = !emptyResult && result.captured.height() < result.requested.height(); boolean finish = false; if (emptyResult) { // Potentially reached a vertical boundary. Extend in the other direction. if (mFinishOnBoundary) { Log.d(TAG, "Partial/empty: finished!"); finish = true; Log.d(TAG, "Empty: finished!"); finishCapture(); return; } else { // We hit a boundary, clear the tiles, capture everything in the opposite direction, // then finish. mImageTileSet.clear(); mFinishOnBoundary = true; mScrollingUp = !mScrollingUp; Log.d(TAG, "Partial/empty: cleared, switch direction to finish"); Log.d(TAG, "Empty: cleared, switch direction to finish"); } } else { // Got a non-empty result, but may already have enough bitmap data now Loading @@ -223,12 +221,14 @@ public class ScrollCaptureController { 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). finish = true; finishCapture(); return; } else { if (mScrollingUp && !mFinishOnBoundary) { // During the initial scroll up, we only want to acquire the portion described // by IDEAL_PORTION_ABOVE. if (expectedTiles >= mSession.getMaxTiles() * IDEAL_PORTION_ABOVE) { if (mImageTileSet.getHeight() + result.captured.height() >= mSession.getTargetHeight() * IDEAL_PORTION_ABOVE) { 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(); Loading @@ -246,15 +246,15 @@ public class ScrollCaptureController { + " - " + mImageTileSet.getRight() + "," + mImageTileSet.getBottom() + " (" + mImageTileSet.getWidth() + "x" + mImageTileSet.getHeight() + ")"); // Stop when "too tall" if (mImageTileSet.getHeight() > MAX_HEIGHT) { Log.d(TAG, "Max height reached."); finish = true; Rect gapBounds = mImageTileSet.getGaps(); if (!gapBounds.isEmpty()) { Log.d(TAG, "Found gaps in tileset: " + gapBounds + ", requesting " + gapBounds.top); requestNextTile(gapBounds.top); return; } if (finish) { Log.d(TAG, "Stop."); if (mImageTileSet.getHeight() >= mSession.getTargetHeight()) { Log.d(TAG, "Target height reached."); finishCapture(); return; } Loading @@ -268,8 +268,8 @@ public class ScrollCaptureController { : result.requested.bottom; } else { nextTop = (mScrollingUp) ? result.captured.top - mSession.getTileHeight() : result.captured.bottom; ? mImageTileSet.getTop() - mSession.getTileHeight() : mImageTileSet.getBottom(); } requestNextTile(nextTop); } Loading packages/SystemUI/tests/src/com/android/systemui/screenshot/FakeSession.java +10 −2 Original line number Diff line number Diff line Loading @@ -57,16 +57,19 @@ class FakeSession implements ScrollCaptureClient.Session { private int mScrollDelta; private int mPageHeight; private int mTargetHeight; FakeSession(int pageHeight, float maxPages, int tileHeight, int visiblePageTop, int visiblePageBottom, int availableTop, int availableBottom) { int visiblePageBottom, int availableTop, int availableBottom, int maxTiles) { mPageHeight = pageHeight; mTileHeight = tileHeight; mAvailable = new Rect(0, availableTop, getPageWidth(), availableBottom); mAvailableTop = new Rect(mAvailable); mAvailableTop.inset(0, 0, 0, pageHeight); mVisiblePage = new Rect(0, visiblePageTop, getPageWidth(), visiblePageBottom); mMaxTiles = (int) Math.ceil((pageHeight * maxPages) / mTileHeight); mTargetHeight = (int) (pageHeight * maxPages); mMaxTiles = maxTiles; } private static Image mockImage() { Loading Loading @@ -157,6 +160,11 @@ class FakeSession implements ScrollCaptureClient.Session { return mMaxTiles; } @Override public int getTargetHeight() { return mTargetHeight; } @Override public int getTileHeight() { return mTileHeight; Loading packages/SystemUI/tests/src/com/android/systemui/screenshot/FakeSessionTest.java +26 −28 Original line number Diff line number Diff line Loading @@ -41,21 +41,6 @@ import org.junit.runner.RunWith; @SmallTest @RunWith(AndroidTestingRunner.class) public class FakeSessionTest extends SysuiTestCase { @Test public void testMaxTiles() { FakeSession session = new FakeSession( /* pageHeight */ 100, /* maxPages */ 2.25f, /* tileHeight */ 10, /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -250, /* availableBottom */ 250); // (pageHeight * maxPages) / tileHeight assertEquals("getMaxTiles()", 23, session.getMaxTiles()); } @Test public void testNonEmptyResult_hasImage() { FakeSession session = new FakeSession( Loading @@ -65,7 +50,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ 0, /* availableBottom */ 100); /* availableBottom */ 100, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(0)); assertNotNull("result.image", result.image); assertNotNull("result.image.getHardwareBuffer()", result.image.getHardwareBuffer()); Loading @@ -80,7 +66,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ 0, /* availableBottom */ 100); /* availableBottom */ 100, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(-100)); assertNull("result.image", result.image); } Loading @@ -94,7 +81,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -250, /* availableBottom */ 250); /* availableBottom */ 250, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(0)); assertEquals("requested top", 0, result.requested.top); Loading @@ -113,7 +101,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -250, /* availableBottom */ 250); /* availableBottom */ 250, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(90)); assertEquals("requested top", 90, result.requested.top); Loading @@ -132,7 +121,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -250, /* availableBottom */ 250); /* availableBottom */ 250, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(-100)); assertEquals("requested top", -100, result.requested.top); Loading @@ -151,7 +141,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -250, /* availableBottom */ 250); /* availableBottom */ 250, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(150)); assertEquals("requested top", 150, result.requested.top); Loading @@ -170,7 +161,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -100, /* availableBottom */ 100); /* availableBottom */ 100, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(-125)); assertEquals("requested top", -125, result.requested.top); Loading @@ -189,7 +181,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -100, /* availableBottom */ 100); /* availableBottom */ 100, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(75)); assertEquals("requested top", 75, result.requested.top); Loading @@ -211,7 +204,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 25, // <<-- /* visiblePageBottom */ 100, /* availableTop */ -150, /* availableBottom */ 150); /* availableBottom */ 150, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(-150)); assertEquals("requested top", -150, result.requested.top); Loading @@ -233,7 +227,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 75, /* availableTop */ -150, /* availableBottom */ 150); /* availableBottom */ 150, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(50)); assertEquals("requested top", 50, result.requested.top); Loading @@ -252,7 +247,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -100, /* availableBottom */ 200); /* availableBottom */ 200, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(-150)); assertTrue("captured rect is empty", result.captured.isEmpty()); } Loading @@ -266,7 +262,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -100, /* availableBottom */ 200); /* availableBottom */ 200, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(200)); assertTrue("captured rect is empty", result.captured.isEmpty()); } Loading @@ -280,7 +277,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 60, // <<--- /* visiblePageBottom */ 0, /* availableTop */ -150, /* availableBottom */ 150); /* availableBottom */ 150, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(0)); assertEquals("requested top", 0, result.requested.top); Loading Loading
packages/SystemUI/src/com/android/systemui/screenshot/ImageTileSet.java +19 −47 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.graphics.Bitmap; import android.graphics.HardwareRenderer; import android.graphics.RecordingCanvas; import android.graphics.Rect; import android.graphics.Region; import android.graphics.RenderNode; import android.graphics.drawable.Drawable; import android.os.Handler; Loading @@ -46,7 +47,6 @@ class ImageTileSet { private static final String TAG = "ImageTileSet"; private CallbackRegistry<OnBoundsChangedListener, ImageTileSet, Rect> mOnBoundsListeners; private CallbackRegistry<OnContentChangedListener, ImageTileSet, Rect> mContentListeners; @Inject Loading @@ -54,14 +54,6 @@ class ImageTileSet { mHandler = handler; } interface OnBoundsChangedListener { /** * Reports an update to the bounding box that contains all active tiles. These are virtual * (capture) coordinates which can be either negative or positive. */ void onBoundsChanged(int left, int top, int right, int bottom); } interface OnContentChangedListener { /** * Mark as dirty and rebuild display list. Loading @@ -70,25 +62,9 @@ class ImageTileSet { } private final List<ImageTile> mTiles = new ArrayList<>(); private final Rect mBounds = new Rect(); private final Region mRegion = new Region(); private final Handler mHandler; void addOnBoundsChangedListener(OnBoundsChangedListener listener) { if (mOnBoundsListeners == null) { mOnBoundsListeners = new CallbackRegistry<>( new NotifierCallback<OnBoundsChangedListener, ImageTileSet, Rect>() { @Override public void onNotifyCallback(OnBoundsChangedListener callback, ImageTileSet sender, int arg, Rect newBounds) { callback.onBoundsChanged(newBounds.left, newBounds.top, newBounds.right, newBounds.bottom); } }); } mOnBoundsListeners.add(listener); } void addOnContentChangedListener(OnContentChangedListener listener) { if (mContentListeners == null) { mContentListeners = new CallbackRegistry<>( Loading @@ -110,14 +86,8 @@ class ImageTileSet { mHandler.post(() -> addTile(tile)); return; } final Rect newBounds = new Rect(mBounds); final Rect newRect = tile.getLocation(); mTiles.add(tile); newBounds.union(newRect); if (!newBounds.equals(mBounds)) { mBounds.set(newBounds); notifyBoundsChanged(mBounds); } mRegion.op(tile.getLocation(), mRegion, Region.Op.UNION); notifyContentChanged(); } Loading @@ -127,12 +97,6 @@ class ImageTileSet { } } private void notifyBoundsChanged(Rect bounds) { if (mOnBoundsListeners != null) { mOnBoundsListeners.notifyCallbacks(this, 0, bounds); } } /** * Returns a drawable to paint the combined contents of the tiles. Drawable dimensions are * zero-based and map directly to {@link #getLeft()}, {@link #getTop()}, {@link #getRight()}, Loading @@ -153,6 +117,15 @@ class ImageTileSet { return mTiles.size(); } /** * @return the bounding rect around any gaps in the tiles. */ Rect getGaps() { Region difference = new Region(); difference.op(mRegion.getBounds(), mRegion, Region.Op.DIFFERENCE); return difference.getBounds(); } ImageTile get(int i) { return mTiles.get(i); } Loading Loading @@ -182,41 +155,40 @@ class ImageTileSet { } int getLeft() { return mBounds.left; return mRegion.getBounds().left; } int getTop() { return mBounds.top; return mRegion.getBounds().top; } int getRight() { return mBounds.right; return mRegion.getBounds().right; } int getBottom() { return mBounds.bottom; return mRegion.getBounds().bottom; } int getWidth() { return mBounds.width(); return mRegion.getBounds().width(); } int getHeight() { return mBounds.height(); return mRegion.getBounds().height(); } void clear() { if (mTiles.isEmpty()) { return; } mBounds.setEmpty(); mRegion.setEmpty(); Iterator<ImageTile> i = mTiles.iterator(); while (i.hasNext()) { ImageTile next = i.next(); next.close(); i.remove(); } notifyBoundsChanged(mBounds); notifyContentChanged(); } }
packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java +15 −8 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import javax.inject.Inject; public class ScrollCaptureClient { private static final int TILE_SIZE_PX_MAX = 4 * (1024 * 1024); private static final int TILES_PER_PAGE = 2; // increase once b/174571735 is addressed private static final int MAX_TILES = 30; @VisibleForTesting static final int MATCH_ANY_TASK = ActivityTaskManager.INVALID_TASK_ID; Loading Loading @@ -83,11 +84,12 @@ public class ScrollCaptureClient { int getMaxTiles(); /** * @return the maximum combined capture height for this session, in pixels. * Target pixel height for acquisition this session. Session may yield more or less data * than this, but acquiring this height is considered sufficient for completion. * * @return target height in pixels. */ default int getMaxHeight() { return getMaxTiles() * getTileHeight(); } int getTargetHeight(); /** * @return the height of each image tile Loading Loading @@ -234,11 +236,11 @@ public class ScrollCaptureClient { private final int mTileWidth; private Rect mRequestRect; private boolean mStarted; private final int mTargetHeight; private ICancellationSignal mCancellationSignal; private final Rect mWindowBounds; private final Rect mBoundsInWindow; private final int mMaxTiles; private Completer<Session> mStartCompleter; private Completer<CaptureResult> mTileRequestCompleter; Loading @@ -256,7 +258,7 @@ public class ScrollCaptureClient { mTileWidth = mBoundsInWindow.width(); mTileHeight = pxPerTile / mBoundsInWindow.width(); mMaxTiles = (int) Math.ceil(maxPages * TILES_PER_PAGE); mTargetHeight = (int) (mBoundsInWindow.height() * maxPages); if (DEBUG_SCROLL) { Log.d(TAG, "boundsInWindow: " + mBoundsInWindow); Loading Loading @@ -285,7 +287,7 @@ public class ScrollCaptureClient { private void start(Completer<Session> completer) { mReader = ImageReader.newInstance(mTileWidth, mTileHeight, PixelFormat.RGBA_8888, mMaxTiles, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE); MAX_TILES, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE); mStartCompleter = completer; try { mCancellationSignal = mConnection.startCapture(mReader.getSurface(), this); Loading Loading @@ -409,9 +411,14 @@ public class ScrollCaptureClient { return new Rect(mBoundsInWindow); } @Override public int getTargetHeight() { return mTargetHeight; } @Override public int getMaxTiles() { return mMaxTiles; return MAX_TILES; } } }
packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java +17 −17 Original line number Diff line number Diff line Loading @@ -199,22 +199,20 @@ public class ScrollCaptureController { Log.d(TAG, "onCaptureResult: " + result + " scrolling " + (mScrollingUp ? "UP" : "DOWN") + " finish on boundary: " + mFinishOnBoundary); boolean emptyResult = result.captured.height() == 0; boolean partialResult = !emptyResult && result.captured.height() < result.requested.height(); boolean finish = false; if (emptyResult) { // Potentially reached a vertical boundary. Extend in the other direction. if (mFinishOnBoundary) { Log.d(TAG, "Partial/empty: finished!"); finish = true; Log.d(TAG, "Empty: finished!"); finishCapture(); return; } else { // We hit a boundary, clear the tiles, capture everything in the opposite direction, // then finish. mImageTileSet.clear(); mFinishOnBoundary = true; mScrollingUp = !mScrollingUp; Log.d(TAG, "Partial/empty: cleared, switch direction to finish"); Log.d(TAG, "Empty: cleared, switch direction to finish"); } } else { // Got a non-empty result, but may already have enough bitmap data now Loading @@ -223,12 +221,14 @@ public class ScrollCaptureController { 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). finish = true; finishCapture(); return; } else { if (mScrollingUp && !mFinishOnBoundary) { // During the initial scroll up, we only want to acquire the portion described // by IDEAL_PORTION_ABOVE. if (expectedTiles >= mSession.getMaxTiles() * IDEAL_PORTION_ABOVE) { if (mImageTileSet.getHeight() + result.captured.height() >= mSession.getTargetHeight() * IDEAL_PORTION_ABOVE) { 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(); Loading @@ -246,15 +246,15 @@ public class ScrollCaptureController { + " - " + mImageTileSet.getRight() + "," + mImageTileSet.getBottom() + " (" + mImageTileSet.getWidth() + "x" + mImageTileSet.getHeight() + ")"); // Stop when "too tall" if (mImageTileSet.getHeight() > MAX_HEIGHT) { Log.d(TAG, "Max height reached."); finish = true; Rect gapBounds = mImageTileSet.getGaps(); if (!gapBounds.isEmpty()) { Log.d(TAG, "Found gaps in tileset: " + gapBounds + ", requesting " + gapBounds.top); requestNextTile(gapBounds.top); return; } if (finish) { Log.d(TAG, "Stop."); if (mImageTileSet.getHeight() >= mSession.getTargetHeight()) { Log.d(TAG, "Target height reached."); finishCapture(); return; } Loading @@ -268,8 +268,8 @@ public class ScrollCaptureController { : result.requested.bottom; } else { nextTop = (mScrollingUp) ? result.captured.top - mSession.getTileHeight() : result.captured.bottom; ? mImageTileSet.getTop() - mSession.getTileHeight() : mImageTileSet.getBottom(); } requestNextTile(nextTop); } Loading
packages/SystemUI/tests/src/com/android/systemui/screenshot/FakeSession.java +10 −2 Original line number Diff line number Diff line Loading @@ -57,16 +57,19 @@ class FakeSession implements ScrollCaptureClient.Session { private int mScrollDelta; private int mPageHeight; private int mTargetHeight; FakeSession(int pageHeight, float maxPages, int tileHeight, int visiblePageTop, int visiblePageBottom, int availableTop, int availableBottom) { int visiblePageBottom, int availableTop, int availableBottom, int maxTiles) { mPageHeight = pageHeight; mTileHeight = tileHeight; mAvailable = new Rect(0, availableTop, getPageWidth(), availableBottom); mAvailableTop = new Rect(mAvailable); mAvailableTop.inset(0, 0, 0, pageHeight); mVisiblePage = new Rect(0, visiblePageTop, getPageWidth(), visiblePageBottom); mMaxTiles = (int) Math.ceil((pageHeight * maxPages) / mTileHeight); mTargetHeight = (int) (pageHeight * maxPages); mMaxTiles = maxTiles; } private static Image mockImage() { Loading Loading @@ -157,6 +160,11 @@ class FakeSession implements ScrollCaptureClient.Session { return mMaxTiles; } @Override public int getTargetHeight() { return mTargetHeight; } @Override public int getTileHeight() { return mTileHeight; Loading
packages/SystemUI/tests/src/com/android/systemui/screenshot/FakeSessionTest.java +26 −28 Original line number Diff line number Diff line Loading @@ -41,21 +41,6 @@ import org.junit.runner.RunWith; @SmallTest @RunWith(AndroidTestingRunner.class) public class FakeSessionTest extends SysuiTestCase { @Test public void testMaxTiles() { FakeSession session = new FakeSession( /* pageHeight */ 100, /* maxPages */ 2.25f, /* tileHeight */ 10, /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -250, /* availableBottom */ 250); // (pageHeight * maxPages) / tileHeight assertEquals("getMaxTiles()", 23, session.getMaxTiles()); } @Test public void testNonEmptyResult_hasImage() { FakeSession session = new FakeSession( Loading @@ -65,7 +50,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ 0, /* availableBottom */ 100); /* availableBottom */ 100, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(0)); assertNotNull("result.image", result.image); assertNotNull("result.image.getHardwareBuffer()", result.image.getHardwareBuffer()); Loading @@ -80,7 +66,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ 0, /* availableBottom */ 100); /* availableBottom */ 100, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(-100)); assertNull("result.image", result.image); } Loading @@ -94,7 +81,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -250, /* availableBottom */ 250); /* availableBottom */ 250, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(0)); assertEquals("requested top", 0, result.requested.top); Loading @@ -113,7 +101,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -250, /* availableBottom */ 250); /* availableBottom */ 250, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(90)); assertEquals("requested top", 90, result.requested.top); Loading @@ -132,7 +121,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -250, /* availableBottom */ 250); /* availableBottom */ 250, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(-100)); assertEquals("requested top", -100, result.requested.top); Loading @@ -151,7 +141,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -250, /* availableBottom */ 250); /* availableBottom */ 250, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(150)); assertEquals("requested top", 150, result.requested.top); Loading @@ -170,7 +161,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -100, /* availableBottom */ 100); /* availableBottom */ 100, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(-125)); assertEquals("requested top", -125, result.requested.top); Loading @@ -189,7 +181,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -100, /* availableBottom */ 100); /* availableBottom */ 100, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(75)); assertEquals("requested top", 75, result.requested.top); Loading @@ -211,7 +204,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 25, // <<-- /* visiblePageBottom */ 100, /* availableTop */ -150, /* availableBottom */ 150); /* availableBottom */ 150, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(-150)); assertEquals("requested top", -150, result.requested.top); Loading @@ -233,7 +227,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 75, /* availableTop */ -150, /* availableBottom */ 150); /* availableBottom */ 150, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(50)); assertEquals("requested top", 50, result.requested.top); Loading @@ -252,7 +247,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -100, /* availableBottom */ 200); /* availableBottom */ 200, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(-150)); assertTrue("captured rect is empty", result.captured.isEmpty()); } Loading @@ -266,7 +262,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 0, /* visiblePageBottom */ 100, /* availableTop */ -100, /* availableBottom */ 200); /* availableBottom */ 200, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(200)); assertTrue("captured rect is empty", result.captured.isEmpty()); } Loading @@ -280,7 +277,8 @@ public class FakeSessionTest extends SysuiTestCase { /* visiblePageTop */ 60, // <<--- /* visiblePageBottom */ 0, /* availableTop */ -150, /* availableBottom */ 150); /* availableBottom */ 150, /* max Tiles */ 30); ScrollCaptureClient.CaptureResult result = getUnchecked(session.requestTile(0)); assertEquals("requested top", 0, result.requested.top); Loading