Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +2 −1 Original line number Diff line number Diff line Loading @@ -2644,7 +2644,8 @@ public class BubbleController implements ConfigurationChangeListener, } private void moveBubbleToFullscreen(String key) { // TODO b/388858013: convert the bubble to full screen Bubble b = mBubbleData.getBubbleInStackWithKey(key); mBubbleTransitions.startDraggedBubbleIconToFullscreen(b); } private boolean isDeviceLocked() { Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java +116 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,11 @@ public class BubbleTransitions { return convert; } /** Starts a transition that converts a dragged bubble icon to a full screen task. */ public BubbleTransition startDraggedBubbleIconToFullscreen(Bubble bubble) { return new DraggedBubbleIconToFullscreen(bubble); } /** * Plucks the task-surface out of an ancestor view while making the view invisible. This helper * attempts to do this seamlessly (ie. view becomes invisible in sync with task reparent). Loading Loading @@ -645,4 +650,115 @@ public class BubbleTransitions { t.apply(); } } /** * A transition that converts a dragged bubble icon to a full screen window. * * <p>This transition assumes that the bubble is invisible so it is simply sent to front. */ class DraggedBubbleIconToFullscreen implements Transitions.TransitionHandler, BubbleTransition { IBinder mTransition; final Bubble mBubble; DraggedBubbleIconToFullscreen(Bubble bubble) { mBubble = bubble; bubble.setPreparingTransition(this); WindowContainerToken token = bubble.getTaskView().getTaskInfo().getToken(); WindowContainerTransaction wct = new WindowContainerTransaction(); wct.setAlwaysOnTop(token, false); wct.setWindowingMode(token, WINDOWING_MODE_UNDEFINED); wct.reorder(token, /* onTop= */ true); wct.setHidden(token, false); mTaskOrganizer.setInterceptBackPressedOnTaskRoot(token, false); mTaskViewTransitions.enqueueExternal(bubble.getTaskView().getController(), () -> { mTransition = mTransitions.startTransition(TRANSIT_TO_FRONT, wct, this); return mTransition; }); } @Override public void skip() { mBubble.setPreparingTransition(null); } @Override public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { if (mTransition != transition) { return false; } final TaskViewTaskController taskViewTaskController = mBubble.getTaskView().getController(); if (taskViewTaskController == null) { mTaskViewTransitions.onExternalDone(transition); finishCallback.onTransitionFinished(null); return true; } TransitionInfo.Change change = findTransitionChange(info); if (change == null) { Slog.w(TAG, "Expected a TaskView transition to front but didn't find " + "one, cleaning up the task view"); taskViewTaskController.setTaskNotFound(); mTaskViewTransitions.onExternalDone(transition); finishCallback.onTransitionFinished(null); return true; } mRepository.remove(taskViewTaskController); startTransaction.apply(); finishCallback.onTransitionFinished(null); taskViewTaskController.notifyTaskRemovalStarted(mBubble.getTaskView().getTaskInfo()); mTaskViewTransitions.onExternalDone(transition); return true; } private TransitionInfo.Change findTransitionChange(TransitionInfo info) { TransitionInfo.Change result = null; WindowContainerToken token = mBubble.getTaskView().getTaskInfo().getToken(); for (int i = 0; i < info.getChanges().size(); ++i) { final TransitionInfo.Change change = info.getChanges().get(i); if (change.getTaskInfo() == null) { continue; } if (change.getMode() != TRANSIT_TO_FRONT) { continue; } if (!token.equals(change.getTaskInfo().token)) { continue; } result = change; break; } return result; } @Override public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull IBinder mergeTarget, @NonNull Transitions.TransitionFinishCallback finishCallback) { } @Override public WindowContainerTransaction handleRequest(@NonNull IBinder transition, @NonNull TransitionRequestInfo request) { return null; } @Override public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted, @Nullable SurfaceControl.Transaction finishTransaction) { if (!aborted) { return; } mTransition = null; mTaskViewTransitions.onExternalDone(transition); } } } libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTransitionsTest.java +26 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.wm.shell.bubbles; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE; Loading Loading @@ -52,6 +53,7 @@ import com.android.launcher3.icons.BubbleIconFactory; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestSyncExecutor; import com.android.wm.shell.bubbles.BubbleTransitions.DraggedBubbleIconToFullscreen; import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView; import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; import com.android.wm.shell.common.ShellExecutor; Loading Loading @@ -136,6 +138,7 @@ public class BubbleTransitionsTest extends ShellTestCase { when(tvtc.getTaskInfo()).thenReturn(taskInfo); when(tv.getController()).thenReturn(tvtc); when(mBubble.getTaskView()).thenReturn(tv); when(tv.getTaskInfo()).thenReturn(taskInfo); mRepository.add(tvtc); return taskInfo; } Loading Loading @@ -285,4 +288,27 @@ public class BubbleTransitionsTest extends ShellTestCase { // directly tested. assertFalse(mTaskViewTransitions.hasPending()); } @Test public void convertDraggedBubbleToFullscreen() { ActivityManager.RunningTaskInfo taskInfo = setupBubble(); final DraggedBubbleIconToFullscreen bt = (DraggedBubbleIconToFullscreen) mBubbleTransitions .startDraggedBubbleIconToFullscreen(mBubble); verify(mTransitions).startTransition(anyInt(), any(), eq(bt)); final TransitionInfo info = new TransitionInfo(TRANSIT_TO_FRONT, 0); final TransitionInfo.Change chg = new TransitionInfo.Change(taskInfo.token, mock(SurfaceControl.class)); chg.setMode(TRANSIT_TO_FRONT); chg.setTaskInfo(taskInfo); info.addChange(chg); info.addRoot(new TransitionInfo.Root(0, mock(SurfaceControl.class), 0, 0)); SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); Transitions.TransitionFinishCallback finishCb = wct -> {}; bt.startAnimation(bt.mTransition, info, startT, finishT, finishCb); verify(startT).apply(); assertFalse(mTaskViewTransitions.hasPending()); } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +2 −1 Original line number Diff line number Diff line Loading @@ -2644,7 +2644,8 @@ public class BubbleController implements ConfigurationChangeListener, } private void moveBubbleToFullscreen(String key) { // TODO b/388858013: convert the bubble to full screen Bubble b = mBubbleData.getBubbleInStackWithKey(key); mBubbleTransitions.startDraggedBubbleIconToFullscreen(b); } private boolean isDeviceLocked() { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java +116 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,11 @@ public class BubbleTransitions { return convert; } /** Starts a transition that converts a dragged bubble icon to a full screen task. */ public BubbleTransition startDraggedBubbleIconToFullscreen(Bubble bubble) { return new DraggedBubbleIconToFullscreen(bubble); } /** * Plucks the task-surface out of an ancestor view while making the view invisible. This helper * attempts to do this seamlessly (ie. view becomes invisible in sync with task reparent). Loading Loading @@ -645,4 +650,115 @@ public class BubbleTransitions { t.apply(); } } /** * A transition that converts a dragged bubble icon to a full screen window. * * <p>This transition assumes that the bubble is invisible so it is simply sent to front. */ class DraggedBubbleIconToFullscreen implements Transitions.TransitionHandler, BubbleTransition { IBinder mTransition; final Bubble mBubble; DraggedBubbleIconToFullscreen(Bubble bubble) { mBubble = bubble; bubble.setPreparingTransition(this); WindowContainerToken token = bubble.getTaskView().getTaskInfo().getToken(); WindowContainerTransaction wct = new WindowContainerTransaction(); wct.setAlwaysOnTop(token, false); wct.setWindowingMode(token, WINDOWING_MODE_UNDEFINED); wct.reorder(token, /* onTop= */ true); wct.setHidden(token, false); mTaskOrganizer.setInterceptBackPressedOnTaskRoot(token, false); mTaskViewTransitions.enqueueExternal(bubble.getTaskView().getController(), () -> { mTransition = mTransitions.startTransition(TRANSIT_TO_FRONT, wct, this); return mTransition; }); } @Override public void skip() { mBubble.setPreparingTransition(null); } @Override public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { if (mTransition != transition) { return false; } final TaskViewTaskController taskViewTaskController = mBubble.getTaskView().getController(); if (taskViewTaskController == null) { mTaskViewTransitions.onExternalDone(transition); finishCallback.onTransitionFinished(null); return true; } TransitionInfo.Change change = findTransitionChange(info); if (change == null) { Slog.w(TAG, "Expected a TaskView transition to front but didn't find " + "one, cleaning up the task view"); taskViewTaskController.setTaskNotFound(); mTaskViewTransitions.onExternalDone(transition); finishCallback.onTransitionFinished(null); return true; } mRepository.remove(taskViewTaskController); startTransaction.apply(); finishCallback.onTransitionFinished(null); taskViewTaskController.notifyTaskRemovalStarted(mBubble.getTaskView().getTaskInfo()); mTaskViewTransitions.onExternalDone(transition); return true; } private TransitionInfo.Change findTransitionChange(TransitionInfo info) { TransitionInfo.Change result = null; WindowContainerToken token = mBubble.getTaskView().getTaskInfo().getToken(); for (int i = 0; i < info.getChanges().size(); ++i) { final TransitionInfo.Change change = info.getChanges().get(i); if (change.getTaskInfo() == null) { continue; } if (change.getMode() != TRANSIT_TO_FRONT) { continue; } if (!token.equals(change.getTaskInfo().token)) { continue; } result = change; break; } return result; } @Override public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull IBinder mergeTarget, @NonNull Transitions.TransitionFinishCallback finishCallback) { } @Override public WindowContainerTransaction handleRequest(@NonNull IBinder transition, @NonNull TransitionRequestInfo request) { return null; } @Override public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted, @Nullable SurfaceControl.Transaction finishTransaction) { if (!aborted) { return; } mTransition = null; mTaskViewTransitions.onExternalDone(transition); } } }
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTransitionsTest.java +26 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.wm.shell.bubbles; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE; Loading Loading @@ -52,6 +53,7 @@ import com.android.launcher3.icons.BubbleIconFactory; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestSyncExecutor; import com.android.wm.shell.bubbles.BubbleTransitions.DraggedBubbleIconToFullscreen; import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView; import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; import com.android.wm.shell.common.ShellExecutor; Loading Loading @@ -136,6 +138,7 @@ public class BubbleTransitionsTest extends ShellTestCase { when(tvtc.getTaskInfo()).thenReturn(taskInfo); when(tv.getController()).thenReturn(tvtc); when(mBubble.getTaskView()).thenReturn(tv); when(tv.getTaskInfo()).thenReturn(taskInfo); mRepository.add(tvtc); return taskInfo; } Loading Loading @@ -285,4 +288,27 @@ public class BubbleTransitionsTest extends ShellTestCase { // directly tested. assertFalse(mTaskViewTransitions.hasPending()); } @Test public void convertDraggedBubbleToFullscreen() { ActivityManager.RunningTaskInfo taskInfo = setupBubble(); final DraggedBubbleIconToFullscreen bt = (DraggedBubbleIconToFullscreen) mBubbleTransitions .startDraggedBubbleIconToFullscreen(mBubble); verify(mTransitions).startTransition(anyInt(), any(), eq(bt)); final TransitionInfo info = new TransitionInfo(TRANSIT_TO_FRONT, 0); final TransitionInfo.Change chg = new TransitionInfo.Change(taskInfo.token, mock(SurfaceControl.class)); chg.setMode(TRANSIT_TO_FRONT); chg.setTaskInfo(taskInfo); info.addChange(chg); info.addRoot(new TransitionInfo.Root(0, mock(SurfaceControl.class), 0, 0)); SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); Transitions.TransitionFinishCallback finishCb = wct -> {}; bt.startAnimation(bt.mTransition, info, startT, finishT, finishCb); verify(startT).apply(); assertFalse(mTaskViewTransitions.hasPending()); } }