blob: 2e29931421893156616b2f97e3cecce04c3d106e [file] [log] [blame]
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -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
19import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
20import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Jorim Jaggif84e2f62018-01-16 14:17:59 +010021import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
22import static android.view.WindowManager.TRANSIT_UNSET;
Vishnu Nairc1d2ff62018-11-08 16:50:12 -080023
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080024import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
25import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
26import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080027import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
28import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
29import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
30import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080031
Jorim Jaggie2c77f92016-12-29 14:57:22 +010032import android.app.ActivityManager.TaskSnapshot;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080033import android.content.res.CompatibilityInfo;
34import android.content.res.Configuration;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080035import android.os.Debug;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080036import android.os.Handler;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080037import android.os.IBinder;
Sudheer Shankac766db02017-06-12 10:37:29 -070038import android.os.Looper;
39import android.os.Message;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080040import android.util.Slog;
41import android.view.IApplicationToken;
Jorim Jaggif84e2f62018-01-16 14:17:59 +010042import android.view.RemoteAnimationDefinition;
43import android.view.WindowManager;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080044
Winson Chung30480042017-01-26 10:55:34 -080045import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080046import com.android.server.AttributeCache;
Adrian Roose99bc052017-11-20 17:55:31 +010047import com.android.server.policy.WindowManagerPolicy.StartingSurface;
48
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080049/**
50 * Controller for the app window token container. This is created by activity manager to link
51 * activity records to the app window token container they use in window manager.
52 *
53 * Test class: {@link AppWindowContainerControllerTests}
54 */
55public class AppWindowContainerController
56 extends WindowContainerController<AppWindowToken, AppWindowContainerListener> {
57
Jorim Jaggi02886a82016-12-06 09:10:06 -080058 private static final int STARTING_WINDOW_TYPE_NONE = 0;
59 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
60 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
61
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080062 private final IApplicationToken mToken;
Jorim Jaggi9bafc712017-01-19 17:28:30 +010063 private final Handler mHandler;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080064
Sudheer Shankac766db02017-06-12 10:37:29 -070065 private final class H extends Handler {
66 public static final int NOTIFY_WINDOWS_DRAWN = 1;
67 public static final int NOTIFY_STARTING_WINDOW_DRAWN = 2;
Vishnu Nairc1d2ff62018-11-08 16:50:12 -080068 public static final int NOTIFY_WINDOWS_NOTDRAWN = 3;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080069
Sudheer Shankac766db02017-06-12 10:37:29 -070070 public H(Looper looper) {
71 super(looper);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080072 }
Sudheer Shankac766db02017-06-12 10:37:29 -070073
74 @Override
75 public void handleMessage(Message msg) {
76 switch (msg.what) {
77 case NOTIFY_WINDOWS_DRAWN:
78 if (mListener == null) {
79 return;
80 }
81 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting drawn in "
82 + AppWindowContainerController.this.mToken);
83 mListener.onWindowsDrawn(msg.getWhen());
84 break;
85 case NOTIFY_STARTING_WINDOW_DRAWN:
86 if (mListener == null) {
87 return;
88 }
Vishnu Nairc1d2ff62018-11-08 16:50:12 -080089 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting starting window drawn in "
Sudheer Shankac766db02017-06-12 10:37:29 -070090 + AppWindowContainerController.this.mToken);
91 mListener.onStartingWindowDrawn(msg.getWhen());
92 break;
Vishnu Nairc1d2ff62018-11-08 16:50:12 -080093 case NOTIFY_WINDOWS_NOTDRAWN:
94 if (mListener == null) {
95 return;
96 }
97 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting undrawn in "
98 + AppWindowContainerController.this.mToken);
99 mListener.onWindowsNotDrawn(msg.getWhen());
100 break;
Sudheer Shankac766db02017-06-12 10:37:29 -0700101 default:
102 break;
103 }
104 }
105 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800106
107 private final Runnable mOnWindowsVisible = () -> {
108 if (mListener == null) {
109 return;
110 }
111 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting visible in "
112 + AppWindowContainerController.this.mToken);
113 mListener.onWindowsVisible();
114 };
115
116 private final Runnable mOnWindowsGone = () -> {
117 if (mListener == null) {
118 return;
119 }
120 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in "
121 + AppWindowContainerController.this.mToken);
122 mListener.onWindowsGone();
123 };
124
Jorim Jaggid8665f22018-04-10 00:34:24 +0200125 private final Runnable mAddStartingWindow = new Runnable() {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800126
Jorim Jaggid8665f22018-04-10 00:34:24 +0200127 @Override
128 public void run() {
129 final StartingData startingData;
130 final AppWindowToken container;
131
132 synchronized (mWindowMap) {
133 if (mContainer == null) {
134 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "mContainer was null while trying to"
135 + " add starting window");
136 return;
137 }
138
139 // There can only be one adding request, silly caller!
140 mService.mAnimationHandler.removeCallbacks(this);
141
142 startingData = mContainer.startingData;
143 container = mContainer;
144 }
145
146 if (startingData == null) {
147 // Animation has been canceled... do nothing.
148 if (DEBUG_STARTING_WINDOW)
149 Slog.v(TAG_WM, "startingData was nulled out before handling"
150 + " mAddStartingWindow: " + mContainer);
Jorim Jaggi73f88202017-01-12 13:54:40 +0100151 return;
152 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800153
Jorim Jaggid8665f22018-04-10 00:34:24 +0200154 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting "
155 + AppWindowContainerController.this + ": startingData="
156 + container.startingData);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800157
Jorim Jaggid8665f22018-04-10 00:34:24 +0200158 StartingSurface surface = null;
159 try {
160 surface = startingData.createStartingSurface(container);
161 } catch (Exception e) {
162 Slog.w(TAG_WM, "Exception when adding starting window", e);
163 }
164 if (surface != null) {
165 boolean abort = false;
166 synchronized (mWindowMap) {
167 // If the window was successfully added, then
168 // we need to remove it.
169 if (container.removed || container.startingData == null) {
170 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
171 "Aborted starting " + container
172 + ": removed=" + container.removed
173 + " startingData=" + container.startingData);
174 container.startingWindow = null;
175 container.startingData = null;
176 abort = true;
177 } else {
178 container.startingSurface = surface;
179 }
180 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM,
181 "Added starting " + mContainer
182 + ": startingWindow="
183 + container.startingWindow + " startingView="
184 + container.startingSurface);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800185 }
Jorim Jaggid8665f22018-04-10 00:34:24 +0200186 if (abort) {
187 surface.remove();
188 }
189 } else if (DEBUG_STARTING_WINDOW) {
190 Slog.v(TAG_WM, "Surface returned was null: " + mContainer);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800191 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800192 }
193 };
194
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800195 public AppWindowContainerController(TaskWindowContainerController taskController,
196 IApplicationToken token, AppWindowContainerListener listener, int index,
197 int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges,
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800198 boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
Bryce Leef3c6a472017-11-14 14:53:06 -0800199 int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800200 this(taskController, token, listener, index, requestedOrientation, fullscreen,
201 showForAllUsers,
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800202 configChanges, voiceInteraction, launchTaskBehind, alwaysFocusable,
203 targetSdkVersion, rotationAnimationHint, inputDispatchingTimeoutNanos,
Bryce Leef3c6a472017-11-14 14:53:06 -0800204 WindowManagerService.getInstance());
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800205 }
206
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800207 public AppWindowContainerController(TaskWindowContainerController taskController,
208 IApplicationToken token, AppWindowContainerListener listener, int index,
209 int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges,
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800210 boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
211 int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos,
Bryce Leef3c6a472017-11-14 14:53:06 -0800212 WindowManagerService service) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800213 super(listener, service);
Sudheer Shankac766db02017-06-12 10:37:29 -0700214 mHandler = new H(service.mH.getLooper());
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800215 mToken = token;
216 synchronized(mWindowMap) {
217 AppWindowToken atoken = mRoot.getAppWindowToken(mToken.asBinder());
218 if (atoken != null) {
219 // TODO: Should this throw an exception instead?
220 Slog.w(TAG_WM, "Attempted to add existing app token: " + mToken);
221 return;
222 }
223
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800224 final Task task = taskController.mContainer;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800225 if (task == null) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800226 throw new IllegalArgumentException("AppWindowContainerController: invalid "
227 + " controller=" + taskController);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800228 }
229
Winson Chung30480042017-01-26 10:55:34 -0800230 atoken = createAppWindow(mService, token, voiceInteraction, task.getDisplayContent(),
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800231 inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdkVersion,
232 requestedOrientation, rotationAnimationHint, configChanges, launchTaskBehind,
Bryce Leef3c6a472017-11-14 14:53:06 -0800233 alwaysFocusable, this);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800234 if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800235 + " controller=" + taskController + " at " + index);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800236 task.addChild(atoken, index);
237 }
238 }
239
Winson Chung30480042017-01-26 10:55:34 -0800240 @VisibleForTesting
241 AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
242 boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
243 boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
244 int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
Bryce Leef3c6a472017-11-14 14:53:06 -0800245 boolean alwaysFocusable, AppWindowContainerController controller) {
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100246 return new AppWindowToken(service, token, voiceInteraction, dc,
Winson Chung30480042017-01-26 10:55:34 -0800247 inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation,
248 rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
Bryce Leef3c6a472017-11-14 14:53:06 -0800249 controller);
Winson Chung30480042017-01-26 10:55:34 -0800250 }
251
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800252 public void removeContainer(int displayId) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800253 synchronized(mWindowMap) {
254 final DisplayContent dc = mRoot.getDisplayContent(displayId);
255 if (dc == null) {
256 Slog.w(TAG_WM, "removeAppToken: Attempted to remove binder token: "
257 + mToken + " from non-existing displayId=" + displayId);
258 return;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800259 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800260 dc.removeAppToken(mToken.asBinder());
261 super.removeContainer();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800262 }
263 }
264
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800265 @Override
266 public void removeContainer() {
267 throw new UnsupportedOperationException("Use removeContainer(displayId) instead.");
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800268 }
269
Winson Chung30480042017-01-26 10:55:34 -0800270 public void reparent(TaskWindowContainerController taskController, int position) {
271 synchronized (mWindowMap) {
272 if (DEBUG_ADD_REMOVE) Slog.i(TAG_WM, "reparent: moving app token=" + mToken
273 + " to task=" + taskController + " at " + position);
274 if (mContainer == null) {
275 if (DEBUG_ADD_REMOVE) Slog.i(TAG_WM,
276 "reparent: could not find app token=" + mToken);
277 return;
278 }
279 final Task task = taskController.mContainer;
280 if (task == null) {
281 throw new IllegalArgumentException("reparent: could not find task="
282 + taskController);
283 }
284 mContainer.reparent(task, position);
285 mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
286 }
287 }
288
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800289 public Configuration setOrientation(int requestedOrientation, int displayId,
290 Configuration displayConfig, boolean freezeScreenIfNeeded) {
291 synchronized(mWindowMap) {
292 if (mContainer == null) {
293 Slog.w(TAG_WM,
294 "Attempted to set orientation of non-existing app token: " + mToken);
295 return null;
296 }
297
298 mContainer.setOrientation(requestedOrientation);
299
300 final IBinder binder = freezeScreenIfNeeded ? mToken.asBinder() : null;
301 return mService.updateOrientationFromAppTokens(displayConfig, binder, displayId);
302
303 }
304 }
305
306 public int getOrientation() {
307 synchronized(mWindowMap) {
308 if (mContainer == null) {
309 return SCREEN_ORIENTATION_UNSPECIFIED;
310 }
311
312 return mContainer.getOrientationIgnoreVisibility();
313 }
314 }
315
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100316 public void setDisablePreviewScreenshots(boolean disable) {
317 synchronized (mWindowMap) {
318 if (mContainer == null) {
319 Slog.w(TAG_WM, "Attempted to set disable screenshots of non-existing app"
320 + " token: " + mToken);
321 return;
322 }
Jorim Jaggid635a4a2017-05-03 15:21:26 +0200323 mContainer.setDisablePreviewScreenshots(disable);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100324 }
325 }
326
Tim Murray68ed8442017-08-29 23:21:27 +0000327 public void setVisibility(boolean visible, boolean deferHidingClient) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800328 synchronized(mWindowMap) {
329 if (mContainer == null) {
330 Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
331 + mToken);
332 return;
333 }
334
335 final AppWindowToken wtoken = mContainer;
336
Wale Ogunwale0c20ee32017-05-23 10:34:48 -0700337 // Don't set visibility to false if we were already not visible. This prevents WM from
338 // adding the app to the closing app list which doesn't make sense for something that is
339 // already not visible. However, set visibility to true even if we are already visible.
340 // This makes sure the app is added to the opening apps list so that the right
341 // transition can be selected.
342 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
343 // concept of setting visibility...
344 if (!visible && wtoken.hiddenRequested) {
345
346 if (!deferHidingClient && wtoken.mDeferHidingClient) {
347 // We previously deferred telling the client to hide itself when visibility was
348 // initially set to false. Now we would like it to hide, so go ahead and set it.
349 wtoken.mDeferHidingClient = deferHidingClient;
350 wtoken.setClientHidden(true);
351 }
352 return;
353 }
354
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800355 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG_WM, "setAppVisibility("
356 + mToken + ", visible=" + visible + "): " + mService.mAppTransition
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200357 + " hidden=" + wtoken.isHidden() + " hiddenRequested="
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800358 + wtoken.hiddenRequested + " Callers=" + Debug.getCallers(6));
359
360 mService.mOpeningApps.remove(wtoken);
361 mService.mClosingApps.remove(wtoken);
362 wtoken.waitingToShow = false;
363 wtoken.hiddenRequested = !visible;
Wale Ogunwale89973222017-04-23 18:39:45 -0700364 wtoken.mDeferHidingClient = deferHidingClient;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800365
366 if (!visible) {
367 // If the app is dead while it was visible, we kept its dead window on screen.
368 // Now that the app is going invisible, we can remove it. It will be restarted
369 // if made visible again.
370 wtoken.removeDeadWindows();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800371 } else {
372 if (!mService.mAppTransition.isTransitionSet()
373 && mService.mAppTransition.isReady()) {
374 // Add the app mOpeningApps if transition is unset but ready. This means
375 // we're doing a screen freeze, and the unfreeze will wait for all opening
376 // apps to be ready.
377 mService.mOpeningApps.add(wtoken);
378 }
379 wtoken.startingMoved = false;
380 // If the token is currently hidden (should be the common case), or has been
381 // stopped, then we need to set up to wait for its windows to be ready.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200382 if (wtoken.isHidden() || wtoken.mAppStopped) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800383 wtoken.clearAllDrawn();
384
385 // If the app was already visible, don't reset the waitingToShow state.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200386 if (wtoken.isHidden()) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800387 wtoken.waitingToShow = true;
388 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800389 }
Jorim Jaggi067b5bf2018-02-23 17:42:39 +0100390
391 // In the case where we are making an app visible but holding off for a transition,
392 // we still need to tell the client to make its windows visible so they get drawn.
393 // Otherwise, we will wait on performing the transition until all windows have been
394 // drawn, they never will be, and we are sad.
395 wtoken.setClientHidden(false);
396
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800397 wtoken.requestUpdateWallpaperIfNeeded();
398
399 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + wtoken);
400 wtoken.mAppStopped = false;
Jorim Jaggi60f9c972018-02-01 19:21:07 +0100401
402 mContainer.transferStartingWindowFromHiddenAboveTokenIfNeeded();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800403 }
404
405 // If we are preparing an app transition, then delay changing
406 // the visibility of this token until we execute that transition.
David Stevensf62360c2017-03-16 19:00:20 -0700407 if (wtoken.okToAnimate() && mService.mAppTransition.isTransitionSet()) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800408 wtoken.inPendingTransaction = true;
409 if (visible) {
410 mService.mOpeningApps.add(wtoken);
411 wtoken.mEnteringAnimation = true;
412 } else {
413 mService.mClosingApps.add(wtoken);
414 wtoken.mEnteringAnimation = false;
415 }
416 if (mService.mAppTransition.getAppTransition()
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100417 == WindowManager.TRANSIT_TASK_OPEN_BEHIND) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800418 // We're launchingBehind, add the launching activity to mOpeningApps.
419 final WindowState win =
420 mService.getDefaultDisplayContentLocked().findFocusedWindow();
421 if (win != null) {
422 final AppWindowToken focusedToken = win.mAppToken;
423 if (focusedToken != null) {
424 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
425 + " adding " + focusedToken + " to mOpeningApps");
426 // Force animation to be loaded.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200427 focusedToken.setHidden(true);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800428 mService.mOpeningApps.add(focusedToken);
429 }
430 }
431 }
432 return;
433 }
434
435 wtoken.setVisibility(null, visible, TRANSIT_UNSET, true, wtoken.mVoiceInteraction);
436 wtoken.updateReportedVisibilityLocked();
437 }
438 }
439
440 /**
441 * Notifies that we launched an app that might be visible or not visible depending on what kind
442 * of Keyguard flags it's going to set on its windows.
443 */
444 public void notifyUnknownVisibilityLaunched() {
445 synchronized(mWindowMap) {
446 if (mContainer != null) {
447 mService.mUnknownAppVisibilityController.notifyLaunched(mContainer);
448 }
449 }
450 }
451
452 public boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
453 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
Jorim Jaggibae01b12017-04-11 16:29:10 -0700454 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
Jorim Jaggi42befc62017-06-13 11:54:04 -0700455 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800456 synchronized(mWindowMap) {
457 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "setAppStartingWindow: token=" + mToken
Jorim Jaggie4b0f282017-05-17 15:10:29 +0200458 + " pkg=" + pkg + " transferFrom=" + transferFrom + " newTask=" + newTask
459 + " taskSwitch=" + taskSwitch + " processRunning=" + processRunning
460 + " allowTaskSnapshot=" + allowTaskSnapshot);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800461
462 if (mContainer == null) {
463 Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + mToken);
464 return false;
465 }
466
467 // If the display is frozen, we won't do anything until the actual window is
468 // displayed so there is no reason to put in the starting window.
David Stevensf62360c2017-03-16 19:00:20 -0700469 if (!mContainer.okToDisplay()) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800470 return false;
471 }
472
473 if (mContainer.startingData != null) {
474 return false;
475 }
476
Wale Ogunwale4ba3e832017-04-20 16:45:13 -0700477 final WindowState mainWin = mContainer.findMainWindow();
Jorim Jaggie6b1b3b2017-07-24 16:44:18 +0200478 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
479 // App already has a visible window...why would you want a starting window?
Wale Ogunwale4ba3e832017-04-20 16:45:13 -0700480 return false;
481 }
482
Jorim Jaggi42befc62017-06-13 11:54:04 -0700483 final TaskSnapshot snapshot = mService.mTaskSnapshotController.getSnapshot(
484 mContainer.getTask().mTaskId, mContainer.getTask().mUserId,
485 false /* restoreFromDisk */, false /* reducedResolution */);
Jorim Jaggibae01b12017-04-11 16:29:10 -0700486 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
Jorim Jaggi42befc62017-06-13 11:54:04 -0700487 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800488
489 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
Jorim Jaggi42befc62017-06-13 11:54:04 -0700490 return createSnapshot(snapshot);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800491 }
492
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800493 // If this is a translucent window, then don't show a starting window -- the current
494 // effect (a full-screen opaque starting window that fades away to the real contents
495 // when it is ready) does not work for this.
496 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Checking theme of starting window: 0x"
497 + Integer.toHexString(theme));
498 if (theme != 0) {
499 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
500 com.android.internal.R.styleable.Window, mService.mCurrentUserId);
501 if (ent == null) {
502 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
503 // see that.
504 return false;
505 }
506 final boolean windowIsTranslucent = ent.array.getBoolean(
507 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
508 final boolean windowIsFloating = ent.array.getBoolean(
509 com.android.internal.R.styleable.Window_windowIsFloating, false);
510 final boolean windowShowWallpaper = ent.array.getBoolean(
511 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
512 final boolean windowDisableStarting = ent.array.getBoolean(
513 com.android.internal.R.styleable.Window_windowDisablePreview, false);
514 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Translucent=" + windowIsTranslucent
515 + " Floating=" + windowIsFloating
516 + " ShowWallpaper=" + windowShowWallpaper);
517 if (windowIsTranslucent) {
518 return false;
519 }
520 if (windowIsFloating || windowDisableStarting) {
521 return false;
522 }
523 if (windowShowWallpaper) {
524 if (mContainer.getDisplayContent().mWallpaperController.getWallpaperTarget()
525 == null) {
526 // If this theme is requesting a wallpaper, and the wallpaper
527 // is not currently visible, then this effectively serves as
528 // an opaque window and our starting window transition animation
529 // can still work. We just need to make sure the starting window
530 // is also showing the wallpaper.
531 windowFlags |= FLAG_SHOW_WALLPAPER;
532 } else {
533 return false;
534 }
535 }
536 }
537
538 if (mContainer.transferStartingWindow(transferFrom)) {
539 return true;
540 }
541
Jorim Jaggi02886a82016-12-06 09:10:06 -0800542 // There is no existing starting window, and we don't want to create a splash screen, so
543 // that's it!
544 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800545 return false;
546 }
547
Jorim Jaggie4b0f282017-05-17 15:10:29 +0200548 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
Jorim Jaggie09fc6b2017-01-19 15:33:36 +0100549 mContainer.startingData = new SplashScreenStartingData(mService, pkg, theme,
Jorim Jaggi02886a82016-12-06 09:10:06 -0800550 compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
551 mContainer.getMergedOverrideConfiguration());
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800552 scheduleAddStartingWindow();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800553 }
554 return true;
555 }
556
Jorim Jaggibae01b12017-04-11 16:29:10 -0700557 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
Jorim Jaggi42befc62017-06-13 11:54:04 -0700558 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
559 TaskSnapshot snapshot) {
Matthew Ng606dd802017-06-05 14:06:32 -0700560 if (mService.mAppTransition.getAppTransition() == TRANSIT_DOCK_TASK_FROM_RECENTS) {
561 // TODO(b/34099271): Remove this statement to add back the starting window and figure
562 // out why it causes flickering, the starting window appears over the thumbnail while
563 // the docked from recents transition occurs
564 return STARTING_WINDOW_TYPE_NONE;
565 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800566 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
Jorim Jaggibae01b12017-04-11 16:29:10 -0700567 } else if (taskSwitch && allowTaskSnapshot) {
Jorim Jaggi42befc62017-06-13 11:54:04 -0700568 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
Jorim Jaggi1dda7a62017-06-28 14:40:27 -0400569 : snapshotOrientationSameAsTask(snapshot) || fromRecents
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700570 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800571 } else {
572 return STARTING_WINDOW_TYPE_NONE;
573 }
574 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800575
Jorim Jaggi02886a82016-12-06 09:10:06 -0800576 void scheduleAddStartingWindow() {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800577 // Note: we really want to do sendMessageAtFrontOfQueue() because we
578 // want to process the message ASAP, before any other queued
579 // messages.
Jorim Jaggid8665f22018-04-10 00:34:24 +0200580 if (!mService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
581 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING");
582 mService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
583 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800584 }
585
Jorim Jaggi42befc62017-06-13 11:54:04 -0700586 private boolean createSnapshot(TaskSnapshot snapshot) {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800587 if (snapshot == null) {
588 return false;
589 }
590
Jorim Jaggie4b0f282017-05-17 15:10:29 +0200591 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200592 mContainer.startingData = new SnapshotStartingData(mService, snapshot);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800593 scheduleAddStartingWindow();
594 return true;
595 }
596
Jorim Jaggi1dda7a62017-06-28 14:40:27 -0400597 private boolean snapshotOrientationSameAsTask(TaskSnapshot snapshot) {
Jorim Jaggi42befc62017-06-13 11:54:04 -0700598 if (snapshot == null) {
599 return false;
600 }
Jorim Jaggi1dda7a62017-06-28 14:40:27 -0400601 return mContainer.getTask().getConfiguration().orientation == snapshot.getOrientation();
Jorim Jaggi42befc62017-06-13 11:54:04 -0700602 }
603
Jorim Jaggi19be6052017-08-03 18:33:43 +0200604 public void removeStartingWindow() {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800605 synchronized (mWindowMap) {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800606 if (mContainer.startingWindow == null) {
607 if (mContainer.startingData != null) {
608 // Starting window has not been added yet, but it is scheduled to be added.
609 // Go ahead and cancel the request.
610 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
611 "Clearing startingData for token=" + mContainer);
612 mContainer.startingData = null;
613 }
614 return;
615 }
616
Seigo Nonaka82871bd2017-07-17 20:22:44 -0700617 final StartingSurface surface;
618 if (mContainer.startingData != null) {
619 surface = mContainer.startingSurface;
620 mContainer.startingData = null;
621 mContainer.startingSurface = null;
622 mContainer.startingWindow = null;
623 mContainer.startingDisplayed = false;
Seigo Nonakaeafe7372017-08-16 12:39:49 -0700624 if (surface == null) {
625 if (DEBUG_STARTING_WINDOW) {
626 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
627 + "remove");
628 }
629 return;
Seigo Nonaka82871bd2017-07-17 20:22:44 -0700630 }
631 } else {
632 if (DEBUG_STARTING_WINDOW) {
633 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
634 + mContainer);
635 }
636 return;
637 }
638
Jorim Jaggie4b0f282017-05-17 15:10:29 +0200639 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Schedule remove starting " + mContainer
Seigo Nonaka82871bd2017-07-17 20:22:44 -0700640 + " startingWindow=" + mContainer.startingWindow
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +0100641 + " startingView=" + mContainer.startingSurface
642 + " Callers=" + Debug.getCallers(5));
Jorim Jaggia3382192017-07-18 14:33:21 +0200643
644 // Use the same thread to remove the window as we used to add it, as otherwise we end up
645 // with things in the view hierarchy being called from different threads.
Jorim Jaggi8829cf12017-09-05 12:28:52 +0200646 mService.mAnimationHandler.post(() -> {
Seigo Nonaka82871bd2017-07-17 20:22:44 -0700647 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
648 try {
649 surface.remove();
650 } catch (Exception e) {
651 Slog.w(TAG_WM, "Exception when removing starting window", e);
652 }
653 });
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800654 }
655 }
656
657 public void pauseKeyDispatching() {
658 synchronized (mWindowMap) {
659 if (mContainer != null) {
660 mService.mInputMonitor.pauseDispatchingLw(mContainer);
661 }
662 }
663 }
664
665 public void resumeKeyDispatching() {
666 synchronized (mWindowMap) {
667 if (mContainer != null) {
668 mService.mInputMonitor.resumeDispatchingLw(mContainer);
669 }
670 }
671 }
672
Jorim Jaggibae01b12017-04-11 16:29:10 -0700673 public void notifyAppResumed(boolean wasStopped) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800674 synchronized(mWindowMap) {
675 if (mContainer == null) {
676 Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: " + mToken);
677 return;
678 }
Jorim Jaggibae01b12017-04-11 16:29:10 -0700679 mContainer.notifyAppResumed(wasStopped);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800680 }
681 }
682
Robert Carr29daa922018-04-27 11:56:48 -0700683 public void notifyAppStopping() {
684 synchronized(mWindowMap) {
685 if (mContainer == null) {
686 Slog.w(TAG_WM, "Attempted to notify stopping on non-existing app token: "
687 + mToken);
688 return;
689 }
690 mContainer.detachChildren();
691 }
692 }
693
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800694 public void notifyAppStopped() {
695 synchronized(mWindowMap) {
696 if (mContainer == null) {
697 Slog.w(TAG_WM, "Attempted to notify stopped of non-existing app token: "
698 + mToken);
699 return;
700 }
701 mContainer.notifyAppStopped();
702 }
703 }
704
705 public void startFreezingScreen(int configChanges) {
706 synchronized(mWindowMap) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800707 if (mContainer == null) {
708 Slog.w(TAG_WM,
709 "Attempted to freeze screen with non-existing app token: " + mContainer);
710 return;
711 }
David Stevensf62360c2017-03-16 19:00:20 -0700712
713 if (configChanges == 0 && mContainer.okToDisplay()) {
714 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + mToken);
715 return;
716 }
717
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800718 mContainer.startFreezingScreen();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800719 }
720 }
721
722 public void stopFreezingScreen(boolean force) {
723 synchronized(mWindowMap) {
724 if (mContainer == null) {
725 return;
726 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800727 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + mToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000728 + mContainer.isHidden() + " freezing=" + mContainer.isFreezingScreen());
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800729 mContainer.stopFreezingScreen(true, force);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800730 }
731 }
732
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100733 public void registerRemoteAnimations(RemoteAnimationDefinition definition) {
734 synchronized (mWindowMap) {
735 if (mContainer == null) {
736 Slog.w(TAG_WM, "Attempted to register remote animations with non-existing app"
737 + " token: " + mToken);
738 return;
739 }
740 mContainer.registerRemoteAnimations(definition);
741 }
742 }
743
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800744 void reportStartingWindowDrawn() {
Sudheer Shankac766db02017-06-12 10:37:29 -0700745 mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_STARTING_WINDOW_DRAWN));
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800746 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800747
748 void reportWindowsDrawn() {
Sudheer Shankac766db02017-06-12 10:37:29 -0700749 mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_WINDOWS_DRAWN));
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800750 }
751
Vishnu Nairc1d2ff62018-11-08 16:50:12 -0800752 void reportWindowsNotDrawn() {
753 mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_WINDOWS_NOTDRAWN));
754 }
755
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800756 void reportWindowsVisible() {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800757 mHandler.post(mOnWindowsVisible);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800758 }
759
760 void reportWindowsGone() {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800761 mHandler.post(mOnWindowsGone);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800762 }
763
764 /** Calls directly into activity manager so window manager lock shouldn't held. */
Wale Ogunwale7402ddf2017-03-29 12:58:24 -0700765 boolean keyDispatchingTimedOut(String reason, int windowPid) {
766 return mListener != null && mListener.keyDispatchingTimedOut(reason, windowPid);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800767 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800768
chaviw4ad54912018-05-30 11:05:44 -0700769 /**
770 * Notifies AWT that this app is waiting to pause in order to determine if it will enter PIP.
771 * This information helps AWT know that the app is in the process of pausing before it gets the
772 * signal on the WM side.
773 */
774 public void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
775 synchronized (mWindowMap) {
776 if (mContainer == null) {
777 return;
778 }
779
780 mContainer.setWillCloseOrEnterPip(willCloseOrEnterPip);
781 }
782 }
783
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800784 @Override
785 public String toString() {
Wale Ogunwale9c64cb62017-04-12 13:39:59 -0700786 return "AppWindowContainerController{"
787 + " token=" + mToken
788 + " mContainer=" + mContainer
789 + " mListener=" + mListener
790 + "}";
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800791 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800792}