blob: c03c48772d481f30b9467493c89cc1cd58fe8b3e [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;
21import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
22import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
23import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
24import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
25import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
26import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
27import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
28import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
29import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080030
Jorim Jaggie2c77f92016-12-29 14:57:22 +010031import android.app.ActivityManager.TaskSnapshot;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080032import android.content.res.CompatibilityInfo;
33import android.content.res.Configuration;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080034import android.graphics.Bitmap;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -070035import android.graphics.Rect;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080036import android.os.Debug;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080037import android.os.Handler;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080038import android.os.IBinder;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -070039import android.os.Looper;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080040import android.os.Trace;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080041import android.util.Slog;
42import android.view.IApplicationToken;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080043import android.view.WindowManagerPolicy.StartingSurface;
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;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080047/**
48 * Controller for the app window token container. This is created by activity manager to link
49 * activity records to the app window token container they use in window manager.
50 *
51 * Test class: {@link AppWindowContainerControllerTests}
52 */
53public class AppWindowContainerController
54 extends WindowContainerController<AppWindowToken, AppWindowContainerListener> {
55
Jorim Jaggi02886a82016-12-06 09:10:06 -080056 private static final int STARTING_WINDOW_TYPE_NONE = 0;
57 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
58 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
59
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080060 private final IApplicationToken mToken;
Jorim Jaggi9bafc712017-01-19 17:28:30 +010061 private final Handler mHandler;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080062
Jorim Jaggi3878ca32017-02-02 17:13:05 -080063 private final Runnable mOnStartingWindowDrawn = () -> {
64 if (mListener == null) {
65 return;
66 }
67 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting drawn in "
68 + AppWindowContainerController.this.mToken);
69 mListener.onStartingWindowDrawn();
70 };
71
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080072 private final Runnable mOnWindowsDrawn = () -> {
73 if (mListener == null) {
74 return;
75 }
76 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting drawn in "
77 + AppWindowContainerController.this.mToken);
78 mListener.onWindowsDrawn();
79 };
80
81 private final Runnable mOnWindowsVisible = () -> {
82 if (mListener == null) {
83 return;
84 }
85 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting visible in "
86 + AppWindowContainerController.this.mToken);
87 mListener.onWindowsVisible();
88 };
89
90 private final Runnable mOnWindowsGone = () -> {
91 if (mListener == null) {
92 return;
93 }
94 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in "
95 + AppWindowContainerController.this.mToken);
96 mListener.onWindowsGone();
97 };
98
Jorim Jaggi02886a82016-12-06 09:10:06 -080099 private final Runnable mRemoveStartingWindow = () -> {
100 StartingSurface surface = null;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800101 synchronized (mWindowMap) {
102 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Remove starting " + mContainer
103 + ": startingWindow=" + mContainer.startingWindow
104 + " startingView=" + mContainer.startingSurface);
Jorim Jaggi553cec62017-01-13 13:00:42 +0100105 if (mContainer == null) {
106 return;
107 }
Jorim Jaggi02886a82016-12-06 09:10:06 -0800108 if (mContainer.startingWindow != null) {
109 surface = mContainer.startingSurface;
Jorim Jaggi02886a82016-12-06 09:10:06 -0800110 mContainer.startingData = null;
111 mContainer.startingSurface = null;
112 mContainer.startingWindow = null;
113 mContainer.startingDisplayed = false;
114 }
115 }
Jorim Jaggie09fc6b2017-01-19 15:33:36 +0100116 if (surface != null) {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800117 try {
118 surface.remove();
119 } catch (Exception e) {
120 Slog.w(TAG_WM, "Exception when removing starting window", e);
121 }
122 }
123 };
124
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800125 private final Runnable mAddStartingWindow = () -> {
126 final StartingData startingData;
Jorim Jaggie09fc6b2017-01-19 15:33:36 +0100127 final AppWindowToken container;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800128
129 synchronized (mWindowMap) {
Jorim Jaggi73f88202017-01-12 13:54:40 +0100130 if (mContainer == null) {
131 return;
132 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800133 startingData = mContainer.startingData;
Jorim Jaggie09fc6b2017-01-19 15:33:36 +0100134 container = mContainer;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800135 }
136
137 if (startingData == null) {
138 // Animation has been canceled... do nothing.
139 return;
140 }
141
142 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting "
Jorim Jaggie09fc6b2017-01-19 15:33:36 +0100143 + this + ": startingData=" + container.startingData);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800144
Jorim Jaggi02886a82016-12-06 09:10:06 -0800145 StartingSurface surface = null;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800146 try {
Jorim Jaggie09fc6b2017-01-19 15:33:36 +0100147 surface = startingData.createStartingSurface(container);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800148 } catch (Exception e) {
149 Slog.w(TAG_WM, "Exception when adding starting window", e);
150 }
Jorim Jaggi02886a82016-12-06 09:10:06 -0800151 if (surface != null) {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800152 boolean abort = false;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800153 synchronized(mWindowMap) {
Jorim Jaggie09fc6b2017-01-19 15:33:36 +0100154 if (container.removed || container.startingData == null) {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800155 // If the window was successfully added, then
156 // we need to remove it.
Jorim Jaggie09fc6b2017-01-19 15:33:36 +0100157 if (container.startingWindow != null) {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800158 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
Jorim Jaggie09fc6b2017-01-19 15:33:36 +0100159 "Aborted starting " + container
160 + ": removed=" + container.removed
161 + " startingData=" + container.startingData);
162 container.startingWindow = null;
163 container.startingData = null;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800164 abort = true;
165 }
166 } else {
Jorim Jaggie09fc6b2017-01-19 15:33:36 +0100167 container.startingSurface = surface;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800168 }
169 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM,
170 "Added starting " + mContainer
171 + ": startingWindow="
Jorim Jaggie09fc6b2017-01-19 15:33:36 +0100172 + container.startingWindow + " startingView="
173 + container.startingSurface);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800174 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800175 if (abort) {
Jorim Jaggie09fc6b2017-01-19 15:33:36 +0100176 surface.remove();
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800177 }
178 }
179 };
180
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800181 public AppWindowContainerController(TaskWindowContainerController taskController,
182 IApplicationToken token, AppWindowContainerListener listener, int index,
183 int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges,
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800184 boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700185 int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos,
186 Configuration overrideConfig, Rect bounds) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800187 this(taskController, token, listener, index, requestedOrientation, fullscreen,
188 showForAllUsers,
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800189 configChanges, voiceInteraction, launchTaskBehind, alwaysFocusable,
190 targetSdkVersion, rotationAnimationHint, inputDispatchingTimeoutNanos,
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700191 WindowManagerService.getInstance(), overrideConfig, bounds);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800192 }
193
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800194 public AppWindowContainerController(TaskWindowContainerController taskController,
195 IApplicationToken token, AppWindowContainerListener listener, int index,
196 int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges,
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800197 boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
198 int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos,
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700199 WindowManagerService service, Configuration overrideConfig, Rect bounds) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800200 super(listener, service);
Jorim Jaggi9bafc712017-01-19 17:28:30 +0100201 mHandler = new Handler(service.mH.getLooper());
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800202 mToken = token;
203 synchronized(mWindowMap) {
204 AppWindowToken atoken = mRoot.getAppWindowToken(mToken.asBinder());
205 if (atoken != null) {
206 // TODO: Should this throw an exception instead?
207 Slog.w(TAG_WM, "Attempted to add existing app token: " + mToken);
208 return;
209 }
210
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800211 final Task task = taskController.mContainer;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800212 if (task == null) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800213 throw new IllegalArgumentException("AppWindowContainerController: invalid "
214 + " controller=" + taskController);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800215 }
216
Winson Chung30480042017-01-26 10:55:34 -0800217 atoken = createAppWindow(mService, token, voiceInteraction, task.getDisplayContent(),
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800218 inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdkVersion,
219 requestedOrientation, rotationAnimationHint, configChanges, launchTaskBehind,
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700220 alwaysFocusable, this, overrideConfig, bounds);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800221 if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800222 + " controller=" + taskController + " at " + index);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800223 task.addChild(atoken, index);
224 }
225 }
226
Winson Chung30480042017-01-26 10:55:34 -0800227 @VisibleForTesting
228 AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
229 boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
230 boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
231 int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700232 boolean alwaysFocusable, AppWindowContainerController controller,
233 Configuration overrideConfig, Rect bounds) {
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100234 return new AppWindowToken(service, token, voiceInteraction, dc,
Winson Chung30480042017-01-26 10:55:34 -0800235 inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation,
236 rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700237 controller, overrideConfig, bounds);
Winson Chung30480042017-01-26 10:55:34 -0800238 }
239
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800240 public void removeContainer(int displayId) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800241 synchronized(mWindowMap) {
242 final DisplayContent dc = mRoot.getDisplayContent(displayId);
243 if (dc == null) {
244 Slog.w(TAG_WM, "removeAppToken: Attempted to remove binder token: "
245 + mToken + " from non-existing displayId=" + displayId);
246 return;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800247 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800248 dc.removeAppToken(mToken.asBinder());
249 super.removeContainer();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800250 }
251 }
252
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800253 @Override
254 public void removeContainer() {
255 throw new UnsupportedOperationException("Use removeContainer(displayId) instead.");
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800256 }
257
Winson Chung30480042017-01-26 10:55:34 -0800258 public void reparent(TaskWindowContainerController taskController, int position) {
259 synchronized (mWindowMap) {
260 if (DEBUG_ADD_REMOVE) Slog.i(TAG_WM, "reparent: moving app token=" + mToken
261 + " to task=" + taskController + " at " + position);
262 if (mContainer == null) {
263 if (DEBUG_ADD_REMOVE) Slog.i(TAG_WM,
264 "reparent: could not find app token=" + mToken);
265 return;
266 }
267 final Task task = taskController.mContainer;
268 if (task == null) {
269 throw new IllegalArgumentException("reparent: could not find task="
270 + taskController);
271 }
272 mContainer.reparent(task, position);
273 mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
274 }
275 }
276
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800277 public Configuration setOrientation(int requestedOrientation, int displayId,
278 Configuration displayConfig, boolean freezeScreenIfNeeded) {
279 synchronized(mWindowMap) {
280 if (mContainer == null) {
281 Slog.w(TAG_WM,
282 "Attempted to set orientation of non-existing app token: " + mToken);
283 return null;
284 }
285
286 mContainer.setOrientation(requestedOrientation);
287
288 final IBinder binder = freezeScreenIfNeeded ? mToken.asBinder() : null;
289 return mService.updateOrientationFromAppTokens(displayConfig, binder, displayId);
290
291 }
292 }
293
294 public int getOrientation() {
295 synchronized(mWindowMap) {
296 if (mContainer == null) {
297 return SCREEN_ORIENTATION_UNSPECIFIED;
298 }
299
300 return mContainer.getOrientationIgnoreVisibility();
301 }
302 }
303
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700304 // TODO(b/36505427): Maybe move to WindowContainerController so other sub-classes can use it as
305 // a generic way to set override config. Need to untangle current ways the override config is
306 // currently set for tasks and displays before we are doing that though.
307 public void onOverrideConfigurationChanged(Configuration overrideConfiguration, Rect bounds) {
308 synchronized(mWindowMap) {
309 if (mContainer != null) {
310 mContainer.onOverrideConfigurationChanged(overrideConfiguration, bounds);
311 }
312 }
313 }
314
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100315 public void setDisablePreviewScreenshots(boolean disable) {
316 synchronized (mWindowMap) {
317 if (mContainer == null) {
318 Slog.w(TAG_WM, "Attempted to set disable screenshots of non-existing app"
319 + " token: " + mToken);
320 return;
321 }
322 mContainer.setDisablePreviewSnapshots(disable);
323 }
324 }
325
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800326 public void setVisibility(boolean visible) {
327 synchronized(mWindowMap) {
328 if (mContainer == null) {
329 Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
330 + mToken);
331 return;
332 }
333
334 final AppWindowToken wtoken = mContainer;
335
336 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG_WM, "setAppVisibility("
337 + mToken + ", visible=" + visible + "): " + mService.mAppTransition
338 + " hidden=" + wtoken.hidden + " hiddenRequested="
339 + wtoken.hiddenRequested + " Callers=" + Debug.getCallers(6));
340
341 mService.mOpeningApps.remove(wtoken);
342 mService.mClosingApps.remove(wtoken);
343 wtoken.waitingToShow = false;
344 wtoken.hiddenRequested = !visible;
345
346 if (!visible) {
347 // If the app is dead while it was visible, we kept its dead window on screen.
348 // Now that the app is going invisible, we can remove it. It will be restarted
349 // if made visible again.
350 wtoken.removeDeadWindows();
351 wtoken.setVisibleBeforeClientHidden();
352 } else {
353 if (!mService.mAppTransition.isTransitionSet()
354 && mService.mAppTransition.isReady()) {
355 // Add the app mOpeningApps if transition is unset but ready. This means
356 // we're doing a screen freeze, and the unfreeze will wait for all opening
357 // apps to be ready.
358 mService.mOpeningApps.add(wtoken);
359 }
360 wtoken.startingMoved = false;
361 // If the token is currently hidden (should be the common case), or has been
362 // stopped, then we need to set up to wait for its windows to be ready.
363 if (wtoken.hidden || wtoken.mAppStopped) {
364 wtoken.clearAllDrawn();
365
366 // If the app was already visible, don't reset the waitingToShow state.
367 if (wtoken.hidden) {
368 wtoken.waitingToShow = true;
369 }
370
371 if (wtoken.clientHidden) {
372 // In the case where we are making an app visible
373 // but holding off for a transition, we still need
374 // to tell the client to make its windows visible so
375 // they get drawn. Otherwise, we will wait on
376 // performing the transition until all windows have
377 // been drawn, they never will be, and we are sad.
378 wtoken.clientHidden = false;
379 wtoken.sendAppVisibilityToClients();
380 }
381 }
382 wtoken.requestUpdateWallpaperIfNeeded();
383
384 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + wtoken);
385 wtoken.mAppStopped = false;
386 }
387
388 // If we are preparing an app transition, then delay changing
389 // the visibility of this token until we execute that transition.
390 if (mService.okToDisplay() && mService.mAppTransition.isTransitionSet()) {
391 // A dummy animation is a placeholder animation which informs others that an
392 // animation is going on (in this case an application transition). If the animation
393 // was transferred from another application/animator, no dummy animator should be
394 // created since an animation is already in progress.
395 if (wtoken.mAppAnimator.usingTransferredAnimation
396 && wtoken.mAppAnimator.animation == null) {
397 Slog.wtf(TAG_WM, "Will NOT set dummy animation on: " + wtoken
398 + ", using null transferred animation!");
399 }
400 if (!wtoken.mAppAnimator.usingTransferredAnimation &&
401 (!wtoken.startingDisplayed || mService.mSkipAppTransitionAnimation)) {
402 if (DEBUG_APP_TRANSITIONS) Slog.v(
403 TAG_WM, "Setting dummy animation on: " + wtoken);
404 wtoken.mAppAnimator.setDummyAnimation();
405 }
406 wtoken.inPendingTransaction = true;
407 if (visible) {
408 mService.mOpeningApps.add(wtoken);
409 wtoken.mEnteringAnimation = true;
410 } else {
411 mService.mClosingApps.add(wtoken);
412 wtoken.mEnteringAnimation = false;
413 }
414 if (mService.mAppTransition.getAppTransition()
415 == AppTransition.TRANSIT_TASK_OPEN_BEHIND) {
416 // We're launchingBehind, add the launching activity to mOpeningApps.
417 final WindowState win =
418 mService.getDefaultDisplayContentLocked().findFocusedWindow();
419 if (win != null) {
420 final AppWindowToken focusedToken = win.mAppToken;
421 if (focusedToken != null) {
422 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
423 + " adding " + focusedToken + " to mOpeningApps");
424 // Force animation to be loaded.
425 focusedToken.hidden = true;
426 mService.mOpeningApps.add(focusedToken);
427 }
428 }
429 }
430 return;
431 }
432
433 wtoken.setVisibility(null, visible, TRANSIT_UNSET, true, wtoken.mVoiceInteraction);
434 wtoken.updateReportedVisibilityLocked();
435 }
436 }
437
438 /**
439 * Notifies that we launched an app that might be visible or not visible depending on what kind
440 * of Keyguard flags it's going to set on its windows.
441 */
442 public void notifyUnknownVisibilityLaunched() {
443 synchronized(mWindowMap) {
444 if (mContainer != null) {
445 mService.mUnknownAppVisibilityController.notifyLaunched(mContainer);
446 }
447 }
448 }
449
450 public boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
451 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
Jorim Jaggi02886a82016-12-06 09:10:06 -0800452 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800453 synchronized(mWindowMap) {
454 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "setAppStartingWindow: token=" + mToken
455 + " pkg=" + pkg + " transferFrom=" + transferFrom);
456
457 if (mContainer == null) {
458 Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + mToken);
459 return false;
460 }
461
462 // If the display is frozen, we won't do anything until the actual window is
463 // displayed so there is no reason to put in the starting window.
464 if (!mService.okToDisplay()) {
465 return false;
466 }
467
468 if (mContainer.startingData != null) {
469 return false;
470 }
471
Jorim Jaggi02886a82016-12-06 09:10:06 -0800472 final int type = getStartingWindowType(newTask, taskSwitch, processRunning);
473
474 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
475 return createSnapshot();
476 }
477
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800478 // If this is a translucent window, then don't show a starting window -- the current
479 // effect (a full-screen opaque starting window that fades away to the real contents
480 // when it is ready) does not work for this.
481 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Checking theme of starting window: 0x"
482 + Integer.toHexString(theme));
483 if (theme != 0) {
484 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
485 com.android.internal.R.styleable.Window, mService.mCurrentUserId);
486 if (ent == null) {
487 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
488 // see that.
489 return false;
490 }
491 final boolean windowIsTranslucent = ent.array.getBoolean(
492 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
493 final boolean windowIsFloating = ent.array.getBoolean(
494 com.android.internal.R.styleable.Window_windowIsFloating, false);
495 final boolean windowShowWallpaper = ent.array.getBoolean(
496 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
497 final boolean windowDisableStarting = ent.array.getBoolean(
498 com.android.internal.R.styleable.Window_windowDisablePreview, false);
499 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Translucent=" + windowIsTranslucent
500 + " Floating=" + windowIsFloating
501 + " ShowWallpaper=" + windowShowWallpaper);
502 if (windowIsTranslucent) {
503 return false;
504 }
505 if (windowIsFloating || windowDisableStarting) {
506 return false;
507 }
508 if (windowShowWallpaper) {
509 if (mContainer.getDisplayContent().mWallpaperController.getWallpaperTarget()
510 == null) {
511 // If this theme is requesting a wallpaper, and the wallpaper
512 // is not currently visible, then this effectively serves as
513 // an opaque window and our starting window transition animation
514 // can still work. We just need to make sure the starting window
515 // is also showing the wallpaper.
516 windowFlags |= FLAG_SHOW_WALLPAPER;
517 } else {
518 return false;
519 }
520 }
521 }
522
523 if (mContainer.transferStartingWindow(transferFrom)) {
524 return true;
525 }
526
Jorim Jaggi02886a82016-12-06 09:10:06 -0800527 // There is no existing starting window, and we don't want to create a splash screen, so
528 // that's it!
529 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800530 return false;
531 }
532
533 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating StartingData");
Jorim Jaggie09fc6b2017-01-19 15:33:36 +0100534 mContainer.startingData = new SplashScreenStartingData(mService, pkg, theme,
Jorim Jaggi02886a82016-12-06 09:10:06 -0800535 compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
536 mContainer.getMergedOverrideConfiguration());
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800537 scheduleAddStartingWindow();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800538 }
539 return true;
540 }
541
Jorim Jaggi02886a82016-12-06 09:10:06 -0800542 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning) {
543 if (newTask || !processRunning) {
544 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
545 } else if (taskSwitch) {
546 return STARTING_WINDOW_TYPE_SNAPSHOT;
547 } else {
548 return STARTING_WINDOW_TYPE_NONE;
549 }
550 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800551
Jorim Jaggi02886a82016-12-06 09:10:06 -0800552 void scheduleAddStartingWindow() {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800553 // Note: we really want to do sendMessageAtFrontOfQueue() because we
554 // want to process the message ASAP, before any other queued
555 // messages.
556 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING");
Jorim Jaggied7993b2017-03-28 18:50:01 +0100557 mService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800558 }
559
Jorim Jaggi02886a82016-12-06 09:10:06 -0800560 private boolean createSnapshot() {
Jorim Jaggie2c77f92016-12-29 14:57:22 +0100561 final TaskSnapshot snapshot = mService.mTaskSnapshotController.getSnapshot(
Bryce Lee6d410262017-02-28 15:30:17 -0800562 mContainer.getTask().mTaskId, mContainer.getTask().mUserId,
Jorim Jaggi35e3f532017-03-17 17:06:50 +0100563 false /* restoreFromDisk */, false /* reducedResolution */);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800564
565 if (snapshot == null) {
566 return false;
567 }
568
Jorim Jaggi30d64f32017-04-07 16:33:17 +0200569 mContainer.startingData = new SnapshotStartingData(mService, snapshot);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800570 scheduleAddStartingWindow();
571 return true;
572 }
573
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800574 public void removeStartingWindow() {
575 synchronized (mWindowMap) {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800576 if (mHandler.hasCallbacks(mRemoveStartingWindow)) {
577 // Already scheduled.
578 return;
579 }
580
581 if (mContainer.startingWindow == null) {
582 if (mContainer.startingData != null) {
583 // Starting window has not been added yet, but it is scheduled to be added.
584 // Go ahead and cancel the request.
585 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
586 "Clearing startingData for token=" + mContainer);
587 mContainer.startingData = null;
588 }
589 return;
590 }
591
592 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, Debug.getCallers(1)
593 + ": Schedule remove starting " + mContainer
594 + " startingWindow=" + mContainer.startingWindow);
595 mHandler.post(mRemoveStartingWindow);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800596 }
597 }
598
599 public void pauseKeyDispatching() {
600 synchronized (mWindowMap) {
601 if (mContainer != null) {
602 mService.mInputMonitor.pauseDispatchingLw(mContainer);
603 }
604 }
605 }
606
607 public void resumeKeyDispatching() {
608 synchronized (mWindowMap) {
609 if (mContainer != null) {
610 mService.mInputMonitor.resumeDispatchingLw(mContainer);
611 }
612 }
613 }
614
615 public void notifyAppResumed(boolean wasStopped, boolean allowSavedSurface) {
616 synchronized(mWindowMap) {
617 if (mContainer == null) {
618 Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: " + mToken);
619 return;
620 }
621 mContainer.notifyAppResumed(wasStopped, allowSavedSurface);
622 }
623 }
624
625 public void notifyAppStopped() {
626 synchronized(mWindowMap) {
627 if (mContainer == null) {
628 Slog.w(TAG_WM, "Attempted to notify stopped of non-existing app token: "
629 + mToken);
630 return;
631 }
632 mContainer.notifyAppStopped();
633 }
634 }
635
636 public void startFreezingScreen(int configChanges) {
637 synchronized(mWindowMap) {
638 if (configChanges == 0 && mService.okToDisplay()) {
639 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + mToken);
640 return;
641 }
642
643 if (mContainer == null) {
644 Slog.w(TAG_WM,
645 "Attempted to freeze screen with non-existing app token: " + mContainer);
646 return;
647 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800648 mContainer.startFreezingScreen();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800649 }
650 }
651
652 public void stopFreezingScreen(boolean force) {
653 synchronized(mWindowMap) {
654 if (mContainer == null) {
655 return;
656 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800657 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + mToken + ": hidden="
658 + mContainer.hidden + " freezing=" + mContainer.mAppAnimator.freezingScreen);
659 mContainer.stopFreezingScreen(true, force);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800660 }
661 }
662
663 /**
664 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
665 * In portrait mode, it grabs the full screenshot.
666 *
667 * @param displayId the Display to take a screenshot of.
668 * @param width the width of the target bitmap
669 * @param height the height of the target bitmap
670 * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
671 */
672 public Bitmap screenshotApplications(int displayId, int width, int height, float frameScale) {
673 try {
674 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotApplications");
675 final DisplayContent dc;
676 synchronized(mWindowMap) {
677 dc = mRoot.getDisplayContentOrCreate(displayId);
678 if (dc == null) {
679 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + mToken
680 + ": returning null. No Display for displayId=" + displayId);
681 return null;
682 }
683 }
684 return dc.screenshotApplications(mToken.asBinder(), width, height,
685 false /* includeFullDisplay */, frameScale, Bitmap.Config.RGB_565,
Jorim Jaggi6a7a8592017-01-12 00:44:33 +0100686 false /* wallpaperOnly */, false /* includeDecor */);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800687 } finally {
688 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
689 }
690 }
691
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800692 void reportStartingWindowDrawn() {
693 mHandler.post(mOnStartingWindowDrawn);
694 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800695
696 void reportWindowsDrawn() {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800697 mHandler.post(mOnWindowsDrawn);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800698 }
699
700 void reportWindowsVisible() {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800701 mHandler.post(mOnWindowsVisible);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800702 }
703
704 void reportWindowsGone() {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800705 mHandler.post(mOnWindowsGone);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800706 }
707
708 /** Calls directly into activity manager so window manager lock shouldn't held. */
Wale Ogunwale7402ddf2017-03-29 12:58:24 -0700709 boolean keyDispatchingTimedOut(String reason, int windowPid) {
710 return mListener != null && mListener.keyDispatchingTimedOut(reason, windowPid);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800711 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800712
713 @Override
714 public String toString() {
Wale Ogunwale9c64cb62017-04-12 13:39:59 -0700715 return "AppWindowContainerController{"
716 + " token=" + mToken
717 + " mContainer=" + mContainer
718 + " mListener=" + mListener
719 + "}";
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800720 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800721}