Commit c62b2799 authored by ckitagawa's avatar ckitagawa Committed by Commit Bot

[Paint Preview] More eagerly release native memory on exit

To ensure we are cleaning up native memory promptly this CL invokes
recycle on all bitmaps prior to ceasing to use them.

Change-Id: If76397cdd8f232eff9992763d2b1cf07ecaed07c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2471598Reviewed-by: default avatarMehran Mahmoudi <mahmoudi@chromium.org>
Commit-Queue: Calder Kitagawa <ckitagawa@chromium.org>
Cr-Commit-Position: refs/heads/master@{#817152}
parent 229fdaf8
...@@ -231,6 +231,10 @@ public class PlayerManager { ...@@ -231,6 +231,10 @@ public class PlayerManager {
mDelegate.destroy(); mDelegate.destroy();
mDelegate = null; mDelegate = null;
} }
if (mRootFrameCoordinator != null) {
mRootFrameCoordinator.destroy();
mRootFrameCoordinator = null;
}
} }
public View getView() { public View getView() {
......
...@@ -97,10 +97,17 @@ public class PlayerFrameBitmapState { ...@@ -97,10 +97,17 @@ public class PlayerFrameBitmapState {
/** /**
* Clears state so in-flight requests abort upon return. * Clears state so in-flight requests abort upon return.
*/ */
void clear() { void destroy() {
mBitmapMatrix = null;
mRequiredBitmaps = null; mRequiredBitmaps = null;
mPendingBitmapRequests = null; mPendingBitmapRequests = null;
for (int i = 0; i < mBitmapMatrix.length; i++) {
for (int j = 0; j < mBitmapMatrix[i].length; j++) {
if (mBitmapMatrix[i][j] != null) {
mBitmapMatrix[i][j].destroy();
}
}
}
mBitmapMatrix = null;
} }
/** /**
...@@ -117,19 +124,6 @@ public class PlayerFrameBitmapState { ...@@ -117,19 +124,6 @@ public class PlayerFrameBitmapState {
mInitialMissingVisibleBitmaps = null; mInitialMissingVisibleBitmaps = null;
} }
/**
* Clears all the required bitmaps before they are re-set in {@link #requestBitmapForRect()}
*/
void clearRequiredBitmaps() {
if (mRequiredBitmaps == null) return;
for (int row = 0; row < mRequiredBitmaps.length; row++) {
for (int col = 0; col < mRequiredBitmaps[row].length; col++) {
mRequiredBitmaps[row][col] = false;
}
}
}
/** /**
* Requests bitmaps for tiles that overlap with the provided rect. Also requests bitmaps for * Requests bitmaps for tiles that overlap with the provided rect. Also requests bitmaps for
* adjacent tiles. * adjacent tiles.
...@@ -137,7 +131,7 @@ public class PlayerFrameBitmapState { ...@@ -137,7 +131,7 @@ public class PlayerFrameBitmapState {
*/ */
void requestBitmapForRect(Rect viewportRect) { void requestBitmapForRect(Rect viewportRect) {
if (mRequiredBitmaps == null || mBitmapMatrix == null) return; if (mRequiredBitmaps == null || mBitmapMatrix == null) return;
clearVisibleBitmaps(); clearBeforeRequest();
final int rowStart = final int rowStart =
Math.max(0, (int) Math.floor((double) viewportRect.top / mTileSize.getHeight())); Math.max(0, (int) Math.floor((double) viewportRect.top / mTileSize.getHeight()));
...@@ -248,12 +242,18 @@ public class PlayerFrameBitmapState { ...@@ -248,12 +242,18 @@ public class PlayerFrameBitmapState {
mStateController.stateUpdated(this); mStateController.stateUpdated(this);
} }
private void clearVisibleBitmaps() { private void clearBeforeRequest() {
if (mVisibleBitmaps == null) return; if (mVisibleBitmaps == null || mRequiredBitmaps == null) return;
assert mVisibleBitmaps.length == mRequiredBitmaps.length;
assert (mVisibleBitmaps.length > 0)
? mVisibleBitmaps[0].length == mRequiredBitmaps[0].length
: true;
for (int row = 0; row < mVisibleBitmaps.length; row++) { for (int row = 0; row < mVisibleBitmaps.length; row++) {
for (int col = 0; col < mVisibleBitmaps[row].length; col++) { for (int col = 0; col < mVisibleBitmaps[row].length; col++) {
mVisibleBitmaps[row][col] = false; mVisibleBitmaps[row][col] = false;
mRequiredBitmaps[row][col] = false;
} }
} }
} }
......
...@@ -37,6 +37,17 @@ public class PlayerFrameBitmapStateController { ...@@ -37,6 +37,17 @@ public class PlayerFrameBitmapStateController {
mTaskRunner = taskRunner; mTaskRunner = taskRunner;
} }
void destroy() {
if (mLoadingBitmapState != null) {
mLoadingBitmapState.destroy();
mLoadingBitmapState = null;
}
if (mVisibleBitmapState != null) {
mVisibleBitmapState.destroy();
mVisibleBitmapState = null;
}
}
@VisibleForTesting @VisibleForTesting
void swapForTest() { void swapForTest() {
swap(mLoadingBitmapState); swap(mLoadingBitmapState);
...@@ -76,7 +87,7 @@ public class PlayerFrameBitmapStateController { ...@@ -76,7 +87,7 @@ public class PlayerFrameBitmapStateController {
assert mLoadingBitmapState == newState; assert mLoadingBitmapState == newState;
// Clear the state to stop potential stragling updates. // Clear the state to stop potential stragling updates.
if (mVisibleBitmapState != null) { if (mVisibleBitmapState != null) {
mVisibleBitmapState.clear(); mVisibleBitmapState.destroy();
} }
mVisibleBitmapState = newState; mVisibleBitmapState = newState;
mLoadingBitmapState = null; mLoadingBitmapState = null;
...@@ -119,7 +130,7 @@ public class PlayerFrameBitmapStateController { ...@@ -119,7 +130,7 @@ public class PlayerFrameBitmapStateController {
// Invalidate an in-progress load if there is one. We only want one new scale factor fetched // Invalidate an in-progress load if there is one. We only want one new scale factor fetched
// at a time. NOTE: we clear then null as the bitmap callbacks still hold a reference to the // at a time. NOTE: we clear then null as the bitmap callbacks still hold a reference to the
// state so it won't be GC'd right away. // state so it won't be GC'd right away.
mLoadingBitmapState.clear(); mLoadingBitmapState.destroy();
mLoadingBitmapState = null; mLoadingBitmapState = null;
} }
} }
...@@ -69,6 +69,13 @@ public class PlayerFrameCoordinator { ...@@ -69,6 +69,13 @@ public class PlayerFrameCoordinator {
PropertyModelChangeProcessor.create(model, mView, PlayerFrameViewBinder::bind); PropertyModelChangeProcessor.create(model, mView, PlayerFrameViewBinder::bind);
} }
public void destroy() {
mMediator.destroy();
for (PlayerFrameCoordinator subframe : mSubFrames) {
subframe.destroy();
}
}
public void setAcceptUserInput(boolean acceptUserInput) { public void setAcceptUserInput(boolean acceptUserInput) {
if (mScrollController != null) mScrollController.setAcceptUserInput(acceptUserInput); if (mScrollController != null) mScrollController.setAcceptUserInput(acceptUserInput);
if (mScaleController != null) mScaleController.setAcceptUserInput(acceptUserInput); if (mScaleController != null) mScaleController.setAcceptUserInput(acceptUserInput);
......
...@@ -95,6 +95,10 @@ class PlayerFrameMediator implements PlayerFrameViewDelegate, PlayerFrameMediato ...@@ -95,6 +95,10 @@ class PlayerFrameMediator implements PlayerFrameViewDelegate, PlayerFrameMediato
mViewport.setScale(0f); mViewport.setScale(0f);
} }
void destroy() {
mBitmapStateController.destroy();
}
@VisibleForTesting @VisibleForTesting
PlayerFrameBitmapStateController getBitmapStateControllerForTest() { PlayerFrameBitmapStateController getBitmapStateControllerForTest() {
return mBitmapStateController; return mBitmapStateController;
...@@ -251,9 +255,6 @@ class PlayerFrameMediator implements PlayerFrameViewDelegate, PlayerFrameMediato ...@@ -251,9 +255,6 @@ class PlayerFrameMediator implements PlayerFrameViewDelegate, PlayerFrameMediato
mModel.set(PlayerFrameProperties.VIEWPORT, viewportRect); mModel.set(PlayerFrameProperties.VIEWPORT, viewportRect);
} }
// Clear the required bitmaps matrix. It will be updated in #requestBitmapForTile.
activeLoadingState.clearRequiredBitmaps();
// Request bitmaps for tiles inside the view port that don't already have a bitmap. // Request bitmaps for tiles inside the view port that don't already have a bitmap.
activeLoadingState.requestBitmapForRect(viewportRect); activeLoadingState.requestBitmapForRect(viewportRect);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment