Loading libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java +55 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,16 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener { private TaskViewBase mTaskViewBase; private final Context mContext; /** * There could be a situation where we have task info and receive * {@link #onTaskAppeared(ActivityManager.RunningTaskInfo, SurfaceControl)}, however, the * activity might fail to open, and in this case we need to clean up the task view / notify * listeners of a task removal. This requires task info, so we save the info from onTaskAppeared * in this situation to allow us to notify listeners correctly if the task failed to open. */ private ActivityManager.RunningTaskInfo mPendingInfo; /* Indicates that the task we attempted to launch in the task view failed to launch. */ private boolean mTaskNotFound; protected ActivityManager.RunningTaskInfo mTaskInfo; private WindowContainerToken mTaskToken; private SurfaceControl mTaskLeash; Loading Loading @@ -236,6 +246,8 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener { mTaskInfo = null; mTaskToken = null; mTaskLeash = null; mPendingInfo = null; mTaskNotFound = false; } private void updateTaskVisibility() { Loading @@ -257,6 +269,12 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener { public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { if (isUsingShellTransitions()) { mPendingInfo = taskInfo; if (mTaskNotFound) { // If we were already notified by shell transit that we don't have the // the task, clean it up now. cleanUpPendingTask(); } // Everything else handled by enter transition. return; } Loading Loading @@ -455,6 +473,42 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener { return mTaskInfo; } /** * Indicates that the task was not found in the start animation for the transition. * In this case we should clean up the task if we have the pending info. If we don't * have the pending info, we'll do it when we receive it in * {@link #onTaskAppeared(ActivityManager.RunningTaskInfo, SurfaceControl)}. */ void setTaskNotFound() { mTaskNotFound = true; if (mPendingInfo != null) { cleanUpPendingTask(); } } /** * Called when a task failed to open and we need to clean up task view / * notify users of task view. */ void cleanUpPendingTask() { if (mPendingInfo != null) { if (mListener != null) { final int taskId = mPendingInfo.taskId; mListenerExecutor.execute(() -> { mListener.onTaskRemovalStarted(taskId); }); } mTaskViewBase.onTaskVanished(mPendingInfo); mTaskOrganizer.setInterceptBackPressedOnTaskRoot(mPendingInfo.token, false); // Make sure the task is removed WindowContainerTransaction wct = new WindowContainerTransaction(); wct.removeTask(mPendingInfo.token); mTaskViewTransitions.closeTaskView(wct, this); } resetTaskInfo(); } void prepareHideAnimation(@NonNull SurfaceControl.Transaction finishTransaction) { if (mTaskToken == null) { // Nothing to update, task is not yet available Loading Loading @@ -492,6 +546,7 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener { @NonNull SurfaceControl.Transaction finishTransaction, ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash, WindowContainerTransaction wct) { mPendingInfo = null; mTaskInfo = taskInfo; mTaskToken = mTaskInfo.token; mTaskLeash = leash; Loading libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java +7 −5 Original line number Diff line number Diff line Loading @@ -139,7 +139,8 @@ public class TaskViewTransitions implements Transitions.TransitionHandler { * `taskView`. * @param taskView the pending transition should be for this. */ private PendingTransition findPendingOpeningTransition(TaskViewTaskController taskView) { @VisibleForTesting PendingTransition findPendingOpeningTransition(TaskViewTaskController taskView) { for (int i = mPending.size() - 1; i >= 0; --i) { if (mPending.get(i).mTaskView != taskView) continue; if (TransitionUtil.isOpeningType(mPending.get(i).mType)) { Loading Loading @@ -398,10 +399,11 @@ public class TaskViewTransitions implements Transitions.TransitionHandler { } } if (stillNeedsMatchingLaunch) { throw new IllegalStateException("Expected a TaskView launch in this transition but" + " didn't get one."); } if (wct == null && pending == null && changesHandled != info.getChanges().size()) { Slog.w(TAG, "Expected a TaskView launch in this transition but didn't get one, " + "cleaning up the task view"); // Didn't find a task so the task must have never launched pending.mTaskView.setTaskNotFound(); } else if (wct == null && pending == null && changesHandled != info.getChanges().size()) { // Just some house-keeping, let another handler animate. return false; } Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java +21 −2 Original line number Diff line number Diff line Loading @@ -128,8 +128,8 @@ public class TaskViewTest extends ShellTestCase { doReturn(true).when(mTransitions).isRegistered(); } mTaskViewTransitions = spy(new TaskViewTransitions(mTransitions)); mTaskViewTaskController = new TaskViewTaskController(mContext, mOrganizer, mTaskViewTransitions, mSyncQueue); mTaskViewTaskController = spy(new TaskViewTaskController(mContext, mOrganizer, mTaskViewTransitions, mSyncQueue)); mTaskView = new TaskView(mContext, mTaskViewTaskController); mTaskView.setListener(mExecutor, mViewListener); } Loading Loading @@ -544,4 +544,23 @@ public class TaskViewTest extends ShellTestCase { mTaskView.removeTask(); verify(mTaskViewTransitions).closeTaskView(any(), eq(mTaskViewTaskController)); } @Test public void testOnTaskAppearedWithTaskNotFound() { assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS); mTaskViewTaskController.setTaskNotFound(); mTaskViewTaskController.onTaskAppeared(mTaskInfo, mLeash); verify(mTaskViewTaskController).cleanUpPendingTask(); verify(mTaskViewTransitions).closeTaskView(any(), eq(mTaskViewTaskController)); } @Test public void testOnTaskAppeared_withoutTaskNotFound() { assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS); mTaskViewTaskController.onTaskAppeared(mTaskInfo, mLeash); verify(mTaskViewTaskController, never()).cleanUpPendingTask(); } } libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionsTest.java +35 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.wm.shell.taskview; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static com.google.common.truth.Truth.assertThat; Loading @@ -25,16 +26,19 @@ import static org.junit.Assume.assumeTrue; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.graphics.Rect; import android.os.IBinder; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.SurfaceControl; import android.window.TransitionInfo; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.transition.Transitions; Loading @@ -45,6 +49,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.List; @SmallTest Loading Loading @@ -295,4 +300,34 @@ public class TaskViewTransitionsTest extends ShellTestCase { mTaskViewTransitions.setTaskBounds(mTaskViewTaskController, new Rect(0, 0, 100, 100)); } @Test public void test_startAnimation_setsTaskNotFound() { assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS); TransitionInfo.Change change = mock(TransitionInfo.Change.class); when(change.getTaskInfo()).thenReturn(mTaskInfo); when(change.getMode()).thenReturn(TRANSIT_OPEN); List<TransitionInfo.Change> changes = new ArrayList<>(); changes.add(change); TransitionInfo info = mock(TransitionInfo.class); when(info.getChanges()).thenReturn(changes); mTaskViewTransitions.startTaskView(new WindowContainerTransaction(), mTaskViewTaskController, mock(IBinder.class)); TaskViewTransitions.PendingTransition pending = mTaskViewTransitions.findPendingOpeningTransition(mTaskViewTaskController); mTaskViewTransitions.startAnimation(pending.mClaimed, info, new SurfaceControl.Transaction(), new SurfaceControl.Transaction(), mock(Transitions.TransitionFinishCallback.class)); verify(mTaskViewTaskController).setTaskNotFound(); } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java +55 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,16 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener { private TaskViewBase mTaskViewBase; private final Context mContext; /** * There could be a situation where we have task info and receive * {@link #onTaskAppeared(ActivityManager.RunningTaskInfo, SurfaceControl)}, however, the * activity might fail to open, and in this case we need to clean up the task view / notify * listeners of a task removal. This requires task info, so we save the info from onTaskAppeared * in this situation to allow us to notify listeners correctly if the task failed to open. */ private ActivityManager.RunningTaskInfo mPendingInfo; /* Indicates that the task we attempted to launch in the task view failed to launch. */ private boolean mTaskNotFound; protected ActivityManager.RunningTaskInfo mTaskInfo; private WindowContainerToken mTaskToken; private SurfaceControl mTaskLeash; Loading Loading @@ -236,6 +246,8 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener { mTaskInfo = null; mTaskToken = null; mTaskLeash = null; mPendingInfo = null; mTaskNotFound = false; } private void updateTaskVisibility() { Loading @@ -257,6 +269,12 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener { public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { if (isUsingShellTransitions()) { mPendingInfo = taskInfo; if (mTaskNotFound) { // If we were already notified by shell transit that we don't have the // the task, clean it up now. cleanUpPendingTask(); } // Everything else handled by enter transition. return; } Loading Loading @@ -455,6 +473,42 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener { return mTaskInfo; } /** * Indicates that the task was not found in the start animation for the transition. * In this case we should clean up the task if we have the pending info. If we don't * have the pending info, we'll do it when we receive it in * {@link #onTaskAppeared(ActivityManager.RunningTaskInfo, SurfaceControl)}. */ void setTaskNotFound() { mTaskNotFound = true; if (mPendingInfo != null) { cleanUpPendingTask(); } } /** * Called when a task failed to open and we need to clean up task view / * notify users of task view. */ void cleanUpPendingTask() { if (mPendingInfo != null) { if (mListener != null) { final int taskId = mPendingInfo.taskId; mListenerExecutor.execute(() -> { mListener.onTaskRemovalStarted(taskId); }); } mTaskViewBase.onTaskVanished(mPendingInfo); mTaskOrganizer.setInterceptBackPressedOnTaskRoot(mPendingInfo.token, false); // Make sure the task is removed WindowContainerTransaction wct = new WindowContainerTransaction(); wct.removeTask(mPendingInfo.token); mTaskViewTransitions.closeTaskView(wct, this); } resetTaskInfo(); } void prepareHideAnimation(@NonNull SurfaceControl.Transaction finishTransaction) { if (mTaskToken == null) { // Nothing to update, task is not yet available Loading Loading @@ -492,6 +546,7 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener { @NonNull SurfaceControl.Transaction finishTransaction, ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash, WindowContainerTransaction wct) { mPendingInfo = null; mTaskInfo = taskInfo; mTaskToken = mTaskInfo.token; mTaskLeash = leash; Loading
libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java +7 −5 Original line number Diff line number Diff line Loading @@ -139,7 +139,8 @@ public class TaskViewTransitions implements Transitions.TransitionHandler { * `taskView`. * @param taskView the pending transition should be for this. */ private PendingTransition findPendingOpeningTransition(TaskViewTaskController taskView) { @VisibleForTesting PendingTransition findPendingOpeningTransition(TaskViewTaskController taskView) { for (int i = mPending.size() - 1; i >= 0; --i) { if (mPending.get(i).mTaskView != taskView) continue; if (TransitionUtil.isOpeningType(mPending.get(i).mType)) { Loading Loading @@ -398,10 +399,11 @@ public class TaskViewTransitions implements Transitions.TransitionHandler { } } if (stillNeedsMatchingLaunch) { throw new IllegalStateException("Expected a TaskView launch in this transition but" + " didn't get one."); } if (wct == null && pending == null && changesHandled != info.getChanges().size()) { Slog.w(TAG, "Expected a TaskView launch in this transition but didn't get one, " + "cleaning up the task view"); // Didn't find a task so the task must have never launched pending.mTaskView.setTaskNotFound(); } else if (wct == null && pending == null && changesHandled != info.getChanges().size()) { // Just some house-keeping, let another handler animate. return false; } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java +21 −2 Original line number Diff line number Diff line Loading @@ -128,8 +128,8 @@ public class TaskViewTest extends ShellTestCase { doReturn(true).when(mTransitions).isRegistered(); } mTaskViewTransitions = spy(new TaskViewTransitions(mTransitions)); mTaskViewTaskController = new TaskViewTaskController(mContext, mOrganizer, mTaskViewTransitions, mSyncQueue); mTaskViewTaskController = spy(new TaskViewTaskController(mContext, mOrganizer, mTaskViewTransitions, mSyncQueue)); mTaskView = new TaskView(mContext, mTaskViewTaskController); mTaskView.setListener(mExecutor, mViewListener); } Loading Loading @@ -544,4 +544,23 @@ public class TaskViewTest extends ShellTestCase { mTaskView.removeTask(); verify(mTaskViewTransitions).closeTaskView(any(), eq(mTaskViewTaskController)); } @Test public void testOnTaskAppearedWithTaskNotFound() { assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS); mTaskViewTaskController.setTaskNotFound(); mTaskViewTaskController.onTaskAppeared(mTaskInfo, mLeash); verify(mTaskViewTaskController).cleanUpPendingTask(); verify(mTaskViewTransitions).closeTaskView(any(), eq(mTaskViewTaskController)); } @Test public void testOnTaskAppeared_withoutTaskNotFound() { assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS); mTaskViewTaskController.onTaskAppeared(mTaskInfo, mLeash); verify(mTaskViewTaskController, never()).cleanUpPendingTask(); } }
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionsTest.java +35 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.wm.shell.taskview; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static com.google.common.truth.Truth.assertThat; Loading @@ -25,16 +26,19 @@ import static org.junit.Assume.assumeTrue; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.graphics.Rect; import android.os.IBinder; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.SurfaceControl; import android.window.TransitionInfo; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.transition.Transitions; Loading @@ -45,6 +49,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.List; @SmallTest Loading Loading @@ -295,4 +300,34 @@ public class TaskViewTransitionsTest extends ShellTestCase { mTaskViewTransitions.setTaskBounds(mTaskViewTaskController, new Rect(0, 0, 100, 100)); } @Test public void test_startAnimation_setsTaskNotFound() { assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS); TransitionInfo.Change change = mock(TransitionInfo.Change.class); when(change.getTaskInfo()).thenReturn(mTaskInfo); when(change.getMode()).thenReturn(TRANSIT_OPEN); List<TransitionInfo.Change> changes = new ArrayList<>(); changes.add(change); TransitionInfo info = mock(TransitionInfo.class); when(info.getChanges()).thenReturn(changes); mTaskViewTransitions.startTaskView(new WindowContainerTransaction(), mTaskViewTaskController, mock(IBinder.class)); TaskViewTransitions.PendingTransition pending = mTaskViewTransitions.findPendingOpeningTransition(mTaskViewTaskController); mTaskViewTransitions.startAnimation(pending.mClaimed, info, new SurfaceControl.Transaction(), new SurfaceControl.Transaction(), mock(Transitions.TransitionFinishCallback.class)); verify(mTaskViewTaskController).setTaskNotFound(); } }