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

Commit 44cdf168 authored by Eric Lin's avatar Eric Lin Committed by Android (Google) Code Review
Browse files

Merge "Update task info before notifying task removal." into main

parents 2f5c9344 7a84e808
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper;

import java.io.PrintWriter;
import java.util.concurrent.Executor;
@@ -292,7 +293,11 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
        if (mTaskToken == null || !mTaskToken.equals(taskInfo.token)) return;

        final SurfaceControl taskLeash = mTaskLeash;
        if (BubbleAnythingFlagHelper.enableCreateAnyBubble()) {
            handleAndNotifyTaskRemoval(taskInfo);
        } else {
            handleAndNotifyTaskRemoval(mTaskInfo);
        }

        mTransaction.reparent(taskLeash, null).apply();
        resetTaskInfo();
@@ -454,6 +459,20 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
        if (mListener == null) return;
        ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "TaskController.notifyTaskRemovalStarted(): taskView=%d "
                + "task=%s", hashCode(), taskInfo);

        if (BubbleAnythingFlagHelper.enableCreateAnyBubble()) {
            // Update mTaskInfo to reflect the latest task state before notifying the listener, as
            // it may have been changed by ShellTaskOrganizer#onTaskInfoChanged(), which triggers
            // task listener updates via ShellTaskOrganizer#updateTaskListenerIfNeeded() when a
            // task's info changes, resulting in onTaskVanished() being called on the old listener;
            // without updating mTaskInfo here would leave it with outdated information (e.g.,
            // windowing mode), potentially causing incorrect state checks and unintended cleanup
            // actions in consumers of TaskViewTaskController, such as task removal in
            // BubbleTaskView#cleanup.
            mTaskInfo = taskInfo;
            mTaskToken = mTaskInfo.token;
        }

        final int taskId = taskInfo.taskId;
        mListenerExecutor.execute(() -> mListener.onTaskRemovalStarted(taskId));
    }
+54 −3
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.wm.shell.taskview;

import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;

import static com.google.common.truth.Truth.assertThat;
@@ -32,6 +33,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -67,6 +69,7 @@ import com.android.wm.shell.TestHandler;
import com.android.wm.shell.common.HandlerExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.SyncTransactionQueue.TransactionRunnable;
import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper;
import com.android.wm.shell.transition.Transitions;

import org.junit.After;
@@ -79,11 +82,11 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;

import java.util.List;

import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
import platform.test.runner.parameterized.Parameters;

import java.util.List;

@SmallTest
@RunWith(ParameterizedAndroidJunit4.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@@ -91,7 +94,10 @@ public class TaskViewTest extends ShellTestCase {

    @Parameters(name = "{0}")
    public static List<FlagsParameterization> getParams() {
        return FlagsParameterization.allCombinationsOf(Flags.FLAG_TASK_VIEW_REPOSITORY);
        return FlagsParameterization.allCombinationsOf(
                Flags.FLAG_TASK_VIEW_REPOSITORY,
                Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE
        );
    }

    @Mock
@@ -433,6 +439,51 @@ public class TaskViewTest extends ShellTestCase {
        verify(mViewListener).onTaskRemovalStarted(eq(mTaskInfo.taskId));
    }

    @Test
    public void testOnTaskVanished_withTaskInfoUpdate_notifiesTaskRemoval() {
        assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);

        // Capture task info when onTaskRemovalStarted is triggered on the task view listener.
        final ActivityManager.RunningTaskInfo[] capturedTaskInfo =
                new ActivityManager.RunningTaskInfo[1];
        final int taskId = mTaskInfo.taskId;
        doAnswer(invocation -> {
            capturedTaskInfo[0] = mTaskView.getTaskInfo();
            return null;
        }).when(mViewListener).onTaskRemovalStarted(taskId);

        // Set up a mock TaskViewBase to verify notified task info.
        final TaskViewBase mockTaskViewBase = mock(TaskViewBase.class);
        mTaskViewTaskController.setTaskViewBase(mockTaskViewBase);

        // Prepare and trigger task opening animation with mTaskInfo.
        mTaskViewTransitions.prepareOpenAnimation(mTaskViewTaskController, true /* newTask */,
                new SurfaceControl.Transaction(), new SurfaceControl.Transaction(), mTaskInfo,
                mLeash, new WindowContainerTransaction());
        mTaskView.surfaceCreated(mock(SurfaceHolder.class));

        // Simulate task info change with windowing mode update.
        final ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo();
        newTaskInfo.token = mTaskInfo.token;
        newTaskInfo.taskId = taskId;
        newTaskInfo.taskDescription = mTaskInfo.taskDescription;
        newTaskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);

        // Invoke onTaskVanished with updated task info.
        mTaskViewTaskController.onTaskVanished(newTaskInfo);

        verify(mViewListener).onTaskRemovalStarted(taskId);
        if (BubbleAnythingFlagHelper.enableCreateAnyBubble()) {
            // Verify TaskViewBase and listener updates with new task info.
            verify(mockTaskViewBase).onTaskVanished(same(newTaskInfo));
            assertThat(capturedTaskInfo[0]).isSameInstanceAs(newTaskInfo);
        } else {
            // Verify TaskViewBase and listener updates with old task info.
            verify(mockTaskViewBase).onTaskVanished(same(mTaskInfo));
            assertThat(capturedTaskInfo[0]).isSameInstanceAs(mTaskInfo);
        }
    }

    @Test
    public void testOnBackPressedOnTaskRoot() {
        assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);