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

Commit 24c5a269 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Change back navigation impl to rely on observer" into main

parents e5ff3158 ae9506b4
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.activityembedding.ActivityEmbeddingController;
import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser;
import com.android.wm.shell.apptoweb.AssistContentRequester;
import com.android.wm.shell.back.BackAnimationController;
import com.android.wm.shell.bubbles.BubbleController;
import com.android.wm.shell.bubbles.BubbleData;
import com.android.wm.shell.bubbles.BubbleDataRepository;
@@ -87,7 +88,6 @@ import com.android.wm.shell.desktopmode.DesktopModeEventLogger;
import com.android.wm.shell.desktopmode.DesktopModeKeyGestureHandler;
import com.android.wm.shell.desktopmode.DesktopModeLoggerTransitionObserver;
import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger;
import com.android.wm.shell.desktopmode.DesktopRepository;
import com.android.wm.shell.desktopmode.DesktopTaskChangeListener;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.desktopmode.DesktopTasksLimiter;
@@ -1049,6 +1049,7 @@ public abstract class WMShellModule {
            Transitions transitions,
            ShellTaskOrganizer shellTaskOrganizer,
            Optional<DesktopMixedTransitionHandler> desktopMixedTransitionHandler,
            Optional<BackAnimationController> backAnimationController,
            ShellInit shellInit) {
        return desktopUserRepositories.flatMap(
                repository ->
@@ -1059,6 +1060,7 @@ public abstract class WMShellModule {
                                        transitions,
                                        shellTaskOrganizer,
                                        desktopMixedTransitionHandler.get(),
                                        backAnimationController.get(),
                                        shellInit)));
    }

+0 −10
Original line number Diff line number Diff line
@@ -1777,16 +1777,6 @@ 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(
+62 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.window.TransitionInfo
import android.window.WindowContainerTransaction
import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.back.BackAnimationController
import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.isExitDesktopModeTransition
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
import com.android.wm.shell.shared.TransitionUtil
@@ -48,6 +49,7 @@ class DesktopTasksTransitionObserver(
    private val transitions: Transitions,
    private val shellTaskOrganizer: ShellTaskOrganizer,
    private val desktopMixedTransitionHandler: DesktopMixedTransitionHandler,
    private val backAnimationController: BackAnimationController,
    shellInit: ShellInit,
) : Transitions.TransitionObserver {

@@ -128,21 +130,80 @@ class DesktopTasksTransitionObserver(
                    )
                }
            }
        } else if (info.type == TRANSIT_CLOSE) {
            // In some cases app will be closing as a result of back navigation but we would like
            // to minimize. Mark the task closing as minimized.
            var hasWallpaperClosing = false
            var minimizingTask: Int? = null
            for (change in info.changes) {
                val taskInfo = change.taskInfo
                if (taskInfo == null || taskInfo.taskId == -1) continue
                if (change.mode != TRANSIT_CLOSE) continue

                if (minimizingTask == null) {
                    minimizingTask = getMinimizingTaskForClosingTransition(taskInfo)
                }

                if (DesktopWallpaperActivity.isWallpaperTask(taskInfo)) {
                    hasWallpaperClosing = true
                }
            }

            if (minimizingTask == null) return
            // If the transition has wallpaper closing, it means we are moving out of desktop.
            desktopMixedTransitionHandler.addPendingMixedTransition(
                DesktopMixedTransitionHandler.PendingMixedTransition.Minimize(
                    transition,
                    minimizingTask,
                    isLastTask = hasWallpaperClosing,
                )
            )
        }
    }

    /**
     * Given this a closing task in a closing transition, a task is assumed to be closed by back
     * navigation if:
     * 1) Desktop mode is visible.
     * 2) Task is in freeform.
     * 3) Task is the latest task that the back gesture is triggered on.
     * 4) It's not marked as a closing task as a result of closing it by the app header.
     *
     * This doesn't necessarily mean all the cases are because of back navigation but those cases
     * will be rare. E.g. triggering back navigation on an app that pops up a close dialog, and
     * closing it will minimize it here.
     */
    private fun getMinimizingTaskForClosingTransition(
        taskInfo: ActivityManager.RunningTaskInfo
    ): Int? {
        val desktopRepository = desktopUserRepositories.getProfile(taskInfo.userId)
        val visibleTaskCount = desktopRepository.getVisibleTaskCount(taskInfo.displayId)
        if (
            visibleTaskCount > 0 &&
                taskInfo.windowingMode == WINDOWING_MODE_FREEFORM &&
                backAnimationController.latestTriggerBackTask == taskInfo.taskId &&
                !desktopRepository.isClosingTask(taskInfo.taskId)
        ) {
            desktopRepository.minimizeTask(taskInfo.displayId, taskInfo.taskId)
            return taskInfo.taskId
        }
        return null
    }

    private fun removeWallpaperOnLastTaskClosingIfNeeded(
        transition: IBinder,
        info: TransitionInfo,
    ) {
        // TODO: 380868195 - Smooth animation for wallpaper activity closing just by itself
        for (change in info.changes) {
            val taskInfo = change.taskInfo
            if (taskInfo == null || taskInfo.taskId == -1) {
                continue
            }

            val desktopRepository = desktopUserRepositories.getProfile(taskInfo.userId)
            if (
                desktopRepository.getVisibleTaskCount(taskInfo.displayId) == 1 &&
                desktopRepository.getVisibleTaskCount(taskInfo.displayId) == 0 &&
                    change.mode == TRANSIT_CLOSE &&
                    taskInfo.windowingMode == WINDOWING_MODE_FREEFORM &&
                    desktopRepository.wallpaperActivityToken != null
+6 −8
Original line number Diff line number Diff line
@@ -30,8 +30,8 @@ import com.android.internal.protolog.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.LaunchAdjacentController;
import com.android.wm.shell.desktopmode.DesktopRepository;
import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.sysui.ShellInit;
@@ -121,15 +121,13 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
                    mDesktopUserRepositories.get().getProfile(taskInfo.userId);
            // TODO: b/370038902 - Handle Activity#finishAndRemoveTask.
            if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue()
                    || repository.isClosingTask(taskInfo.taskId)) {
                    || !repository.isMinimizedTask(taskInfo.taskId)) {
                // A task that's vanishing should be removed:
                // - If it's closed by the X button which means it's marked as a closing task.
                // - If it's not yet minimized. It can be minimized when a back navigation is
                // triggered on a task and the task is closing. It will be marked as minimized in
                // [DesktopTasksTransitionObserver] before it gets here.
                repository.removeClosingTask(taskInfo.taskId);
                repository.removeFreeformTask(taskInfo.displayId, taskInfo.taskId);
            } else {
                repository.updateTask(taskInfo.displayId, taskInfo.taskId, /* isVisible= */
                        false);
                repository.minimizeTask(taskInfo.displayId, taskInfo.taskId);
            }
        }
        mWindowDecorationViewModel.onTaskVanished(taskInfo);
+88 −26
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import com.android.modules.utils.testing.ExtendedMockitoRule
import com.android.window.flags.Flags
import com.android.wm.shell.MockToken
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.back.BackAnimationController
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_EXIT_DESKTOP_MODE_TASK_DRAG
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
@@ -67,9 +68,7 @@ class DesktopTasksTransitionObserverTest {
    @JvmField
    @Rule
    val extendedMockitoRule =
        ExtendedMockitoRule.Builder(this)
            .mockStatic(DesktopModeStatus::class.java)
            .build()!!
        ExtendedMockitoRule.Builder(this).mockStatic(DesktopModeStatus::class.java).build()!!

    private val testExecutor = mock<ShellExecutor>()
    private val mockShellInit = mock<ShellInit>()
@@ -79,6 +78,7 @@ class DesktopTasksTransitionObserverTest {
    private val userRepositories = mock<DesktopUserRepositories>()
    private val taskRepository = mock<DesktopRepository>()
    private val mixedHandler = mock<DesktopMixedTransitionHandler>()
    private val backAnimationController = mock<BackAnimationController>()

    private lateinit var transitionObserver: DesktopTasksTransitionObserver
    private lateinit var shellInit: ShellInit
@@ -93,7 +93,13 @@ class DesktopTasksTransitionObserverTest {

        transitionObserver =
            DesktopTasksTransitionObserver(
                context, userRepositories, transitions, shellTaskOrganizer, mixedHandler, shellInit
                context,
                userRepositories,
                transitions,
                shellTaskOrganizer,
                mixedHandler,
                backAnimationController,
                shellInit
            )
    }

@@ -105,8 +111,7 @@ class DesktopTasksTransitionObserverTest {

        transitionObserver.onTransitionReady(
            transition = mock(),
            info =
            createBackNavigationTransition(task),
            info = createBackNavigationTransition(task),
            startTransaction = mock(),
            finishTransaction = mock(),
        )
@@ -115,6 +120,52 @@ class DesktopTasksTransitionObserverTest {
        verify(mixedHandler).addPendingMixedTransition(any())
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION)
    fun backNavigation_withCloseTransitionNotLastTask_taskMinimized() {
        val task = createTaskInfo(1)
        val transition = mock<IBinder>()
        whenever(taskRepository.getVisibleTaskCount(any())).thenReturn(2)
        whenever(taskRepository.isClosingTask(task.taskId)).thenReturn(false)
        whenever(backAnimationController.latestTriggerBackTask).thenReturn(task.taskId)

        transitionObserver.onTransitionReady(
            transition = transition,
            info = createBackNavigationTransition(task, TRANSIT_CLOSE),
            startTransaction = mock(),
            finishTransaction = mock(),
        )

        verify(taskRepository).minimizeTask(task.displayId, task.taskId)
        val pendingTransition =
            DesktopMixedTransitionHandler.PendingMixedTransition.Minimize(
                transition, task.taskId, isLastTask = false)
        verify(mixedHandler).addPendingMixedTransition(pendingTransition)
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION)
    fun backNavigation_withCloseTransitionLastTask_taskMinimized() {
        val task = createTaskInfo(1)
        val transition = mock<IBinder>()
        whenever(taskRepository.getVisibleTaskCount(any())).thenReturn(1)
        whenever(taskRepository.isClosingTask(task.taskId)).thenReturn(false)
        whenever(backAnimationController.latestTriggerBackTask).thenReturn(task.taskId)

        transitionObserver.onTransitionReady(
            transition = transition,
            info = createBackNavigationTransition(task, TRANSIT_CLOSE, true),
            startTransaction = mock(),
            finishTransaction = mock(),
        )

        verify(taskRepository).minimizeTask(task.displayId, task.taskId)
        val pendingTransition =
            DesktopMixedTransitionHandler.PendingMixedTransition.Minimize(
                transition, task.taskId, isLastTask = true)
        verify(mixedHandler).addPendingMixedTransition(pendingTransition)
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION)
    fun backNavigation_nullTaskInfo_taskNotMinimized() {
@@ -123,8 +174,7 @@ class DesktopTasksTransitionObserverTest {

        transitionObserver.onTransitionReady(
            transition = mock(),
            info =
            createBackNavigationTransition(null),
            info = createBackNavigationTransition(null),
            startTransaction = mock(),
            finishTransaction = mock(),
        )
@@ -173,7 +223,7 @@ class DesktopTasksTransitionObserverTest {
        val mockTransition = Mockito.mock(IBinder::class.java)
        val task = createTaskInfo(1, WINDOWING_MODE_FREEFORM)
        val wallpaperToken = MockToken().token()
        whenever(taskRepository.getVisibleTaskCount(task.displayId)).thenReturn(1)
        whenever(taskRepository.getVisibleTaskCount(task.displayId)).thenReturn(0)
        whenever(taskRepository.wallpaperActivityToken).thenReturn(wallpaperToken)

        transitionObserver.onTransitionReady(
@@ -190,17 +240,27 @@ class DesktopTasksTransitionObserverTest {
    }

    private fun createBackNavigationTransition(
        task: RunningTaskInfo?
        task: RunningTaskInfo?,
        type: Int = TRANSIT_TO_BACK,
        withWallpaper: Boolean = false,
    ): TransitionInfo {
        return TransitionInfo(TRANSIT_TO_BACK, 0 /* flags */).apply {
        return TransitionInfo(type, 0 /* flags */).apply {
            addChange(
                Change(mock(), mock()).apply {
                    mode = TRANSIT_TO_BACK
                    mode = type
                    parent = null
                    taskInfo = task
                    flags = flags
                })
            if (withWallpaper) {
                addChange(
                    Change(mock(), mock()).apply {
                        mode = TRANSIT_CLOSE
                        parent = null
                        taskInfo = createWallpaperTaskInfo()
                        flags = flags
                    })
            }
            )
        }
    }

@@ -215,14 +275,11 @@ class DesktopTasksTransitionObserverTest {
                    parent = null
                    taskInfo = task
                    flags = flags
                }
            )
                })
        }
    }

    private fun createCloseTransition(
        task: RunningTaskInfo?
    ): TransitionInfo {
    private fun createCloseTransition(task: RunningTaskInfo?): TransitionInfo {
        return TransitionInfo(TRANSIT_CLOSE, 0 /* flags */).apply {
            addChange(
                Change(mock(), mock()).apply {
@@ -230,8 +287,7 @@ class DesktopTasksTransitionObserverTest {
                    parent = null
                    taskInfo = task
                    flags = flags
                }
            )
                })
        }
    }

@@ -243,8 +299,7 @@ class DesktopTasksTransitionObserverTest {
        if (handlerClass == null) {
            Mockito.verify(transitions).startTransition(eq(type), arg.capture(), isNull())
        } else {
            Mockito.verify(transitions)
                .startTransition(eq(type), arg.capture(), isA(handlerClass))
            Mockito.verify(transitions).startTransition(eq(type), arg.capture(), isA(handlerClass))
        }
        return arg.value
    }
@@ -268,8 +323,15 @@ class DesktopTasksTransitionObserverTest {
            displayId = DEFAULT_DISPLAY
            configuration.windowConfiguration.windowingMode = windowingMode
            token = WindowContainerToken(Mockito.mock(IWindowContainerToken::class.java))
            baseIntent = Intent().apply {
                component = ComponentName("package", "component.name")
            baseIntent = Intent().apply { component = ComponentName("package", "component.name") }
        }

    private fun createWallpaperTaskInfo() =
        RunningTaskInfo().apply {
            token = mock<WindowContainerToken>()
            baseIntent =
                Intent().apply {
                    component = DesktopWallpaperActivity.wallpaperActivityComponent
                }
        }
}
Loading