blob: 61a2cd96f6c51d74abbcf2e80a217b0e5cd18be7 [file] [log] [blame]
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.server.wm;
18
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010019import android.app.ActivityManager.TaskDescription;
Jorim Jaggie2c77f92016-12-29 14:57:22 +010020import android.app.ActivityManager.TaskSnapshot;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080021import android.content.res.Configuration;
22import android.graphics.Rect;
Jorim Jaggifb9d78a2017-01-05 18:57:12 +010023import android.os.Handler;
24import android.os.Looper;
25import android.os.Message;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080026import android.util.EventLog;
27import android.util.Slog;
Wale Ogunwalec5cc3012017-01-13 13:26:16 -080028import com.android.internal.annotations.VisibleForTesting;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080029
30import static com.android.server.EventLogTags.WM_TASK_CREATED;
31import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
32import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
33import static com.android.server.wm.WindowContainer.POSITION_TOP;
34import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
35import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
36
37/**
38 * Controller for the task container. This is created by activity manager to link task records to
39 * the task container they use in window manager.
40 *
41 * Test class: {@link TaskWindowContainerControllerTests}
42 */
43public class TaskWindowContainerController
Jorim Jaggifb9d78a2017-01-05 18:57:12 +010044 extends WindowContainerController<Task, TaskWindowContainerListener> {
45
46 private static final int REPORT_SNAPSHOT_CHANGED = 0;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080047
48 private final int mTaskId;
49
Jorim Jaggifb9d78a2017-01-05 18:57:12 +010050 private final Handler mHandler = new Handler(Looper.getMainLooper()) {
51
52 @Override
53 public void handleMessage(Message msg) {
54 switch (msg.what) {
55 case REPORT_SNAPSHOT_CHANGED:
Jorim Jaggi329a5832017-01-05 18:57:12 +010056 if (mListener != null) {
57 mListener.onSnapshotChanged((TaskSnapshot) msg.obj);
58 }
Jorim Jaggifb9d78a2017-01-05 18:57:12 +010059 break;
60 }
61 }
62 };
63
64 public TaskWindowContainerController(int taskId, TaskWindowContainerListener listener,
65 int stackId, int userId, Rect bounds, Configuration overrideConfig, int resizeMode,
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010066 boolean homeTask, boolean isOnTopLauncher, boolean toTop, boolean showForAllUsers,
67 TaskDescription taskDescription) {
Jorim Jaggifb9d78a2017-01-05 18:57:12 +010068 super(listener, WindowManagerService.getInstance());
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080069 mTaskId = taskId;
70
71 synchronized(mWindowMap) {
72 if (DEBUG_STACK) Slog.i(TAG_WM, "TaskWindowContainerController: taskId=" + taskId
73 + " stackId=" + stackId + " bounds=" + bounds);
74
75 // TODO: Pass controller for the stack to get the container object when stack is
76 // switched to use controller.
77 final TaskStack stack = mService.mStackIdToStack.get(stackId);
78 if (stack == null) {
79 throw new IllegalArgumentException("TaskWindowContainerController: invalid stackId="
80 + stackId);
81 }
82 EventLog.writeEvent(WM_TASK_CREATED, taskId, stackId);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -080083 final Task task = createTask(taskId, stack, userId, bounds, overrideConfig, resizeMode,
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010084 homeTask, isOnTopLauncher, taskDescription);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080085 final int position = toTop ? POSITION_TOP : POSITION_BOTTOM;
86 stack.addTask(task, position, showForAllUsers, true /* moveParents */);
87 }
88 }
89
Wale Ogunwalec5cc3012017-01-13 13:26:16 -080090 @VisibleForTesting
91 Task createTask(int taskId, TaskStack stack, int userId, Rect bounds,
92 Configuration overrideConfig, int resizeMode, boolean homeTask,
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010093 boolean isOnTopLauncher, TaskDescription taskDescription) {
Wale Ogunwalec5cc3012017-01-13 13:26:16 -080094 return new Task(taskId, stack, userId, mService, bounds, overrideConfig, isOnTopLauncher,
Jorim Jaggi829b9cd2017-01-23 16:20:53 +010095 resizeMode, homeTask, taskDescription, this);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -080096 }
97
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080098 @Override
99 public void removeContainer() {
100 synchronized(mWindowMap) {
101 if (mContainer == null) {
102 if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + mTaskId);
103 return;
104 }
105 mContainer.removeIfPossible();
106 super.removeContainer();
107 }
108 }
109
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800110 public void positionChildAt(AppWindowContainerController childController, int position) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800111 synchronized(mService.mWindowMap) {
112 final AppWindowToken aToken = childController.mContainer;
113 if (aToken == null) {
114 Slog.w(TAG_WM,
115 "Attempted to position of non-existing app : " + childController);
116 return;
117 }
118
119 final Task task = mContainer;
120 if (task == null) {
121 throw new IllegalArgumentException("positionChildAt: invalid task=" + this);
122 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800123 task.positionChildAt(position, aToken, false /* includeParents */);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800124 }
125 }
126
127 public void reparent(int stackId, int position) {
128 synchronized (mWindowMap) {
129 if (DEBUG_STACK) Slog.i(TAG_WM, "reparent: moving taskId=" + mTaskId
130 + " to stackId=" + stackId + " at " + position);
131 if (mContainer == null) {
132 if (DEBUG_STACK) Slog.i(TAG_WM,
133 "reparent: could not find taskId=" + mTaskId);
134 return;
135 }
136 final TaskStack stack = mService.mStackIdToStack.get(stackId);
137 if (stack == null) {
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800138 throw new IllegalArgumentException("reparent: could not find stackId=" + stackId);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800139 }
140 mContainer.reparent(stack, position);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800141 mService.mWindowPlacerLocked.performSurfacePlacement();
142 }
143 }
144
145 public void setResizeable(int resizeMode) {
146 synchronized (mWindowMap) {
147 if (mContainer != null) {
148 mContainer.setResizeable(resizeMode);
149 }
150 }
151 }
152
153 public void resize(Rect bounds, Configuration overrideConfig, boolean relayout,
154 boolean forced) {
155 synchronized (mWindowMap) {
156 if (mContainer == null) {
157 throw new IllegalArgumentException("resizeTask: taskId " + mTaskId + " not found.");
158 }
159
160 if (mContainer.resizeLocked(bounds, overrideConfig, forced) && relayout) {
161 mContainer.getDisplayContent().setLayoutNeeded();
162 mService.mWindowPlacerLocked.performSurfacePlacement();
163 }
164 }
165 }
166
167 // TODO: Move to positionChildAt() in stack controller once we have a stack controller.
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800168 public void positionAt(int position, Rect bounds, Configuration overrideConfig) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800169 synchronized (mWindowMap) {
170 if (DEBUG_STACK) Slog.i(TAG_WM, "positionChildAt: positioning taskId=" + mTaskId
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800171 + " at " + position);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800172 if (mContainer == null) {
173 if (DEBUG_STACK) Slog.i(TAG_WM,
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800174 "positionAt: could not find taskId=" + mTaskId);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800175 return;
176 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800177 final TaskStack stack = mContainer.mStack;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800178 if (stack == null) {
179 if (DEBUG_STACK) Slog.i(TAG_WM,
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800180 "positionAt: could not find stack for task=" + mContainer);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800181 return;
182 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800183 mContainer.positionAt(position, bounds, overrideConfig);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800184 final DisplayContent displayContent = stack.getDisplayContent();
185 displayContent.setLayoutNeeded();
186 mService.mWindowPlacerLocked.performSurfacePlacement();
187 }
188 }
189
190 // TODO: Replace with moveChildToTop in stack controller?
191 public void moveToTop(boolean includingParents) {
192 synchronized(mWindowMap) {
193 if (mContainer == null) {
194 Slog.e(TAG_WM, "moveToTop: taskId=" + mTaskId + " not found");
195 return;
196 }
197 final TaskStack stack = mContainer.mStack;
198 stack.positionChildAt(POSITION_TOP, mContainer, includingParents);
199
200 if (mService.mAppTransition.isTransitionSet()) {
201 mContainer.setSendingToBottom(false);
202 }
203 stack.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
204 }
205 }
206
207 // TODO: Replace with moveChildToBottom in stack controller?
208 public void moveToBottom() {
209 synchronized(mWindowMap) {
210 if (mContainer == null) {
211 Slog.e(TAG_WM, "moveTaskToBottom: taskId=" + mTaskId + " not found");
212 return;
213 }
214 final TaskStack stack = mContainer.mStack;
215 stack.positionChildAt(POSITION_BOTTOM, mContainer, false /* includingParents */);
216 if (mService.mAppTransition.isTransitionSet()) {
217 mContainer.setSendingToBottom(true);
218 }
219 stack.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
220 }
221 }
222
223 public void getBounds(Rect bounds) {
224 synchronized (mWindowMap) {
225 if (mContainer != null) {
226 mContainer.getBounds(bounds);
227 return;
228 }
229 bounds.setEmpty();
230 }
231 }
232
233 /**
234 * Puts this task into docked drag resizing mode. See {@link DragResizeMode}.
235 *
236 * @param resizing Whether to put the task into drag resize mode.
237 */
238 public void setTaskDockedResizing(boolean resizing) {
239 synchronized (mWindowMap) {
240 if (mContainer == null) {
241 Slog.w(TAG_WM, "setTaskDockedResizing: taskId " + mTaskId + " not found.");
242 return;
243 }
244 mContainer.setDragResizing(resizing, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
245 }
246 }
247
248 public void cancelWindowTransition() {
249 synchronized (mWindowMap) {
250 if (mContainer == null) {
251 Slog.w(TAG_WM, "cancelWindowTransition: taskId " + mTaskId + " not found.");
252 return;
253 }
254 mContainer.cancelTaskWindowTransition();
255 }
256 }
257
258 public void cancelThumbnailTransition() {
259 synchronized (mWindowMap) {
260 if (mContainer == null) {
261 Slog.w(TAG_WM, "cancelThumbnailTransition: taskId " + mTaskId + " not found.");
262 return;
263 }
264 mContainer.cancelTaskThumbnailTransition();
265 }
266 }
267
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100268 public void setTaskDescription(TaskDescription taskDescription) {
269 synchronized (mWindowMap) {
270 if (mContainer == null) {
271 Slog.w(TAG_WM, "setTaskDescription: taskId " + mTaskId + " not found.");
272 return;
273 }
274 mContainer.setTaskDescription(taskDescription);
275 }
276 }
277
Jorim Jaggifb9d78a2017-01-05 18:57:12 +0100278 void reportSnapshotChanged(TaskSnapshot snapshot) {
279 mHandler.obtainMessage(REPORT_SNAPSHOT_CHANGED, snapshot).sendToTarget();
280 }
281
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800282 @Override
283 public String toString() {
284 return "{TaskWindowContainerController taskId=" + mTaskId + "}";
285 }
286}