Properly clean up screenshot of recents animation upon cancelation

Bug: 122593881
Test: Manual
Change-Id: Ia9ce1ede08309a0898c622bcd07a9e076443d98a
This commit is contained in:
Tracy Zhou
2019-03-12 23:36:47 -07:00
parent 0c3692d5ef
commit 2bd3a0225b
7 changed files with 25 additions and 65 deletions
@@ -173,6 +173,12 @@ public class RecentsAnimationWrapper {
return true;
}
public void setCancelWithDeferredScreenshot(boolean deferredWithScreenshot) {
if (targetSet != null) {
targetSet.controller.setCancelWithDeferredScreenshot(deferredWithScreenshot);
}
}
public SwipeAnimationTargetSet getController() {
return targetSet;
}
@@ -1170,6 +1170,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
mLauncherTransitionController = null;
}
mActivityControlHelper.onSwipeUpComplete(mActivity);
mRecentsAnimationWrapper.setCancelWithDeferredScreenshot(true);
// Animate the first icon.
mRecentsView.animateUpRunningTaskIconScale();
@@ -38,9 +38,16 @@ import androidx.annotation.UiThread;
*/
public class RecentsAnimationListenerSet implements RecentsAnimationListener {
// The actual app surface is replaced by a screenshot upon recents animation cancelation when
// deferredWithScreenshot is true. Launcher takes the responsibility to clean up this screenshot
// after app transition is finished. This delay is introduced to cover the app transition
// period of time.
private final int TRANSITION_DELAY = 100;
private final Set<SwipeAnimationListener> mListeners = new ArraySet<>();
private final boolean mShouldMinimizeSplitScreen;
private final Consumer<SwipeAnimationTargetSet> mOnFinishListener;
private RecentsAnimationControllerCompat mController;
public RecentsAnimationListenerSet(boolean shouldMinimizeSplitScreen,
Consumer<SwipeAnimationTargetSet> onFinishListener) {
@@ -64,6 +71,7 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener {
public final void onAnimationStart(RecentsAnimationControllerCompat controller,
RemoteAnimationTargetCompat[] targets, Rect homeContentInsets,
Rect minimizedHomeBounds) {
mController = controller;
SwipeAnimationTargetSet targetSet = new SwipeAnimationTargetSet(controller, targets,
homeContentInsets, minimizedHomeBounds, mShouldMinimizeSplitScreen,
mOnFinishListener);
@@ -75,12 +83,17 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener {
}
@Override
public final void onAnimationCanceled() {
public final void onAnimationCanceled(boolean deferredWithScreenshot) {
Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> {
for (SwipeAnimationListener listener : getListeners()) {
listener.onRecentsAnimationCanceled();
}
});
// TODO: handle the transition better instead of simply using a transition delay.
if (deferredWithScreenshot) {
MAIN_THREAD_EXECUTOR.getHandler().postDelayed(() -> mController.cleanupScreenshot(),
TRANSITION_DELAY);
}
}
private SwipeAnimationListener[] getListeners() {
@@ -95,12 +95,7 @@ public class LauncherRecentsView extends RecentsView<Launcher> {
@Override
public void startHome() {
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
takeScreenshotAndFinishRecentsAnimation(true,
() -> mActivity.getStateManager().goToState(NORMAL));
} else {
mActivity.getStateManager().goToState(NORMAL);
}
mActivity.getStateManager().goToState(NORMAL);
}
@Override
@@ -94,7 +94,6 @@ import com.android.quickstep.RecentsModel.TaskThumbnailChangeListener;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.util.TaskViewDrawable;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -103,7 +102,6 @@ import com.android.systemui.shared.system.BackgroundExecutor;
import com.android.systemui.shared.system.PackageManagerWrapper;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowCallbacksCompat;
import java.util.ArrayList;
import java.util.function.Consumer;
@@ -1577,50 +1575,4 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
mRecentsAnimationWrapper.finish(toRecents, onFinishComplete);
}
public void takeScreenshotAndFinishRecentsAnimation(boolean toRecents,
Runnable onFinishComplete) {
if (mRecentsAnimationWrapper == null || getRunningTaskView() == null) {
if (onFinishComplete != null) {
onFinishComplete.run();
}
return;
}
SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
// Update the screenshot of the task
ThumbnailData taskSnapshot = controller.screenshotTask(mRunningTaskId);
TaskView taskView = updateThumbnail(mRunningTaskId, taskSnapshot);
if (taskView != null) {
taskView.setShowScreenshot(true);
// Defer finishing the animation until the next launcher frame with the
// new thumbnail
new WindowCallbacksCompat(taskView) {
// The number of frames to defer until we actually finish the animation
private int mDeferFrameCount = 2;
@Override
public void onPostDraw(Canvas canvas) {
if (mDeferFrameCount > 0) {
mDeferFrameCount--;
// Workaround, detach and reattach to invalidate the root node for
// another draw
detach();
attach();
taskView.invalidate();
return;
}
detach();
mRecentsAnimationWrapper.finish(toRecents, () -> {
onFinishComplete.run();
mRunningTaskId = -1;
});
}
}.attach();
}
}
}
}
@@ -208,13 +208,7 @@ public class TaskMenuView extends AbstractFloatingView {
R.layout.task_view_menu_option, this, false);
menuOption.setIconAndLabelFor(
menuOptionView.findViewById(R.id.icon), menuOptionView.findViewById(R.id.text));
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
menuOptionView.setOnClickListener(
view -> mTaskView.getRecentsView().takeScreenshotAndFinishRecentsAnimation(true,
() -> onClickListener.onClick(view)));
} else {
menuOptionView.setOnClickListener(onClickListener);
}
menuOptionView.setOnClickListener(onClickListener);
mOptionLayout.addView(menuOptionView);
}
@@ -259,11 +259,10 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
Handler resultCallbackHandler) {
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
if (isRunningTask()) {
getRecentsView().finishRecentsAnimation(false,
getRecentsView().finishRecentsAnimation(false /* toRecents */,
() -> resultCallbackHandler.post(() -> resultCallback.accept(true)));
} else {
getRecentsView().takeScreenshotAndFinishRecentsAnimation(true,
() -> launchTaskInternal(animate, resultCallback, resultCallbackHandler));
launchTaskInternal(animate, resultCallback, resultCallbackHandler);
}
} else {
launchTaskInternal(animate, resultCallback, resultCallbackHandler);