Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +5 −6 Original line number Diff line number Diff line Loading @@ -3370,16 +3370,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } } /** @return whether the transition-request implies entering bubbles from split. */ public boolean requestImpliesSplitToBubble(TransitionRequestInfo request) { final TaskInfo triggerTask = request.getTriggerTask(); /** @return whether the opening task implies entering bubbles from split. */ public boolean requestImpliesSplitToBubble(TaskInfo openingTask) { if (!isSplitActive() || triggerTask == null || triggerTask.displayId != mDisplayId) { || openingTask == null || openingTask.displayId != mDisplayId) { return false; } int stageForTask = getStageOfTask(triggerTask.taskId); int stageForTask = getStageOfTask(openingTask.taskId); if (stageForTask == STAGE_TYPE_UNDEFINED) { return false; } Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +32 −2 Original line number Diff line number Diff line Loading @@ -331,7 +331,7 @@ public class DefaultMixedHandler implements MixedTransitionHandler, if (requestHasBubbleEnter(request)) { consumeRemoteTransitionIfNecessary(transition, request.getRemoteTransition()); if (mSplitHandler.requestImpliesSplitToBubble(request)) { if (mSplitHandler.requestImpliesSplitToBubble(request.getTriggerTask())) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a Bubble-enter request from a split task"); mBubbleTransitions.storePendingEnterTransition(transition, request); Loading Loading @@ -361,7 +361,7 @@ public class DefaultMixedHandler implements MixedTransitionHandler, } else if (requestHasBubbleEnterFromAppBubbleOrExistingBubble(request)) { consumeRemoteTransitionIfNecessary(transition, request.getRemoteTransition()); if (mSplitHandler.requestImpliesSplitToBubble(request)) { if (mSplitHandler.requestImpliesSplitToBubble(request.getTriggerTask())) { // TODO: Handle from split } else { // Note: This will currently "intercept" launches even while the bubble is collapsed Loading Loading @@ -581,6 +581,24 @@ public class DefaultMixedHandler implements MixedTransitionHandler, break; } // If there was no requested transition but the transition includes an opening bubble task // then handle it here now TransitionInfo.Change bubbleChange = transitionHasBubbleEnterFromAppBubbleOrExistingBubble(info); if (mixed == null && bubbleChange != null) { if (mSplitHandler.requestImpliesSplitToBubble(bubbleChange.getTaskInfo())) { // TODO: Handle from split } else { // Add a mixed transition ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a Bubble-enter " + "transition from an app bubble or for an existing bubble"); mixed = createDefaultMixedTransition( MixedTransition.TYPE_LAUNCH_OR_CONVERT_TO_BUBBLE_FROM_EXISTING_BUBBLE, transition); mActiveTransitions.add(mixed); } } // Offer Keyguard the opportunity to take over lock transitions - ideally we could know by // the time of handleRequest, but we need more information than is available at that time. if (KeyguardTransitionHandler.handles(info)) { Loading Loading @@ -836,6 +854,18 @@ public class DefaultMixedHandler implements MixedTransitionHandler, && mBubbleTransitions.shouldBeAppBubble(request.getTriggerTask()); } /** * Returns the associated change for the bubbled task in the given started transition if it is * from an app bubble or for an existing bubble and should be handled by the bubbles transition */ public TransitionInfo.Change transitionHasBubbleEnterFromAppBubbleOrExistingBubble( @NonNull TransitionInfo info) { if (!BubbleAnythingFlagHelper.enableCreateAnyBubble()) { return null; } return DefaultMixedTransition.getChangeForBubblingTask(info, mBubbleTransitions); } /** * Notifies the remote transition that it will not be played and is consumed by another * transition (and it can clean up accordingly). Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedTransition.java +1 −1 Original line number Diff line number Diff line Loading @@ -453,7 +453,7 @@ class DefaultMixedTransition extends DefaultMixedHandler.MixedTransition { return true; } private static @Nullable TransitionInfo.Change getChangeForBubblingTask( static @Nullable TransitionInfo.Change getChangeForBubblingTask( @NonNull TransitionInfo info, BubbleTransitions bubbleTransitions) { for (int i = 0; i < info.getChanges().size(); i++) { final TransitionInfo.Change chg = info.getChanges().get(i); Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/DefaultMixedHandlerTest.kt +44 −0 Original line number Diff line number Diff line Loading @@ -17,12 +17,16 @@ package com.android.wm.shell.transition import android.app.ActivityManager.RunningTaskInfo import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD import android.os.Binder import android.platform.test.annotations.EnableFlags import android.view.SurfaceControl import android.view.WindowManager.TRANSIT_OPEN import android.window.IRemoteTransition import android.window.RemoteTransition import android.window.TransitionInfo import android.window.TransitionRequestInfo 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.ShellTestCase Loading @@ -45,6 +49,7 @@ import org.mockito.kotlin.any import org.mockito.kotlin.doReturn import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.stub import org.mockito.kotlin.verify Loading Loading @@ -218,6 +223,44 @@ class DefaultMixedHandlerTest : ShellTestCase() { verify(remoteTransition).onTransitionConsumed(any(), eq(false)) } @Test @EnableFlags(FLAG_ENABLE_CREATE_ANY_BUBBLE) fun test_startAnimation_NoBubbleEnterFromAppBubble() { val info = TransitionInfo(TRANSIT_OPEN, 0) bubbleTransitions.stub { on { isShowingAsBubbleBar } doReturn true on { shouldBeAppBubble(any()) } doReturn true } mixedHandler.startAnimation(Binder(), info, mock<SurfaceControl.Transaction>(), mock<SurfaceControl.Transaction>(), mock<Transitions.TransitionFinishCallback>()) verify(bubbleTransitions, never()).startBubbleToBubbleLaunchOrExistingBubbleConvert( any(), any(), any()); } @Test @EnableFlags(FLAG_ENABLE_CREATE_ANY_BUBBLE) fun test_startAnimation_bubbleEnterFromAppBubble() { val change = TransitionInfo.Change(mock<WindowContainerToken>(), mock<SurfaceControl>()) change.mode = TRANSIT_OPEN change.taskInfo = createRunningTask() val info = TransitionInfo(TRANSIT_OPEN, 0) info.addChange(change) bubbleTransitions.stub { on { isShowingAsBubbleBar } doReturn true on { shouldBeAppBubble(any()) } doReturn true } mixedHandler.startAnimation(Binder(), info, mock<SurfaceControl.Transaction>(), mock<SurfaceControl.Transaction>(), mock<Transitions.TransitionFinishCallback>()) verify(bubbleTransitions).startBubbleToBubbleLaunchOrExistingBubbleConvert( any(), any(), any()); } private fun createTransitionRequestInfo( runningTask: RunningTaskInfo? = null, remote: RemoteTransition? = null, Loading @@ -228,6 +271,7 @@ class DefaultMixedHandlerTest : ShellTestCase() { private fun createRunningTask(taskId: Int = 0): RunningTaskInfo { return RunningTaskInfo().apply { this.taskId = taskId this.configuration.windowConfiguration.activityType = ACTIVITY_TYPE_STANDARD } } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +5 −6 Original line number Diff line number Diff line Loading @@ -3370,16 +3370,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } } /** @return whether the transition-request implies entering bubbles from split. */ public boolean requestImpliesSplitToBubble(TransitionRequestInfo request) { final TaskInfo triggerTask = request.getTriggerTask(); /** @return whether the opening task implies entering bubbles from split. */ public boolean requestImpliesSplitToBubble(TaskInfo openingTask) { if (!isSplitActive() || triggerTask == null || triggerTask.displayId != mDisplayId) { || openingTask == null || openingTask.displayId != mDisplayId) { return false; } int stageForTask = getStageOfTask(triggerTask.taskId); int stageForTask = getStageOfTask(openingTask.taskId); if (stageForTask == STAGE_TYPE_UNDEFINED) { return false; } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +32 −2 Original line number Diff line number Diff line Loading @@ -331,7 +331,7 @@ public class DefaultMixedHandler implements MixedTransitionHandler, if (requestHasBubbleEnter(request)) { consumeRemoteTransitionIfNecessary(transition, request.getRemoteTransition()); if (mSplitHandler.requestImpliesSplitToBubble(request)) { if (mSplitHandler.requestImpliesSplitToBubble(request.getTriggerTask())) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a Bubble-enter request from a split task"); mBubbleTransitions.storePendingEnterTransition(transition, request); Loading Loading @@ -361,7 +361,7 @@ public class DefaultMixedHandler implements MixedTransitionHandler, } else if (requestHasBubbleEnterFromAppBubbleOrExistingBubble(request)) { consumeRemoteTransitionIfNecessary(transition, request.getRemoteTransition()); if (mSplitHandler.requestImpliesSplitToBubble(request)) { if (mSplitHandler.requestImpliesSplitToBubble(request.getTriggerTask())) { // TODO: Handle from split } else { // Note: This will currently "intercept" launches even while the bubble is collapsed Loading Loading @@ -581,6 +581,24 @@ public class DefaultMixedHandler implements MixedTransitionHandler, break; } // If there was no requested transition but the transition includes an opening bubble task // then handle it here now TransitionInfo.Change bubbleChange = transitionHasBubbleEnterFromAppBubbleOrExistingBubble(info); if (mixed == null && bubbleChange != null) { if (mSplitHandler.requestImpliesSplitToBubble(bubbleChange.getTaskInfo())) { // TODO: Handle from split } else { // Add a mixed transition ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a Bubble-enter " + "transition from an app bubble or for an existing bubble"); mixed = createDefaultMixedTransition( MixedTransition.TYPE_LAUNCH_OR_CONVERT_TO_BUBBLE_FROM_EXISTING_BUBBLE, transition); mActiveTransitions.add(mixed); } } // Offer Keyguard the opportunity to take over lock transitions - ideally we could know by // the time of handleRequest, but we need more information than is available at that time. if (KeyguardTransitionHandler.handles(info)) { Loading Loading @@ -836,6 +854,18 @@ public class DefaultMixedHandler implements MixedTransitionHandler, && mBubbleTransitions.shouldBeAppBubble(request.getTriggerTask()); } /** * Returns the associated change for the bubbled task in the given started transition if it is * from an app bubble or for an existing bubble and should be handled by the bubbles transition */ public TransitionInfo.Change transitionHasBubbleEnterFromAppBubbleOrExistingBubble( @NonNull TransitionInfo info) { if (!BubbleAnythingFlagHelper.enableCreateAnyBubble()) { return null; } return DefaultMixedTransition.getChangeForBubblingTask(info, mBubbleTransitions); } /** * Notifies the remote transition that it will not be played and is consumed by another * transition (and it can clean up accordingly). Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedTransition.java +1 −1 Original line number Diff line number Diff line Loading @@ -453,7 +453,7 @@ class DefaultMixedTransition extends DefaultMixedHandler.MixedTransition { return true; } private static @Nullable TransitionInfo.Change getChangeForBubblingTask( static @Nullable TransitionInfo.Change getChangeForBubblingTask( @NonNull TransitionInfo info, BubbleTransitions bubbleTransitions) { for (int i = 0; i < info.getChanges().size(); i++) { final TransitionInfo.Change chg = info.getChanges().get(i); Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/DefaultMixedHandlerTest.kt +44 −0 Original line number Diff line number Diff line Loading @@ -17,12 +17,16 @@ package com.android.wm.shell.transition import android.app.ActivityManager.RunningTaskInfo import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD import android.os.Binder import android.platform.test.annotations.EnableFlags import android.view.SurfaceControl import android.view.WindowManager.TRANSIT_OPEN import android.window.IRemoteTransition import android.window.RemoteTransition import android.window.TransitionInfo import android.window.TransitionRequestInfo 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.ShellTestCase Loading @@ -45,6 +49,7 @@ import org.mockito.kotlin.any import org.mockito.kotlin.doReturn import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.stub import org.mockito.kotlin.verify Loading Loading @@ -218,6 +223,44 @@ class DefaultMixedHandlerTest : ShellTestCase() { verify(remoteTransition).onTransitionConsumed(any(), eq(false)) } @Test @EnableFlags(FLAG_ENABLE_CREATE_ANY_BUBBLE) fun test_startAnimation_NoBubbleEnterFromAppBubble() { val info = TransitionInfo(TRANSIT_OPEN, 0) bubbleTransitions.stub { on { isShowingAsBubbleBar } doReturn true on { shouldBeAppBubble(any()) } doReturn true } mixedHandler.startAnimation(Binder(), info, mock<SurfaceControl.Transaction>(), mock<SurfaceControl.Transaction>(), mock<Transitions.TransitionFinishCallback>()) verify(bubbleTransitions, never()).startBubbleToBubbleLaunchOrExistingBubbleConvert( any(), any(), any()); } @Test @EnableFlags(FLAG_ENABLE_CREATE_ANY_BUBBLE) fun test_startAnimation_bubbleEnterFromAppBubble() { val change = TransitionInfo.Change(mock<WindowContainerToken>(), mock<SurfaceControl>()) change.mode = TRANSIT_OPEN change.taskInfo = createRunningTask() val info = TransitionInfo(TRANSIT_OPEN, 0) info.addChange(change) bubbleTransitions.stub { on { isShowingAsBubbleBar } doReturn true on { shouldBeAppBubble(any()) } doReturn true } mixedHandler.startAnimation(Binder(), info, mock<SurfaceControl.Transaction>(), mock<SurfaceControl.Transaction>(), mock<Transitions.TransitionFinishCallback>()) verify(bubbleTransitions).startBubbleToBubbleLaunchOrExistingBubbleConvert( any(), any(), any()); } private fun createTransitionRequestInfo( runningTask: RunningTaskInfo? = null, remote: RemoteTransition? = null, Loading @@ -228,6 +271,7 @@ class DefaultMixedHandlerTest : ShellTestCase() { private fun createRunningTask(taskId: Int = 0): RunningTaskInfo { return RunningTaskInfo().apply { this.taskId = taskId this.configuration.windowConfiguration.activityType = ACTIVITY_TYPE_STANDARD } } }