Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesTransitionObserver.java +49 −26 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ 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; Loading Loading @@ -53,12 +54,13 @@ 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, TaskViewTransitions taskViewTransitions, @NonNull TaskViewTransitions taskViewTransitions, Lazy<Optional<SplitScreenController>> splitScreenController) { mBubbleController = controller; mBubbleData = bubbleData; Loading Loading @@ -100,37 +102,60 @@ public class BubblesTransitionObserver implements Transitions.TransitionObserver if (!TransitionUtil.isOpeningType(change.getMode())) { continue; } final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); // We only handle task transitions. if (taskInfo == null || taskInfo.taskId == INVALID_TASK_ID) { continue; } // If the opening task id is the same as the expanded bubble, skip collapsing // because it is our bubble that is opening. if (taskInfo.taskId == expandedTaskId) { // If the opening transition is on a different display, skip collapsing because // it does not visually overlap with the bubbles. if (change.getEndDisplayId() != bubbleViewDisplayId) { continue; } // If the opening task is on a different display, skip collapsing because the task // opening does not visually overlap with the bubbles. if (taskInfo.displayId != bubbleViewDisplayId) { final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); final ActivityTransitionInfo activityInfo = change.getActivityTransitionInfo(); if (taskInfo != null) { // Task transition. if (shouldBypassCollapseForTask(taskInfo.taskId, expandedTaskId)) { continue; } // If the opening task was launched by another bubble, skip collapsing the existing one // since BubbleTransitions will start a new bubble for it // If the opening task was launched by another bubble, skip collapsing the // existing one since BubbleTransitions will start a new bubble for it. if (BubbleAnythingFlagHelper.enableCreateAnyBubble() && mBubbleController.shouldBeAppBubble(taskInfo)) { ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "TransitionObserver.onTransitionReady(): " ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "BubblesTransitionObserver.onTransitionReady(): " + "skipping app bubble for taskId=%d", taskInfo.taskId); continue; } } else if (activityInfo != null) { // Activity transition. if (shouldBypassCollapseForTask(activityInfo.getTaskId(), expandedTaskId)) { continue; } } else { // Invalid transition. continue; } ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "TransitionObserver.onTransitionReady(): " + "collapsing bubble for taskId=%d", taskInfo.taskId); ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "BubblesTransitionObserver.onTransitionReady(): " + "collapse the expanded bubble for taskId=%d", expandedTaskId); mBubbleData.setExpanded(false); return; } } /** Checks if a task should be skipped for bubble collapse based on task ID. */ private boolean shouldBypassCollapseForTask(int taskId, int expandedTaskId) { if (taskId == INVALID_TASK_ID) { ProtoLog.w(WM_SHELL_BUBBLES_NOISY, "BubblesTransitionObserver.onTransitionReady(): " + "task id is invalid so skip collapsing"); return true; } // If the opening task id is the same as the expanded bubble, skip collapsing // because it is our bubble that is opening. if (taskId == expandedTaskId) { ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "BubblesTransitionObserver.onTransitionReady(): " + "task %d is our bubble so skip collapsing", taskId); return true; } return false; } private void removeBubbleIfLaunchingToSplit(@NonNull TransitionInfo info) { if (mSplitScreenController.get().isEmpty()) return; SplitScreenController splitScreenController = mSplitScreenController.get().get(); Loading @@ -141,10 +166,8 @@ public class BubblesTransitionObserver implements Transitions.TransitionObserver 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, "TransitionObserver.onTransitionReady(): removing bubble for task launching " + "into split taskId=%d", taskInfo.taskId); 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 = BubbleUtilsKt.getExitBubbleTransaction(taskInfo.token, Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblesTransitionObserverTest.kt +74 −20 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ 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 import android.view.WindowManager.TRANSIT_CLOSE Loading @@ -27,6 +28,7 @@ import android.view.WindowManager.TRANSIT_OPEN import android.view.WindowManager.TRANSIT_TO_BACK 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 androidx.test.filters.SmallTest Loading @@ -40,14 +42,15 @@ 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.ArgumentMatchers.anyInt 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 Loading @@ -57,7 +60,8 @@ import org.mockito.kotlin.verifyNoInteractions /** * Unit tests of [BubblesTransitionObserver]. * * Build/Install/Run: atest WMShellUnitTests:BubblesTransitionObserverTest * Build/Install/Run: * atest WMShellUnitTests:BubblesTransitionObserverTest */ @SmallTest @RunWith(TestParameterInjector::class) Loading @@ -76,7 +80,7 @@ class BubblesTransitionObserverTest : ShellTestCase() { } private val taskViewTransitions = mock<TaskViewTransitions>() private val splitScreenController = mock<SplitScreenController> { on { isTaskRootOrStageRoot(anyInt()) } doReturn false on { isTaskRootOrStageRoot(any()) } doReturn false } private val transitionObserver = BubblesTransitionObserver( Loading @@ -96,11 +100,37 @@ class BubblesTransitionObserverTest : ShellTestCase() { } @Test fun testOnTransitionReady_openTaskOnAnotherDisplay_doesNotCollapseStack() { val taskInfo = createTaskInfo(taskId = 2).apply { displayId = 1 // not DEFAULT_DISPLAY fun testOnTransitionReady_noneBubbleActivityTransition_collapsesStack() { val info = createActivityTransition(TRANSIT_OPEN, taskId = 2) transitionObserver.onTransitionReady(mock(), info, mock(), mock()) verify(bubbleData).setExpanded(false) } val info = createTaskTransition(TRANSIT_OPEN, taskInfo) @Test fun testOnTransitionReady_expandedBubbleActivityTransition_doesNotCollapseStack() { val info = createActivityTransition(TRANSIT_OPEN, taskId = 1) transitionObserver.onTransitionReady(mock(), info, mock(), mock()) verify(bubbleData, never()).setExpanded(false) } @Test fun testOnTransitionReady_activityTransitionOnAnotherDisplay_doesNotCollapseStack() { val displayId = 1 // not DEFAULT_DISPLAY val info = createActivityTransition(TRANSIT_OPEN, taskId = 1, displayId) transitionObserver.onTransitionReady(mock(), info, mock(), mock()) verify(bubbleData, never()).setExpanded(false) } @Test fun testOnTransitionReady_openTaskOnAnotherDisplay_doesNotCollapseStack() { val displayId = 1 // not DEFAULT_DISPLAY val info = createTaskTransition(TRANSIT_OPEN, taskId = 2, displayId) transitionObserver.onTransitionReady(mock(), info, mock(), mock()) Loading Loading @@ -140,10 +170,8 @@ class BubblesTransitionObserverTest : ShellTestCase() { } @Test fun testOnTransitionReady_noTaskId_skip() { val info = createTaskTransition(TRANSIT_OPEN, taskId = INVALID_TASK_ID) // Invalid task id transitionObserver.onTransitionReady(mock(), info, mock(), mock()) fun testOnTransitionReady_noTaskId_skip(@TestParameter tc: InvalidTaskIdTestCase) { transitionObserver.onTransitionReady(mock(), tc.info, mock(), mock()) verify(bubbleData, never()).setExpanded(false) } Loading Loading @@ -267,17 +295,43 @@ class BubblesTransitionObserverTest : ShellTestCase() { get() = createTaskTransition(changeType, taskId) } // Invalid task id. enum class InvalidTaskIdTestCase( private val transitionCreator: (changeType: Int, taskId: Int) -> TransitionInfo, ) { ACTIVITY_TRANSITION(transitionCreator = ::createActivityTransition), TASK_TRANSITION(transitionCreator = ::createTaskTransition); val info: TransitionInfo get() = transitionCreator(TRANSIT_OPEN, INVALID_TASK_ID) } companion object { private fun createTaskTransition(@TransitionType changeType: Int, taskId: Int) = createTaskTransition(changeType, taskInfo = createTaskInfo(taskId)) private val COMPONENT = ComponentName("com.example.app", "com.example.app.MainActivity") private fun createTaskTransition( @TransitionType changeType: Int, taskId: Int, displayId: Int = DEFAULT_DISPLAY_ID, ) = createTaskTransition(changeType, taskInfo = createTaskInfo(taskId), displayId) private fun createTaskTransition( @TransitionType changeType: Int, taskInfo: ActivityManager.RunningTaskInfo?, ) = TransitionInfoBuilder(TRANSIT_OPEN).addChange(changeType, taskInfo).build() displayId: Int = DEFAULT_DISPLAY_ID, ) = TransitionInfoBuilder(TRANSIT_OPEN, displayId = displayId) .addChange(changeType, taskInfo) .build() private fun createActivityTransition( @TransitionType changeType: Int, taskId: Int, displayId: Int = DEFAULT_DISPLAY_ID, ) = TransitionInfoBuilder(TRANSIT_OPEN, displayId = displayId) .addChange(changeType, ActivityTransitionInfo(COMPONENT, taskId)) .build() private fun createTaskInfo(taskId: Int) = ActivityManager.RunningTaskInfo().apply { private fun createTaskInfo(taskId: Int) = ActivityManager.RunningTaskInfo().apply { this.taskId = taskId this.token = MockToken().token() this.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN Loading libs/WindowManager/Shell/tests/util/src/com/android/wm/shell/transition/TransitionInfoBuilder.kt +5 −3 Original line number Diff line number Diff line Loading @@ -33,11 +33,13 @@ import org.mockito.kotlin.mock * @param type the type of the transition. See [WindowManager.TransitionType]. * @param flags the flags for the transition. See [WindowManager.TransitionFlags]. * @param asNoOp if true, the root leash will not be added. * @param displayId the display ID for the root leash and transition changes. */ class TransitionInfoBuilder @JvmOverloads constructor( @WindowManager.TransitionType type: Int, @WindowManager.TransitionFlags flags: Int = 0, asNoOp: Boolean = false, private val displayId: Int = DEFAULT_DISPLAY_ID, ) { // The underlying TransitionInfo object being built. private val info: TransitionInfo = TransitionInfo(type, flags).apply { Loading @@ -46,7 +48,7 @@ class TransitionInfoBuilder @JvmOverloads constructor( } // Add a root leash by default, unless asNoOp is true. addRootLeash( DISPLAY_ID, displayId, createMockSurface(), /* leash */ 0, /* offsetLeft */ 0, /* offsetTop */ Loading Loading @@ -132,7 +134,7 @@ class TransitionInfoBuilder @JvmOverloads constructor( */ fun addChange(change: TransitionInfo.Change): TransitionInfoBuilder { // Set the display ID for the change. change.setDisplayId(DISPLAY_ID /* start */, DISPLAY_ID /* end */) change.setDisplayId(displayId /* start */, displayId /* end */) // Add the change to the internal TransitionInfo object. info.addChange(change) return this // Return this for fluent builder pattern. Loading @@ -149,7 +151,7 @@ class TransitionInfoBuilder @JvmOverloads constructor( companion object { // Default display ID for root leashes and changes. const val DISPLAY_ID = 0 const val DEFAULT_DISPLAY_ID = 0 // Create a mock SurfaceControl for testing. private fun createMockSurface() = mock<SurfaceControl> { Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesTransitionObserver.java +49 −26 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ 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; Loading Loading @@ -53,12 +54,13 @@ 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, TaskViewTransitions taskViewTransitions, @NonNull TaskViewTransitions taskViewTransitions, Lazy<Optional<SplitScreenController>> splitScreenController) { mBubbleController = controller; mBubbleData = bubbleData; Loading Loading @@ -100,37 +102,60 @@ public class BubblesTransitionObserver implements Transitions.TransitionObserver if (!TransitionUtil.isOpeningType(change.getMode())) { continue; } final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); // We only handle task transitions. if (taskInfo == null || taskInfo.taskId == INVALID_TASK_ID) { continue; } // If the opening task id is the same as the expanded bubble, skip collapsing // because it is our bubble that is opening. if (taskInfo.taskId == expandedTaskId) { // If the opening transition is on a different display, skip collapsing because // it does not visually overlap with the bubbles. if (change.getEndDisplayId() != bubbleViewDisplayId) { continue; } // If the opening task is on a different display, skip collapsing because the task // opening does not visually overlap with the bubbles. if (taskInfo.displayId != bubbleViewDisplayId) { final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); final ActivityTransitionInfo activityInfo = change.getActivityTransitionInfo(); if (taskInfo != null) { // Task transition. if (shouldBypassCollapseForTask(taskInfo.taskId, expandedTaskId)) { continue; } // If the opening task was launched by another bubble, skip collapsing the existing one // since BubbleTransitions will start a new bubble for it // If the opening task was launched by another bubble, skip collapsing the // existing one since BubbleTransitions will start a new bubble for it. if (BubbleAnythingFlagHelper.enableCreateAnyBubble() && mBubbleController.shouldBeAppBubble(taskInfo)) { ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "TransitionObserver.onTransitionReady(): " ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "BubblesTransitionObserver.onTransitionReady(): " + "skipping app bubble for taskId=%d", taskInfo.taskId); continue; } } else if (activityInfo != null) { // Activity transition. if (shouldBypassCollapseForTask(activityInfo.getTaskId(), expandedTaskId)) { continue; } } else { // Invalid transition. continue; } ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "TransitionObserver.onTransitionReady(): " + "collapsing bubble for taskId=%d", taskInfo.taskId); ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "BubblesTransitionObserver.onTransitionReady(): " + "collapse the expanded bubble for taskId=%d", expandedTaskId); mBubbleData.setExpanded(false); return; } } /** Checks if a task should be skipped for bubble collapse based on task ID. */ private boolean shouldBypassCollapseForTask(int taskId, int expandedTaskId) { if (taskId == INVALID_TASK_ID) { ProtoLog.w(WM_SHELL_BUBBLES_NOISY, "BubblesTransitionObserver.onTransitionReady(): " + "task id is invalid so skip collapsing"); return true; } // If the opening task id is the same as the expanded bubble, skip collapsing // because it is our bubble that is opening. if (taskId == expandedTaskId) { ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "BubblesTransitionObserver.onTransitionReady(): " + "task %d is our bubble so skip collapsing", taskId); return true; } return false; } private void removeBubbleIfLaunchingToSplit(@NonNull TransitionInfo info) { if (mSplitScreenController.get().isEmpty()) return; SplitScreenController splitScreenController = mSplitScreenController.get().get(); Loading @@ -141,10 +166,8 @@ public class BubblesTransitionObserver implements Transitions.TransitionObserver 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, "TransitionObserver.onTransitionReady(): removing bubble for task launching " + "into split taskId=%d", taskInfo.taskId); 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 = BubbleUtilsKt.getExitBubbleTransaction(taskInfo.token, Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblesTransitionObserverTest.kt +74 −20 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ 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 import android.view.WindowManager.TRANSIT_CLOSE Loading @@ -27,6 +28,7 @@ import android.view.WindowManager.TRANSIT_OPEN import android.view.WindowManager.TRANSIT_TO_BACK 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 androidx.test.filters.SmallTest Loading @@ -40,14 +42,15 @@ 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.ArgumentMatchers.anyInt 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 Loading @@ -57,7 +60,8 @@ import org.mockito.kotlin.verifyNoInteractions /** * Unit tests of [BubblesTransitionObserver]. * * Build/Install/Run: atest WMShellUnitTests:BubblesTransitionObserverTest * Build/Install/Run: * atest WMShellUnitTests:BubblesTransitionObserverTest */ @SmallTest @RunWith(TestParameterInjector::class) Loading @@ -76,7 +80,7 @@ class BubblesTransitionObserverTest : ShellTestCase() { } private val taskViewTransitions = mock<TaskViewTransitions>() private val splitScreenController = mock<SplitScreenController> { on { isTaskRootOrStageRoot(anyInt()) } doReturn false on { isTaskRootOrStageRoot(any()) } doReturn false } private val transitionObserver = BubblesTransitionObserver( Loading @@ -96,11 +100,37 @@ class BubblesTransitionObserverTest : ShellTestCase() { } @Test fun testOnTransitionReady_openTaskOnAnotherDisplay_doesNotCollapseStack() { val taskInfo = createTaskInfo(taskId = 2).apply { displayId = 1 // not DEFAULT_DISPLAY fun testOnTransitionReady_noneBubbleActivityTransition_collapsesStack() { val info = createActivityTransition(TRANSIT_OPEN, taskId = 2) transitionObserver.onTransitionReady(mock(), info, mock(), mock()) verify(bubbleData).setExpanded(false) } val info = createTaskTransition(TRANSIT_OPEN, taskInfo) @Test fun testOnTransitionReady_expandedBubbleActivityTransition_doesNotCollapseStack() { val info = createActivityTransition(TRANSIT_OPEN, taskId = 1) transitionObserver.onTransitionReady(mock(), info, mock(), mock()) verify(bubbleData, never()).setExpanded(false) } @Test fun testOnTransitionReady_activityTransitionOnAnotherDisplay_doesNotCollapseStack() { val displayId = 1 // not DEFAULT_DISPLAY val info = createActivityTransition(TRANSIT_OPEN, taskId = 1, displayId) transitionObserver.onTransitionReady(mock(), info, mock(), mock()) verify(bubbleData, never()).setExpanded(false) } @Test fun testOnTransitionReady_openTaskOnAnotherDisplay_doesNotCollapseStack() { val displayId = 1 // not DEFAULT_DISPLAY val info = createTaskTransition(TRANSIT_OPEN, taskId = 2, displayId) transitionObserver.onTransitionReady(mock(), info, mock(), mock()) Loading Loading @@ -140,10 +170,8 @@ class BubblesTransitionObserverTest : ShellTestCase() { } @Test fun testOnTransitionReady_noTaskId_skip() { val info = createTaskTransition(TRANSIT_OPEN, taskId = INVALID_TASK_ID) // Invalid task id transitionObserver.onTransitionReady(mock(), info, mock(), mock()) fun testOnTransitionReady_noTaskId_skip(@TestParameter tc: InvalidTaskIdTestCase) { transitionObserver.onTransitionReady(mock(), tc.info, mock(), mock()) verify(bubbleData, never()).setExpanded(false) } Loading Loading @@ -267,17 +295,43 @@ class BubblesTransitionObserverTest : ShellTestCase() { get() = createTaskTransition(changeType, taskId) } // Invalid task id. enum class InvalidTaskIdTestCase( private val transitionCreator: (changeType: Int, taskId: Int) -> TransitionInfo, ) { ACTIVITY_TRANSITION(transitionCreator = ::createActivityTransition), TASK_TRANSITION(transitionCreator = ::createTaskTransition); val info: TransitionInfo get() = transitionCreator(TRANSIT_OPEN, INVALID_TASK_ID) } companion object { private fun createTaskTransition(@TransitionType changeType: Int, taskId: Int) = createTaskTransition(changeType, taskInfo = createTaskInfo(taskId)) private val COMPONENT = ComponentName("com.example.app", "com.example.app.MainActivity") private fun createTaskTransition( @TransitionType changeType: Int, taskId: Int, displayId: Int = DEFAULT_DISPLAY_ID, ) = createTaskTransition(changeType, taskInfo = createTaskInfo(taskId), displayId) private fun createTaskTransition( @TransitionType changeType: Int, taskInfo: ActivityManager.RunningTaskInfo?, ) = TransitionInfoBuilder(TRANSIT_OPEN).addChange(changeType, taskInfo).build() displayId: Int = DEFAULT_DISPLAY_ID, ) = TransitionInfoBuilder(TRANSIT_OPEN, displayId = displayId) .addChange(changeType, taskInfo) .build() private fun createActivityTransition( @TransitionType changeType: Int, taskId: Int, displayId: Int = DEFAULT_DISPLAY_ID, ) = TransitionInfoBuilder(TRANSIT_OPEN, displayId = displayId) .addChange(changeType, ActivityTransitionInfo(COMPONENT, taskId)) .build() private fun createTaskInfo(taskId: Int) = ActivityManager.RunningTaskInfo().apply { private fun createTaskInfo(taskId: Int) = ActivityManager.RunningTaskInfo().apply { this.taskId = taskId this.token = MockToken().token() this.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN Loading
libs/WindowManager/Shell/tests/util/src/com/android/wm/shell/transition/TransitionInfoBuilder.kt +5 −3 Original line number Diff line number Diff line Loading @@ -33,11 +33,13 @@ import org.mockito.kotlin.mock * @param type the type of the transition. See [WindowManager.TransitionType]. * @param flags the flags for the transition. See [WindowManager.TransitionFlags]. * @param asNoOp if true, the root leash will not be added. * @param displayId the display ID for the root leash and transition changes. */ class TransitionInfoBuilder @JvmOverloads constructor( @WindowManager.TransitionType type: Int, @WindowManager.TransitionFlags flags: Int = 0, asNoOp: Boolean = false, private val displayId: Int = DEFAULT_DISPLAY_ID, ) { // The underlying TransitionInfo object being built. private val info: TransitionInfo = TransitionInfo(type, flags).apply { Loading @@ -46,7 +48,7 @@ class TransitionInfoBuilder @JvmOverloads constructor( } // Add a root leash by default, unless asNoOp is true. addRootLeash( DISPLAY_ID, displayId, createMockSurface(), /* leash */ 0, /* offsetLeft */ 0, /* offsetTop */ Loading Loading @@ -132,7 +134,7 @@ class TransitionInfoBuilder @JvmOverloads constructor( */ fun addChange(change: TransitionInfo.Change): TransitionInfoBuilder { // Set the display ID for the change. change.setDisplayId(DISPLAY_ID /* start */, DISPLAY_ID /* end */) change.setDisplayId(displayId /* start */, displayId /* end */) // Add the change to the internal TransitionInfo object. info.addChange(change) return this // Return this for fluent builder pattern. Loading @@ -149,7 +151,7 @@ class TransitionInfoBuilder @JvmOverloads constructor( companion object { // Default display ID for root leashes and changes. const val DISPLAY_ID = 0 const val DEFAULT_DISPLAY_ID = 0 // Create a mock SurfaceControl for testing. private fun createMockSurface() = mock<SurfaceControl> { Loading