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

Commit 98227099 authored by Ats Jenk's avatar Ats Jenk Committed by Android (Google) Code Review
Browse files

Merge "Revert "Remove a task from bubbles if it is moving to split"" into main

parents b738d680 92fce6c4
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -510,8 +510,7 @@ public class BubbleController implements ConfigurationChangeListener,
            }
        }, mMainHandler);

        mTransitions.registerObserver(new BubblesTransitionObserver(this, mBubbleData,
                mBubbleTransitions.mTaskViewTransitions, mSplitScreenController));
        mTransitions.registerObserver(new BubblesTransitionObserver(this, mBubbleData));

        mTaskStackListener.addListener(
                new BubbleTaskStackListener(this, mBubbleData, mSplitScreenController));
+1 −53
Original line number Diff line number Diff line
@@ -18,32 +18,21 @@ package com.android.wm.shell.bubbles;

import static android.app.ActivityTaskManager.INVALID_TASK_ID;

import static com.android.wm.shell.bubbles.util.BubbleUtils.getExitBubbleTransaction;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BUBBLES_NOISY;

import android.app.ActivityManager;
import android.os.Binder;
import android.os.IBinder;
import android.view.SurfaceControl;
import android.window.ActivityTransitionInfo;
import android.window.TransitionInfo;
import android.window.WindowContainerTransaction;

import androidx.annotation.NonNull;

import com.android.internal.protolog.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.shared.TransitionUtil;
import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.taskview.TaskViewTaskController;
import com.android.wm.shell.taskview.TaskViewTransitions;
import com.android.wm.shell.transition.Transitions;

import dagger.Lazy;

import java.util.Optional;

/**
 * Observer used to identify tasks that are opening or moving to front. If a bubble activity is
 * currently opened when this happens, we'll collapse the bubbles.
@@ -54,18 +43,11 @@ public class BubblesTransitionObserver implements Transitions.TransitionObserver
    private final BubbleController mBubbleController;
    @NonNull
    private final BubbleData mBubbleData;
    @NonNull
    private final TaskViewTransitions mTaskViewTransitions;
    private final Lazy<Optional<SplitScreenController>> mSplitScreenController;

    public BubblesTransitionObserver(@NonNull BubbleController controller,
            @NonNull BubbleData bubbleData,
            @NonNull TaskViewTransitions taskViewTransitions,
            Lazy<Optional<SplitScreenController>> splitScreenController) {
            @NonNull BubbleData bubbleData) {
        mBubbleController = controller;
        mBubbleData = bubbleData;
        mTaskViewTransitions = taskViewTransitions;
        mSplitScreenController = splitScreenController;
    }

    @Override
@@ -73,11 +55,6 @@ public class BubblesTransitionObserver implements Transitions.TransitionObserver
            @NonNull SurfaceControl.Transaction startTransaction,
            @NonNull SurfaceControl.Transaction finishTransaction) {
        collapseBubbleIfNeeded(info);
        if (BubbleAnythingFlagHelper.enableCreateAnyBubble()) {
            if (TransitionUtil.isOpeningType(info.getType()) && mBubbleData.hasBubbles()) {
                removeBubbleIfLaunchingToSplit(info);
            }
        }
    }

    private void collapseBubbleIfNeeded(@NonNull TransitionInfo info) {
@@ -156,35 +133,6 @@ public class BubblesTransitionObserver implements Transitions.TransitionObserver
        return false;
    }

    private void removeBubbleIfLaunchingToSplit(@NonNull TransitionInfo info) {
        if (mSplitScreenController.get().isEmpty()) return;
        SplitScreenController splitScreenController = mSplitScreenController.get().get();
        for (TransitionInfo.Change change : info.getChanges()) {
            ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
            if (taskInfo == null) continue;
            Bubble bubble = mBubbleData.getBubbleInStackWithTaskId(taskInfo.taskId);
            if (bubble == null) continue;
            if (!splitScreenController.isTaskRootOrStageRoot(taskInfo.parentTaskId)) continue;
            // There is a bubble task that is moving to split screen
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "BubblesTransitionObserver.onTransitionReady(): "
                    + "removing bubble for task launching into split taskId=%d", taskInfo.taskId);
            TaskViewTaskController taskViewTaskController = bubble.getTaskView().getController();
            ShellTaskOrganizer taskOrganizer = taskViewTaskController.getTaskOrganizer();
            WindowContainerTransaction wct = getExitBubbleTransaction(taskInfo.token,
                    bubble.getTaskView().getCaptionInsetsOwner());

            // Notify the task removal, but block all TaskViewTransitions during removal so we can
            // clear them without triggering
            final IBinder gate = new Binder();
            mTaskViewTransitions.enqueueExternal(taskViewTaskController, () -> gate);

            taskOrganizer.applyTransaction(wct);
            taskViewTaskController.notifyTaskRemovalStarted(taskInfo);
            mTaskViewTransitions.removePendingTransitions(taskViewTaskController);
            mTaskViewTransitions.onExternalDone(gate);
        }
    }

    @Override
    public void onTransitionStarting(@NonNull IBinder transition) {

+0 −4
Original line number Diff line number Diff line
@@ -2057,10 +2057,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        // TODO (b/336477473): Disallow enter PiP when launching a task in split by default;
        //                     this might have to be changed as more split-to-pip cujs are defined.
        options.setDisallowEnterPictureInPictureWhileLaunching(true);
        // Set an empty rect as the requested launch bounds. This ensures that if an existing
        // task is reused, and it has bounds set, they are cleared.
        options.setLaunchBounds(new Rect());

        opts.putAll(options.toBundle());
    }

+2 −71
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.wm.shell.bubbles
import android.app.ActivityManager
import android.app.ActivityTaskManager.INVALID_TASK_ID
import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW
import android.content.ComponentName
import android.platform.test.annotations.EnableFlags
import android.view.WindowManager.TRANSIT_CHANGE
@@ -30,28 +29,19 @@ import android.view.WindowManager.TRANSIT_TO_FRONT
import android.view.WindowManager.TransitionType
import android.window.ActivityTransitionInfo
import android.window.TransitionInfo
import android.window.WindowContainerTransaction
import android.window.WindowContainerToken
import androidx.test.filters.SmallTest
import com.android.wm.shell.Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE
import com.android.wm.shell.MockToken
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.bubbles.util.BubbleTestUtils.verifyExitBubbleTransaction
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.taskview.TaskView
import com.android.wm.shell.taskview.TaskViewTaskController
import com.android.wm.shell.taskview.TaskViewTransitions
import com.android.wm.shell.transition.TransitionInfoBuilder
import com.android.wm.shell.transition.TransitionInfoBuilder.Companion.DEFAULT_DISPLAY_ID
import com.google.testing.junit.testparameterinjector.TestParameter
import com.google.testing.junit.testparameterinjector.TestParameterInjector
import java.util.Optional
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.stub
@@ -78,16 +68,10 @@ class BubblesTransitionObserverTest : ShellTestCase() {
    private val bubbleController = mock<BubbleController> {
        on { isStackAnimating } doReturn false
    }
    private val taskViewTransitions = mock<TaskViewTransitions>()
    private val splitScreenController = mock<SplitScreenController> {
        on { isTaskRootOrStageRoot(any()) } doReturn false
    }
    private val transitionObserver =
        BubblesTransitionObserver(
            bubbleController,
            bubbleData,
            taskViewTransitions,
            { Optional.of(splitScreenController) },
        )

    @Test
@@ -181,7 +165,6 @@ class BubblesTransitionObserverTest : ShellTestCase() {
        transitionObserver.onTransitionReady(mock(), tc.info, mock(), mock())

        verify(bubbleData, never()).setExpanded(false)
        verifyNoInteractions(splitScreenController)
    }

    @Test
@@ -230,58 +213,6 @@ class BubblesTransitionObserverTest : ShellTestCase() {
        verify(bubbleData, never()).setExpanded(false)
    }

    @EnableFlags(FLAG_ENABLE_CREATE_ANY_BUBBLE)
    @Test
    fun testOnTransitionReady_bubbleMovingToSplit_removeBubble() {
        val taskOrganizer = mock<ShellTaskOrganizer>()
        val taskViewTaskController = mock<TaskViewTaskController> {
            on { this.taskOrganizer } doReturn taskOrganizer
        }
        val taskView = mock<TaskView> {
            on { controller } doReturn taskViewTaskController
        }
        bubble.stub {
            on { this.taskView } doReturn taskView
        }
        bubbleData.stub {
            on { getBubbleInStackWithTaskId(bubble.taskId) } doReturn bubble
        }
        splitScreenController.stub {
            on { isTaskRootOrStageRoot(10) } doReturn true
        }
        val taskInfo =
            createTaskInfo(taskId = 1).apply {
                this.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_MULTI_WINDOW
                this.parentTaskId = 10
            }
        val info = createTaskTransition(TRANSIT_TO_FRONT, taskInfo)

        transitionObserver.onTransitionReady(mock(), info, mock(), mock())

        // Check that we remove the taskView
        verify(taskViewTaskController).notifyTaskRemovalStarted(taskInfo)
        val wctCaptor = argumentCaptor<WindowContainerTransaction>()
        // And clean up bubble specific overrides on a task
        verify(taskOrganizer).applyTransaction(wctCaptor.capture())
        verifyExitBubbleTransaction(
            wctCaptor.firstValue,
            taskInfo.token.asBinder(), /* captionInsetsOwner */
            null,
        )
    }

    @EnableFlags(FLAG_ENABLE_CREATE_ANY_BUBBLE)
    @Test
    fun testOnTransitionReady_noBubbles_doesNotCheckForSplitState() {
        bubbleData.stub {
            on { hasBubbles() } doReturn false
        }
        val info = createTaskTransition(TRANSIT_TO_FRONT, taskId = 1)
        transitionObserver.onTransitionReady(mock(), info, mock(), mock())

        verifyNoInteractions(splitScreenController)
    }

    // Transits that aren't opening.
    enum class TransitNotOpeningTestCase(
        @TransitionType private val changeType: Int,
@@ -333,7 +264,7 @@ class BubblesTransitionObserverTest : ShellTestCase() {

        private fun createTaskInfo(taskId: Int) = ActivityManager.RunningTaskInfo().apply {
            this.taskId = taskId
            this.token = MockToken().token()
            this.token = WindowContainerToken(mock() /* realToken */)
            this.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN
        }
    }