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

Commit 387279d9 authored by Tracy Zhou's avatar Tracy Zhou
Browse files

Live tile should switch to screenshot before finishing recents animation

Fixes: 139439373
Test: Launch a new app from shortcuts in Overview mode. Make sure the
live tile stays put (no hole). Same with touching empty space in
Overview to go home.

Change-Id: I6cacf2842e21f9856d0021cea9fddf4f870f09f0
parent 67138875
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -89,5 +89,5 @@ public abstract class RecentsUiFactory {
        return RotationMode.NORMAL;
    }

    public static void clearSwipeSharedState(boolean finishAnimation) {}
    public static void clearSwipeSharedState(Launcher launcher, boolean finishAnimation) { }
}
+10 −5
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.launcher3.uioverrides;

import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;

import android.content.Context;
@@ -196,12 +197,16 @@ public abstract class RecentsUiFactory {
        return new RecentsViewStateController(launcher);
    }

    /**
     * Clears the swipe shared state for the current swipe gesture.
     */
    public static void clearSwipeSharedState(boolean finishAnimation) {
    /** Clears the swipe shared state for the current swipe gesture. */
    public static void clearSwipeSharedState(Launcher launcher, boolean finishAnimation) {
        if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
            launcher.<RecentsView>getOverviewPanel().switchToScreenshot(
                    () -> TouchInteractionService.getSwipeSharedState().clearAllState(
                            finishAnimation));
        } else {
            TouchInteractionService.getSwipeSharedState().clearAllState(finishAnimation);
        }
    }

    /**
     * Recents logic that triggers when launcher state changes or launcher activity stops/resumes.
+74 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.quickstep;

import android.graphics.Canvas;
import android.view.View;

import com.android.systemui.shared.system.WindowCallbacksCompat;

import java.util.function.BooleanSupplier;

/**
 * Utility class for helpful methods related to {@link View} objects.
 */
public class ViewUtils {

    /** See {@link #postDraw(View, Runnable, BooleanSupplier)}} */
    public static boolean postDraw(View view, Runnable onFinishRunnable) {
        return postDraw(view, onFinishRunnable, () -> false);
    }

    /**
     * Inject some addition logic in order to make sure that the view is updated smoothly post
     * draw, and allow addition task to be run after view update.
     *
     * @param onFinishRunnable runnable to be run right after the view finishes drawing.
     */
    public static boolean postDraw(View view, Runnable onFinishRunnable, BooleanSupplier canceled) {
        // Defer finishing the animation until the next launcher frame with the
        // new thumbnail
        return new WindowCallbacksCompat(view) {
            // The number of frames to defer until we actually finish the animation
            private int mDeferFrameCount = 2;

            @Override
            public void onPostDraw(Canvas canvas) {
                // If we were cancelled after this was attached, do not update
                // the state.
                if (canceled.getAsBoolean()) {
                    detach();
                    return;
                }

                if (mDeferFrameCount > 0) {
                    mDeferFrameCount--;
                    // Workaround, detach and reattach to invalidate the root node for
                    // another draw
                    detach();
                    attach();
                    view.invalidate();
                    return;
                }

                if (onFinishRunnable != null) {
                    onFinishRunnable.run();
                }
                detach();
            }
        }.attach();
    }
}
+15 −33
Original line number Diff line number Diff line
@@ -45,7 +45,6 @@ import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Build;
@@ -90,12 +89,10 @@ import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.LatencyTrackerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.WindowCallbacksCompat;

@TargetApi(Build.VERSION_CODES.O)
public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
        extends BaseSwipeUpHandler<T, RecentsView>
        implements OnApplyWindowInsetsListener {
        extends BaseSwipeUpHandler<T, RecentsView> implements OnApplyWindowInsetsListener {
    private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName();

    private static final String[] STATE_NAMES = DEBUG_STATES ? new String[16] : null;
@@ -1007,6 +1004,10 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
        }
    }

    public boolean isCanceled() {
        return mCanceled;
    }

    @UiThread
    private void resumeLastTask() {
        mRecentsAnimationWrapper.finish(false /* toRecents */, null);
@@ -1099,14 +1100,21 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
    }

    private void switchToScreenshot() {
        SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
        if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
            if (controller != null) {
                // Update the screenshot of the task
                if (mTaskSnapshot == null) {
                    mTaskSnapshot = controller.screenshotTask(mRunningTaskId);
                }
                mRecentsView.updateThumbnail(mRunningTaskId, mTaskSnapshot, false /* refreshNow */);
            }
            setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
        } else if (!mRecentsAnimationWrapper.hasTargets()) {
            // If there are no targets, then we don't need to capture anything
            setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
        } else {
            boolean finishTransitionPosted = false;
            SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
            if (controller != null) {
                // Update the screenshot of the task
                if (mTaskSnapshot == null) {
@@ -1123,34 +1131,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
                if (taskView != null && !mCanceled) {
                    // Defer finishing the animation until the next launcher frame with the
                    // new thumbnail
                    finishTransitionPosted = 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 we were cancelled after this was attached, do not update
                            // the state.
                            if (mCanceled) {
                                detach();
                                return;
                            }

                            if (mDeferFrameCount > 0) {
                                mDeferFrameCount--;
                                // Workaround, detach and reattach to invalidate the root node for
                                // another draw
                                detach();
                                attach();
                                taskView.invalidate();
                                return;
                            }

                            setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
                            detach();
                        }
                    }.attach();
                    finishTransitionPosted = ViewUtils.postDraw(taskView,
                            () -> setStateOnUiThread(STATE_SCREENSHOT_CAPTURED), this::isCanceled);
                }
            }
            if (!finishTransitionPosted) {
+6 −1
Original line number Diff line number Diff line
@@ -78,8 +78,13 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements StateL

    @Override
    public void startHome() {
        if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
            switchToScreenshot(() -> finishRecentsAnimation(true /* toRecents */,
                    () -> mActivity.getStateManager().goToState(NORMAL)));
        } else {
            mActivity.getStateManager().goToState(NORMAL);
        }
    }

    @Override
    public void setTranslationY(float translationY) {
Loading