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

Commit b6a05de8 authored by Orhan Uysal's avatar Orhan Uysal Committed by Android (Google) Code Review
Browse files

Merge "Add back nav animation with minimizing." into main

parents bb02db33 b90ac32f
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ import com.android.wm.shell.dagger.pip.PipModule;
import com.android.wm.shell.desktopmode.CloseDesktopTaskTransitionHandler;
import com.android.wm.shell.desktopmode.DefaultDragToDesktopTransitionHandler;
import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler;
import com.android.wm.shell.desktopmode.DesktopBackNavigationTransitionHandler;
import com.android.wm.shell.desktopmode.DesktopDisplayEventHandler;
import com.android.wm.shell.desktopmode.DesktopImmersiveController;
import com.android.wm.shell.desktopmode.DesktopMixedTransitionHandler;
@@ -913,6 +914,16 @@ public abstract class WMShellModule {
        return new CloseDesktopTaskTransitionHandler(context, mainExecutor, animExecutor);
    }

    @WMSingleton
    @Provides
    static DesktopBackNavigationTransitionHandler provideDesktopBackNavigationTransitionHandler(
            @ShellMainThread ShellExecutor mainExecutor,
            @ShellAnimationThread ShellExecutor animExecutor,
            DisplayController displayController) {
        return new DesktopBackNavigationTransitionHandler(mainExecutor, animExecutor,
                displayController);
    }

    @WMSingleton
    @Provides
    static DesktopModeDragAndDropTransitionHandler provideDesktopModeDragAndDropTransitionHandler(
@@ -964,6 +975,7 @@ public abstract class WMShellModule {
            Optional<DesktopRepository> desktopRepository,
            Transitions transitions,
            ShellTaskOrganizer shellTaskOrganizer,
            Optional<DesktopMixedTransitionHandler> desktopMixedTransitionHandler,
            ShellInit shellInit) {
        return desktopRepository.flatMap(
                repository ->
@@ -973,6 +985,7 @@ public abstract class WMShellModule {
                                        repository,
                                        transitions,
                                        shellTaskOrganizer,
                                        desktopMixedTransitionHandler.get(),
                                        shellInit)));
    }

@@ -985,6 +998,7 @@ public abstract class WMShellModule {
            FreeformTaskTransitionHandler freeformTaskTransitionHandler,
            CloseDesktopTaskTransitionHandler closeDesktopTaskTransitionHandler,
            Optional<DesktopImmersiveController> desktopImmersiveController,
            DesktopBackNavigationTransitionHandler desktopBackNavigationTransitionHandler,
            InteractionJankMonitor interactionJankMonitor,
            @ShellMainThread Handler handler,
            ShellInit shellInit,
@@ -1001,6 +1015,7 @@ public abstract class WMShellModule {
                        freeformTaskTransitionHandler,
                        closeDesktopTaskTransitionHandler,
                        desktopImmersiveController.get(),
                        desktopBackNavigationTransitionHandler,
                        interactionJankMonitor,
                        handler,
                        shellInit,
+97 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.wm.shell.desktopmode

import android.animation.Animator
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.os.IBinder
import android.util.DisplayMetrics
import android.view.SurfaceControl.Transaction
import android.window.TransitionInfo
import android.window.TransitionRequestInfo
import android.window.WindowContainerTransaction
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.shared.TransitionUtil
import com.android.wm.shell.shared.animation.MinimizeAnimator.create
import com.android.wm.shell.transition.Transitions

/**
 * The [Transitions.TransitionHandler] that handles transitions for tasks that are closing or going
 * to back as part of back navigation. This handler is used only for animating transitions.
 */
class DesktopBackNavigationTransitionHandler(
    private val mainExecutor: ShellExecutor,
    private val animExecutor: ShellExecutor,
    private val displayController: DisplayController,
) : Transitions.TransitionHandler {

    /** Shouldn't handle anything */
    override fun handleRequest(
        transition: IBinder,
        request: TransitionRequestInfo,
    ): WindowContainerTransaction? = null

    /** Animates a transition with minimizing tasks */
    override fun startAnimation(
        transition: IBinder,
        info: TransitionInfo,
        startTransaction: Transaction,
        finishTransaction: Transaction,
        finishCallback: Transitions.TransitionFinishCallback,
    ): Boolean {
        if (!TransitionUtil.isClosingType(info.type)) return false

        val animations = mutableListOf<Animator>()
        val onAnimFinish: (Animator) -> Unit = { animator ->
            mainExecutor.execute {
                // Animation completed
                animations.remove(animator)
                if (animations.isEmpty()) {
                    // All animations completed, finish the transition
                    finishCallback.onTransitionFinished(/* wct= */ null)
                }
            }
        }

        animations +=
            info.changes
                .filter {
                    it.mode == info.type &&
                            it.taskInfo?.windowingMode == WINDOWING_MODE_FREEFORM
                }
                .mapNotNull { createMinimizeAnimation(it, finishTransaction, onAnimFinish) }
        if (animations.isEmpty()) return false
        animExecutor.execute { animations.forEach(Animator::start) }
        return true
    }

    private fun createMinimizeAnimation(
        change: TransitionInfo.Change,
        finishTransaction: Transaction,
        onAnimFinish: (Animator) -> Unit
    ): Animator? {
        val t = Transaction()
        val sc = change.leash
        finishTransaction.hide(sc)
        val displayMetrics: DisplayMetrics? =
            change.taskInfo?.let {
                displayController.getDisplayContext(it.displayId)?.getResources()?.displayMetrics
            }
        return displayMetrics?.let { create(it, change, t, onAnimFinish) }
    }
}
+53 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ class DesktopMixedTransitionHandler(
    private val freeformTaskTransitionHandler: FreeformTaskTransitionHandler,
    private val closeDesktopTaskTransitionHandler: CloseDesktopTaskTransitionHandler,
    private val desktopImmersiveController: DesktopImmersiveController,
    private val desktopBackNavigationTransitionHandler: DesktopBackNavigationTransitionHandler,
    private val interactionJankMonitor: InteractionJankMonitor,
    @ShellMainThread private val handler: Handler,
    shellInit: ShellInit,
@@ -161,6 +162,14 @@ class DesktopMixedTransitionHandler(
                finishTransaction,
                finishCallback
            )
            is PendingMixedTransition.Minimize -> animateMinimizeTransition(
                pending,
                transition,
                info,
                startTransaction,
                finishTransaction,
                finishCallback
            )
        }
    }

@@ -272,6 +281,42 @@ class DesktopMixedTransitionHandler(
        )
    }

    private fun animateMinimizeTransition(
        pending: PendingMixedTransition.Minimize,
        transition: IBinder,
        info: TransitionInfo,
        startTransaction: SurfaceControl.Transaction,
        finishTransaction: SurfaceControl.Transaction,
        finishCallback: TransitionFinishCallback,
    ): Boolean {
        if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue) return false

        val minimizeChange = findDesktopTaskChange(info, pending.minimizingTask)
        if (minimizeChange == null) {
            logW("Should have minimizing desktop task")
            return false
        }
        if (pending.isLastTask) {
            // Dispatch close desktop task animation to the default transition handlers.
            return dispatchToLeftoverHandler(
                transition,
                info,
                startTransaction,
                finishTransaction,
                finishCallback
            )
        }

        // Animate minimizing desktop task transition with [DesktopBackNavigationTransitionHandler].
        return desktopBackNavigationTransitionHandler.startAnimation(
            transition,
            info,
            startTransaction,
            finishTransaction,
            finishCallback,
        )
    }

    override fun onTransitionConsumed(
        transition: IBinder,
        aborted: Boolean,
@@ -400,6 +445,14 @@ class DesktopMixedTransitionHandler(
            val minimizingTask: Int?,
            val exitingImmersiveTask: Int?,
        ) : PendingMixedTransition()

        /** A task is minimizing. This should be used for task going to back and some closing cases
         * with back navigation. */
        data class Minimize(
            override val transition: IBinder,
            val minimizingTask: Int,
            val isLastTask: Boolean,
        ) : PendingMixedTransition()
    }

    private fun logV(msg: String, vararg arguments: Any?) {
+14 −3
Original line number Diff line number Diff line
@@ -1290,7 +1290,11 @@ class DesktopTasksController(
                    // Check if freeform task launch during recents should be handled
                    shouldHandleMidRecentsFreeformLaunch -> handleMidRecentsFreeformTaskLaunch(task)
                    // Check if the closing task needs to be handled
                    TransitionUtil.isClosingType(request.type) -> handleTaskClosing(task)
                    TransitionUtil.isClosingType(request.type) -> handleTaskClosing(
                        task,
                        transition,
                        request.type
                    )
                    // Check if the top task shouldn't be allowed to enter desktop mode
                    isIncompatibleTask(task) -> handleIncompatibleTaskLaunch(task)
                    // Check if fullscreen task should be updated
@@ -1620,7 +1624,7 @@ class DesktopTasksController(
    }

    /** Handle task closing by removing wallpaper activity if it's the last active task */
    private fun handleTaskClosing(task: RunningTaskInfo): WindowContainerTransaction? {
    private fun handleTaskClosing(task: RunningTaskInfo, transition: IBinder, requestType: Int): WindowContainerTransaction? {
        logV("handleTaskClosing")
        if (!isDesktopModeShowing(task.displayId))
            return null
@@ -1636,8 +1640,15 @@ class DesktopTasksController(
        if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue()) {
            taskRepository.addClosingTask(task.displayId, task.taskId)
            desktopTilingDecorViewModel.removeTaskIfTiled(task.displayId, task.taskId)
        } else if (requestType == TRANSIT_CLOSE) {
            // Handle closing tasks, tasks that are going to back are handled in
            // [DesktopTasksTransitionObserver].
            desktopMixedTransitionHandler.addPendingMixedTransition(
                DesktopMixedTransitionHandler.PendingMixedTransition.Minimize(
                    transition, task.taskId, taskRepository.getVisibleTaskCount(task.displayId) == 1
                )
            )
        }

        taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate(
            doesAnyTaskRequireTaskbarRounding(
                task.displayId,
+8 −3
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ class DesktopTasksTransitionObserver(
    private val desktopRepository: DesktopRepository,
    private val transitions: Transitions,
    private val shellTaskOrganizer: ShellTaskOrganizer,
    private val desktopMixedTransitionHandler: DesktopMixedTransitionHandler,
    shellInit: ShellInit
) : Transitions.TransitionObserver {

@@ -71,7 +72,7 @@ class DesktopTasksTransitionObserver(
        // TODO: b/332682201 Update repository state
        updateWallpaperToken(info)
        if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue()) {
            handleBackNavigation(info)
            handleBackNavigation(transition, info)
            removeTaskIfNeeded(info)
        }
        removeWallpaperOnLastTaskClosingIfNeeded(transition, info)
@@ -95,7 +96,7 @@ class DesktopTasksTransitionObserver(
        }
    }

    private fun handleBackNavigation(info: TransitionInfo) {
    private fun handleBackNavigation(transition: IBinder, info: TransitionInfo) {
        // When default back navigation happens, transition type is TO_BACK and the change is
        // TO_BACK. Mark the task going to back as minimized.
        if (info.type == TRANSIT_TO_BACK) {
@@ -105,10 +106,14 @@ class DesktopTasksTransitionObserver(
                    continue
                }

                if (desktopRepository.getVisibleTaskCount(taskInfo.displayId) > 0 &&
                val visibleTaskCount = desktopRepository.getVisibleTaskCount(taskInfo.displayId)
                if (visibleTaskCount > 0 &&
                    change.mode == TRANSIT_TO_BACK &&
                    taskInfo.windowingMode == WINDOWING_MODE_FREEFORM) {
                    desktopRepository.minimizeTask(taskInfo.displayId, taskInfo.taskId)
                    desktopMixedTransitionHandler.addPendingMixedTransition(
                        DesktopMixedTransitionHandler.PendingMixedTransition.Minimize(
                            transition, taskInfo.taskId, visibleTaskCount == 1))
                }
            }
        }
Loading