Merge "Track pending task info & if the task doesn't launch clean it up" into udc-dev

This commit is contained in:
Mady Mellor
2023-06-09 17:11:39 +00:00
committed by Android (Google) Code Review
4 changed files with 118 additions and 7 deletions

View File

@@ -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;
@@ -236,6 +246,8 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
mTaskInfo = null;
mTaskToken = null;
mTaskLeash = null;
mPendingInfo = null;
mTaskNotFound = false;
}
private void updateTaskVisibility() {
@@ -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;
}
@@ -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
@@ -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;

View File

@@ -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)) {
@@ -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;
}

View File

@@ -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);
}
@@ -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();
}
}

View File

@@ -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;
@@ -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;
@@ -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
@@ -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();
}
}