Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +1 −2 Original line number Diff line number Diff line Loading @@ -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)); Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesTransitionObserver.java +1 −53 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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 Loading @@ -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) { Loading Loading @@ -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) { Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +0 −4 Original line number Diff line number Diff line Loading @@ -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()); } Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblesTransitionObserverTest.kt +2 −71 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading Loading @@ -181,7 +165,6 @@ class BubblesTransitionObserverTest : ShellTestCase() { transitionObserver.onTransitionReady(mock(), tc.info, mock(), mock()) verify(bubbleData, never()).setExpanded(false) verifyNoInteractions(splitScreenController) } @Test Loading Loading @@ -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, Loading Loading @@ -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 } } Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +1 −2 Original line number Diff line number Diff line Loading @@ -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)); Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesTransitionObserver.java +1 −53 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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 Loading @@ -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) { Loading Loading @@ -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) { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +0 −4 Original line number Diff line number Diff line Loading @@ -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()); } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblesTransitionObserverTest.kt +2 −71 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading Loading @@ -181,7 +165,6 @@ class BubblesTransitionObserverTest : ShellTestCase() { transitionObserver.onTransitionReady(mock(), tc.info, mock(), mock()) verify(bubbleData, never()).setExpanded(false) verifyNoInteractions(splitScreenController) } @Test Loading Loading @@ -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, Loading Loading @@ -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 } } Loading