Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java +66 −12 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED; import static com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP; import static com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE; import static com.android.wm.shell.transition.Transitions.TransitionObserver; import android.annotation.NonNull; Loading @@ -35,6 +36,7 @@ import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SingleInstanceRemoteListener; import com.android.wm.shell.shared.IHomeTransitionListener; import com.android.wm.shell.shared.TransitionUtil; import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper; /** * The {@link TransitionObserver} that observes for transitions involving the home Loading @@ -48,6 +50,8 @@ public class HomeTransitionObserver implements TransitionObserver, private @NonNull final Context mContext; private @NonNull final ShellExecutor mMainExecutor; private Boolean mPendingHomeVisibilityUpdate; public HomeTransitionObserver(@NonNull Context context, @NonNull ShellExecutor mainExecutor) { mContext = context; Loading @@ -59,16 +63,67 @@ public class HomeTransitionObserver implements TransitionObserver, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction) { if (BubbleAnythingFlagHelper.enableBubbleToFullscreen()) { handleTransitionReadyWithBubbleAnything(info); } else { handleTransitionReady(info); } } private void handleTransitionReady(@NonNull TransitionInfo info) { for (TransitionInfo.Change change : info.getChanges()) { final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); if (taskInfo == null || info.getType() == TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP || taskInfo.displayId != DEFAULT_DISPLAY || taskInfo.taskId == -1 || !taskInfo.isRunning) { continue; } Boolean homeVisibilityUpdate = getHomeVisibilityUpdate(info, change, taskInfo); if (homeVisibilityUpdate != null) { notifyHomeVisibilityChanged(homeVisibilityUpdate); } } } private void handleTransitionReadyWithBubbleAnything(@NonNull TransitionInfo info) { Boolean homeVisibilityUpdate = null; for (TransitionInfo.Change change : info.getChanges()) { final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); if (info.getType() == TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP || taskInfo == null if (taskInfo == null || taskInfo.displayId != DEFAULT_DISPLAY || taskInfo.taskId == -1 || !taskInfo.isRunning) { continue; } Boolean update = getHomeVisibilityUpdate(info, change, taskInfo); if (update != null) { homeVisibilityUpdate = update; } } if (info.getType() == TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP) { // Do not apply at the start of desktop drag as that updates launcher UI visibility. // Store the value and apply with a next transition if needed. mPendingHomeVisibilityUpdate = homeVisibilityUpdate; return; } if (info.getType() == TRANSIT_CONVERT_TO_BUBBLE && homeVisibilityUpdate == null) { // We are converting to bubble and we did not get a change to home visibility in this // transition. Apply the value from start of drag. homeVisibilityUpdate = mPendingHomeVisibilityUpdate; } if (homeVisibilityUpdate != null) { mPendingHomeVisibilityUpdate = null; notifyHomeVisibilityChanged(homeVisibilityUpdate); } } private Boolean getHomeVisibilityUpdate(TransitionInfo info, TransitionInfo.Change change, ActivityManager.RunningTaskInfo taskInfo) { final int mode = change.getMode(); final boolean isBackGesture = change.hasFlags(FLAG_BACK_GESTURE_ANIMATED); if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME) { Loading @@ -76,11 +131,10 @@ public class HomeTransitionObserver implements TransitionObserver, && TransitionUtil.isClosingType(info.getType()); if (gestureToHomeTransition || TransitionUtil.isClosingMode(mode) || (!isBackGesture && TransitionUtil.isOpeningMode(mode))) { notifyHomeVisibilityChanged(gestureToHomeTransition || TransitionUtil.isOpeningType(mode)); } return gestureToHomeTransition || TransitionUtil.isOpeningType(mode); } } return null; } @Override Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java +84 −0 Original line number Diff line number Diff line Loading @@ -17,36 +17,44 @@ package com.android.wm.shell.transition; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_PREPARE_BACK_NAVIGATION; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP; import static com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.app.WindowConfiguration.ActivityType; import android.content.Context; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.platform.test.annotations.EnableFlags; import android.view.SurfaceControl; import android.window.TransitionInfo; import android.window.TransitionInfo.TransitionMode; import android.window.WindowContainerToken; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import com.android.wm.shell.Flags; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestShellExecutor; Loading Loading @@ -187,6 +195,72 @@ public class HomeTransitionObserverTest extends ShellTestCase { verify(mListener, times(0)).onHomeVisibilityChanged(anyBoolean()); } @Test @EnableFlags({Flags.FLAG_ENABLE_BUBBLE_TO_FULLSCREEN, Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE}) public void testDragTaskToBubbleOverHome_notifiesHomeIsVisible() throws RemoteException { ActivityManager.RunningTaskInfo homeTask = createTaskInfo(1, ACTIVITY_TYPE_HOME); ActivityManager.RunningTaskInfo bubbleTask = createTaskInfo(2, ACTIVITY_TYPE_STANDARD); TransitionInfo startDragTransition = new TransitionInfoBuilder(TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP) .addChange(TRANSIT_TO_FRONT, homeTask) .addChange(TRANSIT_TO_BACK, bubbleTask) .build(); // Start drag to desktop which brings home to front mHomeTransitionObserver.onTransitionReady(new Binder(), startDragTransition, MockTransactionPool.create(), MockTransactionPool.create()); // Does not notify home visibility yet verify(mListener, never()).onHomeVisibilityChanged(anyBoolean()); TransitionInfo convertToBubbleTransition = new TransitionInfoBuilder(TRANSIT_CONVERT_TO_BUBBLE) .addChange(TRANSIT_TO_FRONT, bubbleTask) .build(); // Convert to bubble. Transition does not include changes for home task mHomeTransitionObserver.onTransitionReady(new Binder(), convertToBubbleTransition, MockTransactionPool.create(), MockTransactionPool.create()); // Notifies home visibility change that was pending from the start of drag verify(mListener).onHomeVisibilityChanged(true); } @Test @EnableFlags({Flags.FLAG_ENABLE_BUBBLE_TO_FULLSCREEN, Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE}) public void testDragTaskToBubbleOverOtherTask_notifiesHomeIsNotVisible() throws RemoteException { ActivityManager.RunningTaskInfo homeTask = createTaskInfo(1, ACTIVITY_TYPE_HOME); ActivityManager.RunningTaskInfo bubbleTask = createTaskInfo(2, ACTIVITY_TYPE_STANDARD); ActivityManager.RunningTaskInfo otherTask = createTaskInfo(3, ACTIVITY_TYPE_STANDARD); TransitionInfo startDragTransition = new TransitionInfoBuilder(TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP) .addChange(TRANSIT_TO_FRONT, homeTask) .addChange(TRANSIT_TO_BACK, bubbleTask) .build(); // Start drag to desktop which brings home to front mHomeTransitionObserver.onTransitionReady(new Binder(), startDragTransition, MockTransactionPool.create(), MockTransactionPool.create()); // Does not notify home visibility yet verify(mListener, never()).onHomeVisibilityChanged(anyBoolean()); TransitionInfo convertToBubbleTransition = new TransitionInfoBuilder(TRANSIT_CONVERT_TO_BUBBLE) .addChange(TRANSIT_TO_FRONT, bubbleTask) .addChange(TRANSIT_TO_FRONT, otherTask) .addChange(TRANSIT_TO_BACK, homeTask) .build(); // Convert to bubble. Transition includes home task to back which updates home visibility mHomeTransitionObserver.onTransitionReady(new Binder(), convertToBubbleTransition, MockTransactionPool.create(), MockTransactionPool.create()); // Notifies home visibility change due to home moving to back in the second transition verify(mListener).onHomeVisibilityChanged(false); } @Test public void testHomeActivityWithBackGestureNotifiesHomeIsVisibleAfterClose() throws RemoteException { Loading Loading @@ -227,4 +301,14 @@ public class HomeTransitionObserverTest extends ShellTestCase { when(change.getMode()).thenReturn(mode); taskInfo.isRunning = isRunning; } private static ActivityManager.RunningTaskInfo createTaskInfo(int taskId, int activityType) { ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); taskInfo.taskId = taskId; taskInfo.topActivityType = activityType; taskInfo.configuration.windowConfiguration.setActivityType(activityType); taskInfo.token = mock(WindowContainerToken.class); taskInfo.isRunning = true; return taskInfo; } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java +66 −12 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED; import static com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP; import static com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE; import static com.android.wm.shell.transition.Transitions.TransitionObserver; import android.annotation.NonNull; Loading @@ -35,6 +36,7 @@ import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SingleInstanceRemoteListener; import com.android.wm.shell.shared.IHomeTransitionListener; import com.android.wm.shell.shared.TransitionUtil; import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper; /** * The {@link TransitionObserver} that observes for transitions involving the home Loading @@ -48,6 +50,8 @@ public class HomeTransitionObserver implements TransitionObserver, private @NonNull final Context mContext; private @NonNull final ShellExecutor mMainExecutor; private Boolean mPendingHomeVisibilityUpdate; public HomeTransitionObserver(@NonNull Context context, @NonNull ShellExecutor mainExecutor) { mContext = context; Loading @@ -59,16 +63,67 @@ public class HomeTransitionObserver implements TransitionObserver, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction) { if (BubbleAnythingFlagHelper.enableBubbleToFullscreen()) { handleTransitionReadyWithBubbleAnything(info); } else { handleTransitionReady(info); } } private void handleTransitionReady(@NonNull TransitionInfo info) { for (TransitionInfo.Change change : info.getChanges()) { final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); if (taskInfo == null || info.getType() == TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP || taskInfo.displayId != DEFAULT_DISPLAY || taskInfo.taskId == -1 || !taskInfo.isRunning) { continue; } Boolean homeVisibilityUpdate = getHomeVisibilityUpdate(info, change, taskInfo); if (homeVisibilityUpdate != null) { notifyHomeVisibilityChanged(homeVisibilityUpdate); } } } private void handleTransitionReadyWithBubbleAnything(@NonNull TransitionInfo info) { Boolean homeVisibilityUpdate = null; for (TransitionInfo.Change change : info.getChanges()) { final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); if (info.getType() == TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP || taskInfo == null if (taskInfo == null || taskInfo.displayId != DEFAULT_DISPLAY || taskInfo.taskId == -1 || !taskInfo.isRunning) { continue; } Boolean update = getHomeVisibilityUpdate(info, change, taskInfo); if (update != null) { homeVisibilityUpdate = update; } } if (info.getType() == TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP) { // Do not apply at the start of desktop drag as that updates launcher UI visibility. // Store the value and apply with a next transition if needed. mPendingHomeVisibilityUpdate = homeVisibilityUpdate; return; } if (info.getType() == TRANSIT_CONVERT_TO_BUBBLE && homeVisibilityUpdate == null) { // We are converting to bubble and we did not get a change to home visibility in this // transition. Apply the value from start of drag. homeVisibilityUpdate = mPendingHomeVisibilityUpdate; } if (homeVisibilityUpdate != null) { mPendingHomeVisibilityUpdate = null; notifyHomeVisibilityChanged(homeVisibilityUpdate); } } private Boolean getHomeVisibilityUpdate(TransitionInfo info, TransitionInfo.Change change, ActivityManager.RunningTaskInfo taskInfo) { final int mode = change.getMode(); final boolean isBackGesture = change.hasFlags(FLAG_BACK_GESTURE_ANIMATED); if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME) { Loading @@ -76,11 +131,10 @@ public class HomeTransitionObserver implements TransitionObserver, && TransitionUtil.isClosingType(info.getType()); if (gestureToHomeTransition || TransitionUtil.isClosingMode(mode) || (!isBackGesture && TransitionUtil.isOpeningMode(mode))) { notifyHomeVisibilityChanged(gestureToHomeTransition || TransitionUtil.isOpeningType(mode)); } return gestureToHomeTransition || TransitionUtil.isOpeningType(mode); } } return null; } @Override Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java +84 −0 Original line number Diff line number Diff line Loading @@ -17,36 +17,44 @@ package com.android.wm.shell.transition; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_PREPARE_BACK_NAVIGATION; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP; import static com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.app.WindowConfiguration.ActivityType; import android.content.Context; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.platform.test.annotations.EnableFlags; import android.view.SurfaceControl; import android.window.TransitionInfo; import android.window.TransitionInfo.TransitionMode; import android.window.WindowContainerToken; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import com.android.wm.shell.Flags; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestShellExecutor; Loading Loading @@ -187,6 +195,72 @@ public class HomeTransitionObserverTest extends ShellTestCase { verify(mListener, times(0)).onHomeVisibilityChanged(anyBoolean()); } @Test @EnableFlags({Flags.FLAG_ENABLE_BUBBLE_TO_FULLSCREEN, Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE}) public void testDragTaskToBubbleOverHome_notifiesHomeIsVisible() throws RemoteException { ActivityManager.RunningTaskInfo homeTask = createTaskInfo(1, ACTIVITY_TYPE_HOME); ActivityManager.RunningTaskInfo bubbleTask = createTaskInfo(2, ACTIVITY_TYPE_STANDARD); TransitionInfo startDragTransition = new TransitionInfoBuilder(TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP) .addChange(TRANSIT_TO_FRONT, homeTask) .addChange(TRANSIT_TO_BACK, bubbleTask) .build(); // Start drag to desktop which brings home to front mHomeTransitionObserver.onTransitionReady(new Binder(), startDragTransition, MockTransactionPool.create(), MockTransactionPool.create()); // Does not notify home visibility yet verify(mListener, never()).onHomeVisibilityChanged(anyBoolean()); TransitionInfo convertToBubbleTransition = new TransitionInfoBuilder(TRANSIT_CONVERT_TO_BUBBLE) .addChange(TRANSIT_TO_FRONT, bubbleTask) .build(); // Convert to bubble. Transition does not include changes for home task mHomeTransitionObserver.onTransitionReady(new Binder(), convertToBubbleTransition, MockTransactionPool.create(), MockTransactionPool.create()); // Notifies home visibility change that was pending from the start of drag verify(mListener).onHomeVisibilityChanged(true); } @Test @EnableFlags({Flags.FLAG_ENABLE_BUBBLE_TO_FULLSCREEN, Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE}) public void testDragTaskToBubbleOverOtherTask_notifiesHomeIsNotVisible() throws RemoteException { ActivityManager.RunningTaskInfo homeTask = createTaskInfo(1, ACTIVITY_TYPE_HOME); ActivityManager.RunningTaskInfo bubbleTask = createTaskInfo(2, ACTIVITY_TYPE_STANDARD); ActivityManager.RunningTaskInfo otherTask = createTaskInfo(3, ACTIVITY_TYPE_STANDARD); TransitionInfo startDragTransition = new TransitionInfoBuilder(TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP) .addChange(TRANSIT_TO_FRONT, homeTask) .addChange(TRANSIT_TO_BACK, bubbleTask) .build(); // Start drag to desktop which brings home to front mHomeTransitionObserver.onTransitionReady(new Binder(), startDragTransition, MockTransactionPool.create(), MockTransactionPool.create()); // Does not notify home visibility yet verify(mListener, never()).onHomeVisibilityChanged(anyBoolean()); TransitionInfo convertToBubbleTransition = new TransitionInfoBuilder(TRANSIT_CONVERT_TO_BUBBLE) .addChange(TRANSIT_TO_FRONT, bubbleTask) .addChange(TRANSIT_TO_FRONT, otherTask) .addChange(TRANSIT_TO_BACK, homeTask) .build(); // Convert to bubble. Transition includes home task to back which updates home visibility mHomeTransitionObserver.onTransitionReady(new Binder(), convertToBubbleTransition, MockTransactionPool.create(), MockTransactionPool.create()); // Notifies home visibility change due to home moving to back in the second transition verify(mListener).onHomeVisibilityChanged(false); } @Test public void testHomeActivityWithBackGestureNotifiesHomeIsVisibleAfterClose() throws RemoteException { Loading Loading @@ -227,4 +301,14 @@ public class HomeTransitionObserverTest extends ShellTestCase { when(change.getMode()).thenReturn(mode); taskInfo.isRunning = isRunning; } private static ActivityManager.RunningTaskInfo createTaskInfo(int taskId, int activityType) { ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); taskInfo.taskId = taskId; taskInfo.topActivityType = activityType; taskInfo.configuration.windowConfiguration.setActivityType(activityType); taskInfo.token = mock(WindowContainerToken.class); taskInfo.isRunning = true; return taskInfo; } }