Merge "Move Task Close to WindowContainerTransaction" into tm-qpr-dev

This commit is contained in:
Maryam Dehaini
2022-08-31 20:39:37 +00:00
committed by Android (Google) Code Review
7 changed files with 139 additions and 1 deletions

View File

@@ -3398,6 +3398,7 @@ package android.window {
method @NonNull public android.window.WindowContainerTransaction createTaskFragment(@NonNull android.window.TaskFragmentCreationParams);
method @NonNull public android.window.WindowContainerTransaction deleteTaskFragment(@NonNull android.window.WindowContainerToken);
method public int describeContents();
method @NonNull public android.window.WindowContainerTransaction removeTask(@NonNull android.window.WindowContainerToken);
method @NonNull public android.window.WindowContainerTransaction reorder(@NonNull android.window.WindowContainerToken, boolean);
method @NonNull public android.window.WindowContainerTransaction reparent(@NonNull android.window.WindowContainerToken, @Nullable android.window.WindowContainerToken, boolean);
method @NonNull public android.window.WindowContainerTransaction reparentActivityToTaskFragment(@NonNull android.os.IBinder, @NonNull android.os.IBinder);

View File

@@ -455,6 +455,17 @@ public final class WindowContainerTransaction implements Parcelable {
return this;
}
/**
* Finds and removes a task and its children using its container token. The task is removed
* from recents.
* @param containerToken ContainerToken of Task to be removed
*/
@NonNull
public WindowContainerTransaction removeTask(@NonNull WindowContainerToken containerToken) {
mHierarchyOps.add(HierarchyOp.createForRemoveTask(containerToken.asBinder()));
return this;
}
/**
* Sends a pending intent in sync.
* @param sender The PendingIntent sender.
@@ -1153,6 +1164,7 @@ public final class WindowContainerTransaction implements Parcelable {
public static final int HIERARCHY_OP_TYPE_REMOVE_INSETS_PROVIDER = 17;
public static final int HIERARCHY_OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT = 18;
public static final int HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP = 19;
public static final int HIERARCHY_OP_TYPE_REMOVE_TASK = 20;
// The following key(s) are for use with mLaunchOptions:
// When launching a task (eg. from recents), this is the taskId to be launched.
@@ -1282,6 +1294,13 @@ public final class WindowContainerTransaction implements Parcelable {
.build();
}
/** create a hierarchy op for deleting a task **/
public static HierarchyOp createForRemoveTask(@NonNull IBinder container) {
return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REMOVE_TASK)
.setContainer(container)
.build();
}
/** Only creates through {@link Builder}. */
private HierarchyOp(int type) {
mType = type;
@@ -1465,6 +1484,8 @@ public final class WindowContainerTransaction implements Parcelable {
case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP:
return "{setAlwaysOnTop: container=" + mContainer
+ " alwaysOnTop=" + mAlwaysOnTop + "}";
case HIERARCHY_OP_TYPE_REMOVE_TASK:
return "{RemoveTask: task=" + mContainer + "}";
default:
return "{mType=" + mType + " container=" + mContainer + " reparent=" + mReparent
+ " mToTop=" + mToTop

View File

@@ -91,6 +91,12 @@ public class FreeformTaskTransitionHandler
}
@Override
public void startRemoveTransition(WindowContainerTransaction wct) {
final int type = WindowManager.TRANSIT_CLOSE;
mPendingTransitionTokens.add(mTransitions.startTransition(type, wct, this));
}
@Override
public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startT,

View File

@@ -40,4 +40,12 @@ public interface FreeformTaskTransitionStarter {
*
*/
void startMinimizedModeTransition(WindowContainerTransaction wct);
/**
* Starts close window transition
*
* @param wct the {@link WindowContainerTransaction} that closes the task
*
*/
void startRemoveTransition(WindowContainerTransaction wct);
}

View File

@@ -148,7 +148,13 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
public void onClick(View v) {
final int id = v.getId();
if (id == R.id.close_window) {
mActivityTaskManager.removeTask(mTaskId);
WindowContainerTransaction wct = new WindowContainerTransaction();
wct.removeTask(mTaskToken);
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
mTransitionStarter.startRemoveTransition(wct);
} else {
mSyncQueue.queue(wct);
}
} else if (id == R.id.maximize_window) {
WindowContainerTransaction wct = new WindowContainerTransaction();
RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);

View File

@@ -29,6 +29,7 @@ import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_LAUNCH_TASK;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_PENDING_INTENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_INSETS_PROVIDER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_TASK;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT;
@@ -703,6 +704,12 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
@Nullable ITaskFragmentOrganizer organizer, @Nullable Transition finishTransition) {
final int type = hop.getType();
switch (type) {
case HIERARCHY_OP_TYPE_REMOVE_TASK: {
final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
final Task task = wc != null ? wc.asTask() : null;
task.remove(true, "Applying remove task Hierarchy Op");
break;
}
case HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT: {
final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
final Task task = wc != null ? wc.asTask() : null;

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wm;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.atLeast;
import android.content.Intent;
import android.platform.test.annotations.Presubmit;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Test class for {@link WindowContainerTransaction}.
*
* Build/Install/Run:
* atest WmTests:WindowContainerTransactionTests
*/
@SmallTest
@Presubmit
@RunWith(WindowTestRunner.class)
public class WindowContainerTransactionTests extends WindowTestsBase {
@Test
public void testRemoveTask() {
final Task rootTask = createTask(mDisplayContent);
final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
WindowContainerTransaction wct = new WindowContainerTransaction();
WindowContainerToken token = task.getTaskInfo().token;
wct.removeTask(token);
applyTransaction(wct);
// There is still an activity to be destroyed, so the task is not removed immediately.
assertNotNull(task.getParent());
assertTrue(rootTask.hasChild());
assertTrue(task.hasChild());
assertTrue(activity.finishing);
activity.destroyed("testRemoveContainer");
// Assert that the container was removed after the activity is destroyed.
assertNull(task.getParent());
assertEquals(0, task.getChildCount());
assertNull(activity.getParent());
verify(mAtm.getLockTaskController(), atLeast(1)).clearLockedTask(task);
verify(mAtm.getLockTaskController(), atLeast(1)).clearLockedTask(rootTask);
}
private Task createTask(int taskId) {
return new Task.Builder(mAtm)
.setTaskId(taskId)
.setIntent(new Intent())
.setRealActivity(ActivityBuilder.getDefaultComponent())
.setEffectiveUid(10050)
.buildInner();
}
private void applyTransaction(@NonNull WindowContainerTransaction t) {
if (!t.isEmpty()) {
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
}
}
}