Merge "Track pending task info & if the task doesn't launch clean it up" into udc-dev
This commit is contained in:
@@ -61,6 +61,16 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
|
|||||||
private TaskViewBase mTaskViewBase;
|
private TaskViewBase mTaskViewBase;
|
||||||
private final Context mContext;
|
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;
|
protected ActivityManager.RunningTaskInfo mTaskInfo;
|
||||||
private WindowContainerToken mTaskToken;
|
private WindowContainerToken mTaskToken;
|
||||||
private SurfaceControl mTaskLeash;
|
private SurfaceControl mTaskLeash;
|
||||||
@@ -236,6 +246,8 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
|
|||||||
mTaskInfo = null;
|
mTaskInfo = null;
|
||||||
mTaskToken = null;
|
mTaskToken = null;
|
||||||
mTaskLeash = null;
|
mTaskLeash = null;
|
||||||
|
mPendingInfo = null;
|
||||||
|
mTaskNotFound = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTaskVisibility() {
|
private void updateTaskVisibility() {
|
||||||
@@ -257,6 +269,12 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
|
|||||||
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo,
|
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo,
|
||||||
SurfaceControl leash) {
|
SurfaceControl leash) {
|
||||||
if (isUsingShellTransitions()) {
|
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.
|
// Everything else handled by enter transition.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -455,6 +473,42 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
|
|||||||
return mTaskInfo;
|
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) {
|
void prepareHideAnimation(@NonNull SurfaceControl.Transaction finishTransaction) {
|
||||||
if (mTaskToken == null) {
|
if (mTaskToken == null) {
|
||||||
// Nothing to update, task is not yet available
|
// Nothing to update, task is not yet available
|
||||||
@@ -492,6 +546,7 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
|
|||||||
@NonNull SurfaceControl.Transaction finishTransaction,
|
@NonNull SurfaceControl.Transaction finishTransaction,
|
||||||
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash,
|
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash,
|
||||||
WindowContainerTransaction wct) {
|
WindowContainerTransaction wct) {
|
||||||
|
mPendingInfo = null;
|
||||||
mTaskInfo = taskInfo;
|
mTaskInfo = taskInfo;
|
||||||
mTaskToken = mTaskInfo.token;
|
mTaskToken = mTaskInfo.token;
|
||||||
mTaskLeash = leash;
|
mTaskLeash = leash;
|
||||||
|
|||||||
@@ -139,7 +139,8 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
|
|||||||
* `taskView`.
|
* `taskView`.
|
||||||
* @param taskView the pending transition should be for this.
|
* @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) {
|
for (int i = mPending.size() - 1; i >= 0; --i) {
|
||||||
if (mPending.get(i).mTaskView != taskView) continue;
|
if (mPending.get(i).mTaskView != taskView) continue;
|
||||||
if (TransitionUtil.isOpeningType(mPending.get(i).mType)) {
|
if (TransitionUtil.isOpeningType(mPending.get(i).mType)) {
|
||||||
@@ -398,10 +399,11 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stillNeedsMatchingLaunch) {
|
if (stillNeedsMatchingLaunch) {
|
||||||
throw new IllegalStateException("Expected a TaskView launch in this transition but"
|
Slog.w(TAG, "Expected a TaskView launch in this transition but didn't get one, "
|
||||||
+ " didn't get one.");
|
+ "cleaning up the task view");
|
||||||
}
|
// Didn't find a task so the task must have never launched
|
||||||
if (wct == null && pending == null && changesHandled != info.getChanges().size()) {
|
pending.mTaskView.setTaskNotFound();
|
||||||
|
} else if (wct == null && pending == null && changesHandled != info.getChanges().size()) {
|
||||||
// Just some house-keeping, let another handler animate.
|
// Just some house-keeping, let another handler animate.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,8 +128,8 @@ public class TaskViewTest extends ShellTestCase {
|
|||||||
doReturn(true).when(mTransitions).isRegistered();
|
doReturn(true).when(mTransitions).isRegistered();
|
||||||
}
|
}
|
||||||
mTaskViewTransitions = spy(new TaskViewTransitions(mTransitions));
|
mTaskViewTransitions = spy(new TaskViewTransitions(mTransitions));
|
||||||
mTaskViewTaskController = new TaskViewTaskController(mContext, mOrganizer,
|
mTaskViewTaskController = spy(new TaskViewTaskController(mContext, mOrganizer,
|
||||||
mTaskViewTransitions, mSyncQueue);
|
mTaskViewTransitions, mSyncQueue));
|
||||||
mTaskView = new TaskView(mContext, mTaskViewTaskController);
|
mTaskView = new TaskView(mContext, mTaskViewTaskController);
|
||||||
mTaskView.setListener(mExecutor, mViewListener);
|
mTaskView.setListener(mExecutor, mViewListener);
|
||||||
}
|
}
|
||||||
@@ -544,4 +544,23 @@ public class TaskViewTest extends ShellTestCase {
|
|||||||
mTaskView.removeTask();
|
mTaskView.removeTask();
|
||||||
verify(mTaskViewTransitions).closeTaskView(any(), eq(mTaskViewTaskController));
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.android.wm.shell.taskview;
|
package com.android.wm.shell.taskview;
|
||||||
|
|
||||||
import static android.view.WindowManager.TRANSIT_CHANGE;
|
import static android.view.WindowManager.TRANSIT_CHANGE;
|
||||||
|
import static android.view.WindowManager.TRANSIT_OPEN;
|
||||||
import static android.view.WindowManager.TRANSIT_TO_FRONT;
|
import static android.view.WindowManager.TRANSIT_TO_FRONT;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
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.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.os.IBinder;
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
import android.testing.TestableLooper;
|
import android.testing.TestableLooper;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.window.TransitionInfo;
|
import android.window.TransitionInfo;
|
||||||
import android.window.WindowContainerToken;
|
import android.window.WindowContainerToken;
|
||||||
|
import android.window.WindowContainerTransaction;
|
||||||
|
|
||||||
import com.android.wm.shell.ShellTestCase;
|
import com.android.wm.shell.ShellTestCase;
|
||||||
import com.android.wm.shell.transition.Transitions;
|
import com.android.wm.shell.transition.Transitions;
|
||||||
@@ -45,6 +49,7 @@ import org.junit.runner.RunWith;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@@ -295,4 +300,34 @@ public class TaskViewTransitionsTest extends ShellTestCase {
|
|||||||
mTaskViewTransitions.setTaskBounds(mTaskViewTaskController,
|
mTaskViewTransitions.setTaskBounds(mTaskViewTaskController,
|
||||||
new Rect(0, 0, 100, 100));
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user