blob: 885eb500cdb20e245180906ffcdd985b48c95daa [file] [log] [blame]
/*
* Copyright (C) 2016 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 android.app.ActivityManager.TaskSnapshot;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.util.EventLog;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import static com.android.server.EventLogTags.WM_TASK_CREATED;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
/**
* Controller for the task container. This is created by activity manager to link task records to
* the task container they use in window manager.
*
* Test class: {@link TaskWindowContainerControllerTests}
*/
public class TaskWindowContainerController
extends WindowContainerController<Task, WindowContainerListener> {
private final int mTaskId;
public TaskWindowContainerController(int taskId, int stackId, int userId, Rect bounds,
Configuration overrideConfig, int resizeMode, boolean homeTask, boolean isOnTopLauncher,
boolean toTop, boolean showForAllUsers) {
super(null, WindowManagerService.getInstance());
mTaskId = taskId;
synchronized(mWindowMap) {
if (DEBUG_STACK) Slog.i(TAG_WM, "TaskWindowContainerController: taskId=" + taskId
+ " stackId=" + stackId + " bounds=" + bounds);
// TODO: Pass controller for the stack to get the container object when stack is
// switched to use controller.
final TaskStack stack = mService.mStackIdToStack.get(stackId);
if (stack == null) {
throw new IllegalArgumentException("TaskWindowContainerController: invalid stackId="
+ stackId);
}
EventLog.writeEvent(WM_TASK_CREATED, taskId, stackId);
final Task task = createTask(taskId, stack, userId, bounds, overrideConfig, resizeMode,
homeTask, isOnTopLauncher);
final int position = toTop ? POSITION_TOP : POSITION_BOTTOM;
stack.addTask(task, position, showForAllUsers, true /* moveParents */);
}
}
@VisibleForTesting
Task createTask(int taskId, TaskStack stack, int userId, Rect bounds,
Configuration overrideConfig, int resizeMode, boolean homeTask,
boolean isOnTopLauncher) {
return new Task(taskId, stack, userId, mService, bounds, overrideConfig, isOnTopLauncher,
resizeMode, homeTask, this);
}
@Override
public void removeContainer() {
synchronized(mWindowMap) {
if (mContainer == null) {
if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + mTaskId);
return;
}
mContainer.removeIfPossible();
super.removeContainer();
}
}
public void positionChildAt(AppWindowContainerController childController, int position) {
synchronized(mService.mWindowMap) {
final AppWindowToken aToken = childController.mContainer;
if (aToken == null) {
Slog.w(TAG_WM,
"Attempted to position of non-existing app : " + childController);
return;
}
final Task task = mContainer;
if (task == null) {
throw new IllegalArgumentException("positionChildAt: invalid task=" + this);
}
task.positionChildAt(position, aToken, false /* includeParents */);
}
}
public void reparent(int stackId, int position) {
synchronized (mWindowMap) {
if (DEBUG_STACK) Slog.i(TAG_WM, "reparent: moving taskId=" + mTaskId
+ " to stackId=" + stackId + " at " + position);
if (mContainer == null) {
if (DEBUG_STACK) Slog.i(TAG_WM,
"reparent: could not find taskId=" + mTaskId);
return;
}
final TaskStack stack = mService.mStackIdToStack.get(stackId);
if (stack == null) {
throw new IllegalArgumentException("reparent: could not find stackId=" + stackId);
}
mContainer.reparent(stack, position);
mService.mWindowPlacerLocked.performSurfacePlacement();
}
}
public void setResizeable(int resizeMode) {
synchronized (mWindowMap) {
if (mContainer != null) {
mContainer.setResizeable(resizeMode);
}
}
}
public void resize(Rect bounds, Configuration overrideConfig, boolean relayout,
boolean forced) {
synchronized (mWindowMap) {
if (mContainer == null) {
throw new IllegalArgumentException("resizeTask: taskId " + mTaskId + " not found.");
}
if (mContainer.resizeLocked(bounds, overrideConfig, forced) && relayout) {
mContainer.getDisplayContent().setLayoutNeeded();
mService.mWindowPlacerLocked.performSurfacePlacement();
}
}
}
// TODO: Move to positionChildAt() in stack controller once we have a stack controller.
public void positionAt(int position, Rect bounds, Configuration overrideConfig) {
synchronized (mWindowMap) {
if (DEBUG_STACK) Slog.i(TAG_WM, "positionChildAt: positioning taskId=" + mTaskId
+ " at " + position);
if (mContainer == null) {
if (DEBUG_STACK) Slog.i(TAG_WM,
"positionAt: could not find taskId=" + mTaskId);
return;
}
final TaskStack stack = mContainer.mStack;
if (stack == null) {
if (DEBUG_STACK) Slog.i(TAG_WM,
"positionAt: could not find stack for task=" + mContainer);
return;
}
mContainer.positionAt(position, bounds, overrideConfig);
final DisplayContent displayContent = stack.getDisplayContent();
displayContent.setLayoutNeeded();
mService.mWindowPlacerLocked.performSurfacePlacement();
}
}
// TODO: Replace with moveChildToTop in stack controller?
public void moveToTop(boolean includingParents) {
synchronized(mWindowMap) {
if (mContainer == null) {
Slog.e(TAG_WM, "moveToTop: taskId=" + mTaskId + " not found");
return;
}
final TaskStack stack = mContainer.mStack;
stack.positionChildAt(POSITION_TOP, mContainer, includingParents);
if (mService.mAppTransition.isTransitionSet()) {
mContainer.setSendingToBottom(false);
}
stack.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
}
}
// TODO: Replace with moveChildToBottom in stack controller?
public void moveToBottom() {
synchronized(mWindowMap) {
if (mContainer == null) {
Slog.e(TAG_WM, "moveTaskToBottom: taskId=" + mTaskId + " not found");
return;
}
final TaskStack stack = mContainer.mStack;
stack.positionChildAt(POSITION_BOTTOM, mContainer, false /* includingParents */);
if (mService.mAppTransition.isTransitionSet()) {
mContainer.setSendingToBottom(true);
}
stack.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
}
}
public void getBounds(Rect bounds) {
synchronized (mWindowMap) {
if (mContainer != null) {
mContainer.getBounds(bounds);
return;
}
bounds.setEmpty();
}
}
/**
* Puts this task into docked drag resizing mode. See {@link DragResizeMode}.
*
* @param resizing Whether to put the task into drag resize mode.
*/
public void setTaskDockedResizing(boolean resizing) {
synchronized (mWindowMap) {
if (mContainer == null) {
Slog.w(TAG_WM, "setTaskDockedResizing: taskId " + mTaskId + " not found.");
return;
}
mContainer.setDragResizing(resizing, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
}
}
public void cancelWindowTransition() {
synchronized (mWindowMap) {
if (mContainer == null) {
Slog.w(TAG_WM, "cancelWindowTransition: taskId " + mTaskId + " not found.");
return;
}
mContainer.cancelTaskWindowTransition();
}
}
public void cancelThumbnailTransition() {
synchronized (mWindowMap) {
if (mContainer == null) {
Slog.w(TAG_WM, "cancelThumbnailTransition: taskId " + mTaskId + " not found.");
return;
}
mContainer.cancelTaskThumbnailTransition();
}
}
/**
* @return a graphic buffer representing a screenshot of a task
*/
public TaskSnapshot getSnapshot() {
synchronized (mWindowMap) {
if (mContainer == null) {
Slog.w(TAG_WM, "getSnapshot: taskId " + mTaskId + " not found.");
return null;
}
return mService.mTaskSnapshotController.getSnapshot(mContainer);
}
}
@Override
public String toString() {
return "{TaskWindowContainerController taskId=" + mTaskId + "}";
}
}