diff --git a/quickstep/src/com/android/quickstep/ViewUtils.java b/quickstep/src/com/android/quickstep/ViewUtils.java index 1fef544e3e..1bb95b97f9 100644 --- a/quickstep/src/com/android/quickstep/ViewUtils.java +++ b/quickstep/src/com/android/quickstep/ViewUtils.java @@ -17,6 +17,7 @@ package com.android.quickstep; import android.graphics.HardwareRenderer; import android.os.Handler; +import android.view.SurfaceControl; import android.view.View; import android.view.ViewRootImpl; @@ -45,22 +46,42 @@ public class ViewUtils { return new FrameHandler(view, onFinishRunnable, canceled).schedule(); } - private static class FrameHandler implements HardwareRenderer.FrameDrawingCallback { + private static class FrameHandler implements HardwareRenderer.FrameDrawingCallback, + ViewRootImpl.SurfaceChangedCallback { final ViewRootImpl mViewRoot; final Runnable mFinishCallback; final BooleanSupplier mCancelled; final Handler mHandler; + boolean mFinished; int mDeferFrameCount = 1; FrameHandler(View view, Runnable finishCallback, BooleanSupplier cancelled) { mViewRoot = view.getViewRootImpl(); + mViewRoot.addSurfaceChangedCallback(this); mFinishCallback = finishCallback; mCancelled = cancelled; mHandler = new Handler(); } + @Override + public void surfaceCreated(SurfaceControl.Transaction t) { + // Do nothing + } + + @Override + public void surfaceReplaced(SurfaceControl.Transaction t) { + // Do nothing + } + + @Override + public void surfaceDestroyed() { + // If the root view is detached, then the app won't get any scheduled frames so we need + // to force-run any pending callbacks + finish(); + } + @Override public void onFrameDraw(long frame) { Utilities.postAsyncCallback(mHandler, this::onFrame); @@ -77,9 +98,7 @@ public class ViewUtils { return; } - if (mFinishCallback != null) { - mFinishCallback.run(); - } + finish(); } private boolean schedule() { @@ -90,5 +109,17 @@ public class ViewUtils { } return false; } + + private void finish() { + if (mFinished) { + return; + } + mFinished = true; + mDeferFrameCount = 0; + if (mFinishCallback != null) { + mFinishCallback.run(); + } + mViewRoot.removeSurfaceChangedCallback(this); + } } }