Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java +14 −2 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ import com.android.wm.shell.bubbles.appinfo.BubbleAppInfoProvider; import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView; import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; import com.android.wm.shell.common.HomeIntentProvider; import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper; import com.android.wm.shell.shared.bubbles.BubbleBarLocation; import com.android.wm.shell.taskview.TaskView; import com.android.wm.shell.taskview.TaskViewRepository; Loading Loading @@ -687,13 +688,14 @@ public class BubbleTransitions { mPlayConvertTaskAnimation = false; for (int i = info.getChanges().size() - 1; i >= 0; i--) { final TransitionInfo.Change chg = info.getChanges().get(i); final boolean isLaunchedTask = (chg.getTaskInfo() != null) final ActivityManager.RunningTaskInfo taskInfo = chg.getTaskInfo(); final boolean isLaunchedTask = (taskInfo != null) && (chg.getMode() == TRANSIT_CHANGE || isOpeningMode(chg.getMode())); if (isLaunchedTask) { mStartBounds.set(chg.getStartAbsBounds()); // Converting a task into taskview, so treat as "new" mFinishWct = new WindowContainerTransaction(); mTaskInfo = chg.getTaskInfo(); mTaskInfo = taskInfo; mFinishT = finishTransaction; mTaskLeash = chg.getLeash(); mSnapshot = chg.getSnapshot(); Loading @@ -701,6 +703,16 @@ public class BubbleTransitions { // is no snapshot, so fallback to the open transition for now mPlayConvertTaskAnimation = false; found = true; } else if (BubbleAnythingFlagHelper.enableRootTaskForBubble() && taskInfo != null && mBubbleController.shouldBeAppBubble(taskInfo)) { // Starting a new bubble from an existing expanded bubble may immediately hide // the currently expanded bubble in the same transition. Ensure the surfaces // stays in the TaskView vs. under the transition root. final Bubble b = mBubbleData.getBubbleInStackWithTaskId(taskInfo.taskId); if (b != null) { startTransaction.reparent(chg.getLeash(), b.getTaskView().getSurfaceControl()); } } else { // In core-initiated launches, the transition is of an OPEN type, and we need to // manually show the surfaces behind the newly bubbled task Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTransitionsTest.java +64 −0 Original line number Diff line number Diff line Loading @@ -23,7 +23,9 @@ import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static com.android.window.flags.Flags.FLAG_ROOT_TASK_FOR_BUBBLE; import static com.android.wm.shell.Flags.FLAG_ENABLE_BUBBLE_BAR; import static com.android.wm.shell.Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE; import static com.android.wm.shell.bubbles.util.BubbleTestUtils.verifyEnterBubbleTransaction; import static com.android.wm.shell.transition.Transitions.TRANSIT_BUBBLE_CONVERT_FLOATING_TO_BAR; import static com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE; Loading Loading @@ -1239,4 +1241,66 @@ public class BubbleTransitionsTest extends ShellTestCase { assertThat(mBubbleTransitions.getClosingBubbleTask(info)).isNull(); } @Test @EnableFlags({FLAG_ENABLE_CREATE_ANY_BUBBLE, FLAG_ROOT_TASK_FOR_BUBBLE}) public void testStartNewBubbleTaskFromExistingBubble() { // Setup a Bubble that's currently expanded final Bubble expandedBubble = mock(Bubble.class); setUpBubbleBarExpandedView(expandedBubble); final TaskView expandedTaskView = setUpBubbleTaskView(expandedBubble); final SurfaceControl expandedTaskViewLeash = expandedTaskView.getSurfaceControl(); final ActivityManager.RunningTaskInfo expandedTaskInfo = setupAppBubble( expandedBubble, expandedTaskView, mTaskViewTaskController); expandedTaskInfo.taskId = 10; // Setup a new open Bubble final TaskView openingTaskView = setUpBubbleTaskView(mBubble); final ActivityManager.RunningTaskInfo openingTaskInfo = setupAppBubble( mBubble, openingTaskView, mTaskViewTaskController); // Setup Transition final IBinder transitionToken = mock(IBinder.class); final Consumer<Transitions.TransitionHandler> onInflatedCallback = mock(Consumer.class); final SurfaceControl openingTaskLeash = new SurfaceControl.Builder().setName("openingTaskLeash").build(); final TransitionInfo.Change openingChg = new TransitionInfo.Change(openingTaskInfo.token, openingTaskLeash); openingChg.setTaskInfo(openingTaskInfo); openingChg.setMode(TRANSIT_OPEN); final SurfaceControl expandedTaskLeash = new SurfaceControl.Builder().setName("expandedTaskLeash").build(); final TransitionInfo.Change expandedChg = new TransitionInfo.Change(expandedTaskInfo.token, expandedTaskLeash); expandedChg.setTaskInfo(expandedTaskInfo); expandedChg.setMode(TRANSIT_TO_BACK); doReturn(expandedBubble).when(mBubbleData).getBubbleInStackWithTaskId( expandedTaskInfo.taskId); final TransitionInfo info = new TransitionInfo(TRANSIT_OPEN, 0); info.addChange(openingChg); info.addChange(expandedChg); info.addRoot(new TransitionInfo.Root(openingTaskInfo.displayId, openingTaskLeash, 0, 0)); final SurfaceControl.Transaction startT = spy(new SurfaceControl.Transaction()); final SurfaceControl.Transaction finishT = spy(new SurfaceControl.Transaction()); doNothing().when(startT).apply(); doNothing().when(finishT).apply(); final Transitions.TransitionFinishCallback finishCb = mock(Transitions.TransitionFinishCallback.class); final BubbleTransitions.LaunchNewTaskBubbleForExistingTransition bt = (BubbleTransitions.LaunchNewTaskBubbleForExistingTransition) mBubbleTransitions .startLaunchNewTaskBubbleForExistingTransition(mBubble, mExpandedViewManager, mTaskViewFactory, mBubblePositioner, mStackView, mLayerView, mIconFactory, false /* inflateSync */, transitionToken, onInflatedCallback); verify(mBubble).setPreparingTransition(bt); bt.onInflated(mBubble); // Start playing the transition bt.startAnimation(transitionToken, info, startT, finishT, finishCb); // Verify that the to-back leash is in TaskView verify(startT).reparent(expandedTaskLeash, expandedTaskViewLeash); verify(startT).apply(); } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java +14 −2 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ import com.android.wm.shell.bubbles.appinfo.BubbleAppInfoProvider; import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView; import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; import com.android.wm.shell.common.HomeIntentProvider; import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper; import com.android.wm.shell.shared.bubbles.BubbleBarLocation; import com.android.wm.shell.taskview.TaskView; import com.android.wm.shell.taskview.TaskViewRepository; Loading Loading @@ -687,13 +688,14 @@ public class BubbleTransitions { mPlayConvertTaskAnimation = false; for (int i = info.getChanges().size() - 1; i >= 0; i--) { final TransitionInfo.Change chg = info.getChanges().get(i); final boolean isLaunchedTask = (chg.getTaskInfo() != null) final ActivityManager.RunningTaskInfo taskInfo = chg.getTaskInfo(); final boolean isLaunchedTask = (taskInfo != null) && (chg.getMode() == TRANSIT_CHANGE || isOpeningMode(chg.getMode())); if (isLaunchedTask) { mStartBounds.set(chg.getStartAbsBounds()); // Converting a task into taskview, so treat as "new" mFinishWct = new WindowContainerTransaction(); mTaskInfo = chg.getTaskInfo(); mTaskInfo = taskInfo; mFinishT = finishTransaction; mTaskLeash = chg.getLeash(); mSnapshot = chg.getSnapshot(); Loading @@ -701,6 +703,16 @@ public class BubbleTransitions { // is no snapshot, so fallback to the open transition for now mPlayConvertTaskAnimation = false; found = true; } else if (BubbleAnythingFlagHelper.enableRootTaskForBubble() && taskInfo != null && mBubbleController.shouldBeAppBubble(taskInfo)) { // Starting a new bubble from an existing expanded bubble may immediately hide // the currently expanded bubble in the same transition. Ensure the surfaces // stays in the TaskView vs. under the transition root. final Bubble b = mBubbleData.getBubbleInStackWithTaskId(taskInfo.taskId); if (b != null) { startTransaction.reparent(chg.getLeash(), b.getTaskView().getSurfaceControl()); } } else { // In core-initiated launches, the transition is of an OPEN type, and we need to // manually show the surfaces behind the newly bubbled task Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTransitionsTest.java +64 −0 Original line number Diff line number Diff line Loading @@ -23,7 +23,9 @@ import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static com.android.window.flags.Flags.FLAG_ROOT_TASK_FOR_BUBBLE; import static com.android.wm.shell.Flags.FLAG_ENABLE_BUBBLE_BAR; import static com.android.wm.shell.Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE; import static com.android.wm.shell.bubbles.util.BubbleTestUtils.verifyEnterBubbleTransaction; import static com.android.wm.shell.transition.Transitions.TRANSIT_BUBBLE_CONVERT_FLOATING_TO_BAR; import static com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE; Loading Loading @@ -1239,4 +1241,66 @@ public class BubbleTransitionsTest extends ShellTestCase { assertThat(mBubbleTransitions.getClosingBubbleTask(info)).isNull(); } @Test @EnableFlags({FLAG_ENABLE_CREATE_ANY_BUBBLE, FLAG_ROOT_TASK_FOR_BUBBLE}) public void testStartNewBubbleTaskFromExistingBubble() { // Setup a Bubble that's currently expanded final Bubble expandedBubble = mock(Bubble.class); setUpBubbleBarExpandedView(expandedBubble); final TaskView expandedTaskView = setUpBubbleTaskView(expandedBubble); final SurfaceControl expandedTaskViewLeash = expandedTaskView.getSurfaceControl(); final ActivityManager.RunningTaskInfo expandedTaskInfo = setupAppBubble( expandedBubble, expandedTaskView, mTaskViewTaskController); expandedTaskInfo.taskId = 10; // Setup a new open Bubble final TaskView openingTaskView = setUpBubbleTaskView(mBubble); final ActivityManager.RunningTaskInfo openingTaskInfo = setupAppBubble( mBubble, openingTaskView, mTaskViewTaskController); // Setup Transition final IBinder transitionToken = mock(IBinder.class); final Consumer<Transitions.TransitionHandler> onInflatedCallback = mock(Consumer.class); final SurfaceControl openingTaskLeash = new SurfaceControl.Builder().setName("openingTaskLeash").build(); final TransitionInfo.Change openingChg = new TransitionInfo.Change(openingTaskInfo.token, openingTaskLeash); openingChg.setTaskInfo(openingTaskInfo); openingChg.setMode(TRANSIT_OPEN); final SurfaceControl expandedTaskLeash = new SurfaceControl.Builder().setName("expandedTaskLeash").build(); final TransitionInfo.Change expandedChg = new TransitionInfo.Change(expandedTaskInfo.token, expandedTaskLeash); expandedChg.setTaskInfo(expandedTaskInfo); expandedChg.setMode(TRANSIT_TO_BACK); doReturn(expandedBubble).when(mBubbleData).getBubbleInStackWithTaskId( expandedTaskInfo.taskId); final TransitionInfo info = new TransitionInfo(TRANSIT_OPEN, 0); info.addChange(openingChg); info.addChange(expandedChg); info.addRoot(new TransitionInfo.Root(openingTaskInfo.displayId, openingTaskLeash, 0, 0)); final SurfaceControl.Transaction startT = spy(new SurfaceControl.Transaction()); final SurfaceControl.Transaction finishT = spy(new SurfaceControl.Transaction()); doNothing().when(startT).apply(); doNothing().when(finishT).apply(); final Transitions.TransitionFinishCallback finishCb = mock(Transitions.TransitionFinishCallback.class); final BubbleTransitions.LaunchNewTaskBubbleForExistingTransition bt = (BubbleTransitions.LaunchNewTaskBubbleForExistingTransition) mBubbleTransitions .startLaunchNewTaskBubbleForExistingTransition(mBubble, mExpandedViewManager, mTaskViewFactory, mBubblePositioner, mStackView, mLayerView, mIconFactory, false /* inflateSync */, transitionToken, onInflatedCallback); verify(mBubble).setPreparingTransition(bt); bt.onInflated(mBubble); // Start playing the transition bt.startAnimation(transitionToken, info, startT, finishT, finishCb); // Verify that the to-back leash is in TaskView verify(startT).reparent(expandedTaskLeash, expandedTaskViewLeash); verify(startT).apply(); } }