blob: 4dbe35f2592b3466e34ae855ad76d966e5401580 [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
31import android.content.res.CompatibilityInfo;
32import android.content.res.Configuration;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080033import android.graphics.Bitmap;
Jorim Jaggi02886a82016-12-06 09:10:06 -080034import android.graphics.GraphicBuffer;
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;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080038import android.os.Looper;
39import android.os.Trace;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080040import android.util.Slog;
41import android.view.IApplicationToken;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080042import android.view.WindowManagerPolicy.StartingSurface;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080043
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080044import com.android.server.AttributeCache;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080045/**
46 * Controller for the app window token container. This is created by activity manager to link
47 * activity records to the app window token container they use in window manager.
48 *
49 * Test class: {@link AppWindowContainerControllerTests}
50 */
51public class AppWindowContainerController
52 extends WindowContainerController<AppWindowToken, AppWindowContainerListener> {
53
Jorim Jaggi02886a82016-12-06 09:10:06 -080054 private static final int STARTING_WINDOW_TYPE_NONE = 0;
55 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
56 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
57
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080058 private final IApplicationToken mToken;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080059 private final Handler mHandler = new Handler(Looper.getMainLooper());
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080060
61 private final Runnable mOnWindowsDrawn = () -> {
62 if (mListener == null) {
63 return;
64 }
65 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting drawn in "
66 + AppWindowContainerController.this.mToken);
67 mListener.onWindowsDrawn();
68 };
69
70 private final Runnable mOnWindowsVisible = () -> {
71 if (mListener == null) {
72 return;
73 }
74 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting visible in "
75 + AppWindowContainerController.this.mToken);
76 mListener.onWindowsVisible();
77 };
78
79 private final Runnable mOnWindowsGone = () -> {
80 if (mListener == null) {
81 return;
82 }
83 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in "
84 + AppWindowContainerController.this.mToken);
85 mListener.onWindowsGone();
86 };
87
Jorim Jaggi02886a82016-12-06 09:10:06 -080088 private final Runnable mRemoveStartingWindow = () -> {
89 StartingSurface surface = null;
90 StartingData data = null;
91 synchronized (mWindowMap) {
92 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Remove starting " + mContainer
93 + ": startingWindow=" + mContainer.startingWindow
94 + " startingView=" + mContainer.startingSurface);
95 if (mContainer.startingWindow != null) {
96 surface = mContainer.startingSurface;
97 data = mContainer.startingData;
98 mContainer.startingData = null;
99 mContainer.startingSurface = null;
100 mContainer.startingWindow = null;
101 mContainer.startingDisplayed = false;
102 }
103 }
104 if (data != null && surface != null) {
105 try {
106 surface.remove();
107 } catch (Exception e) {
108 Slog.w(TAG_WM, "Exception when removing starting window", e);
109 }
110 }
111 };
112
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800113 private final Runnable mAddStartingWindow = () -> {
114 final StartingData startingData;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800115
116 synchronized (mWindowMap) {
Jorim Jaggi73f88202017-01-12 13:54:40 +0100117 if (mContainer == null) {
118 return;
119 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800120 startingData = mContainer.startingData;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800121 }
122
123 if (startingData == null) {
124 // Animation has been canceled... do nothing.
125 return;
126 }
127
128 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting "
Jorim Jaggi02886a82016-12-06 09:10:06 -0800129 + this + ": startingData=" + mContainer.startingData);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800130
Jorim Jaggi02886a82016-12-06 09:10:06 -0800131 StartingSurface surface = null;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800132 try {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800133 surface = startingData.createStartingSurface();
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800134 } catch (Exception e) {
135 Slog.w(TAG_WM, "Exception when adding starting window", e);
136 }
Jorim Jaggi02886a82016-12-06 09:10:06 -0800137 if (surface != null) {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800138 boolean abort = false;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800139 synchronized(mWindowMap) {
140 if (mContainer.removed || mContainer.startingData == null) {
141 // If the window was successfully added, then
142 // we need to remove it.
143 if (mContainer.startingWindow != null) {
144 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
145 "Aborted starting " + mContainer
146 + ": removed=" + mContainer.removed
147 + " startingData=" + mContainer.startingData);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800148 abort = true;
149 }
150 } else {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800151 mContainer.startingSurface = surface;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800152 }
153 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM,
154 "Added starting " + mContainer
155 + ": startingWindow="
156 + mContainer.startingWindow + " startingView="
157 + mContainer.startingSurface);
158 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800159 if (abort) {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800160 mRemoveStartingWindow.run();
Jorim Jaggi73f88202017-01-12 13:54:40 +0100161 if (mContainer == null) {
162 return;
163 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800164 }
165 }
166 };
167
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800168 public AppWindowContainerController(TaskWindowContainerController taskController,
169 IApplicationToken token, AppWindowContainerListener listener, int index,
170 int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges,
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800171 boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
172 int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800173 this(taskController, token, listener, index, requestedOrientation, fullscreen,
174 showForAllUsers,
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800175 configChanges, voiceInteraction, launchTaskBehind, alwaysFocusable,
176 targetSdkVersion, rotationAnimationHint, inputDispatchingTimeoutNanos,
177 WindowManagerService.getInstance());
178 }
179
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800180 public AppWindowContainerController(TaskWindowContainerController taskController,
181 IApplicationToken token, AppWindowContainerListener listener, int index,
182 int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges,
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800183 boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
184 int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos,
185 WindowManagerService service) {
186 super(listener, service);
187 mToken = token;
188 synchronized(mWindowMap) {
189 AppWindowToken atoken = mRoot.getAppWindowToken(mToken.asBinder());
190 if (atoken != null) {
191 // TODO: Should this throw an exception instead?
192 Slog.w(TAG_WM, "Attempted to add existing app token: " + mToken);
193 return;
194 }
195
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800196 final Task task = taskController.mContainer;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800197 if (task == null) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800198 throw new IllegalArgumentException("AppWindowContainerController: invalid "
199 + " controller=" + taskController);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800200 }
201
202 atoken = new AppWindowToken(mService, token, voiceInteraction, task.getDisplayContent(),
203 inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdkVersion,
204 requestedOrientation, rotationAnimationHint, configChanges, launchTaskBehind,
205 alwaysFocusable, this);
206 if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800207 + " controller=" + taskController + " at " + index);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800208 task.addChild(atoken, index);
209 }
210 }
211
212 public void removeContainer(int displayId) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800213 synchronized(mWindowMap) {
214 final DisplayContent dc = mRoot.getDisplayContent(displayId);
215 if (dc == null) {
216 Slog.w(TAG_WM, "removeAppToken: Attempted to remove binder token: "
217 + mToken + " from non-existing displayId=" + displayId);
218 return;
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800219 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800220 dc.removeAppToken(mToken.asBinder());
221 super.removeContainer();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800222 }
223 }
224
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800225 @Override
226 public void removeContainer() {
227 throw new UnsupportedOperationException("Use removeContainer(displayId) instead.");
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800228 }
229
230 public Configuration setOrientation(int requestedOrientation, int displayId,
231 Configuration displayConfig, boolean freezeScreenIfNeeded) {
232 synchronized(mWindowMap) {
233 if (mContainer == null) {
234 Slog.w(TAG_WM,
235 "Attempted to set orientation of non-existing app token: " + mToken);
236 return null;
237 }
238
239 mContainer.setOrientation(requestedOrientation);
240
241 final IBinder binder = freezeScreenIfNeeded ? mToken.asBinder() : null;
242 return mService.updateOrientationFromAppTokens(displayConfig, binder, displayId);
243
244 }
245 }
246
247 public int getOrientation() {
248 synchronized(mWindowMap) {
249 if (mContainer == null) {
250 return SCREEN_ORIENTATION_UNSPECIFIED;
251 }
252
253 return mContainer.getOrientationIgnoreVisibility();
254 }
255 }
256
257 public void setVisibility(boolean visible) {
258 synchronized(mWindowMap) {
259 if (mContainer == null) {
260 Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
261 + mToken);
262 return;
263 }
264
265 final AppWindowToken wtoken = mContainer;
266
267 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG_WM, "setAppVisibility("
268 + mToken + ", visible=" + visible + "): " + mService.mAppTransition
269 + " hidden=" + wtoken.hidden + " hiddenRequested="
270 + wtoken.hiddenRequested + " Callers=" + Debug.getCallers(6));
271
272 mService.mOpeningApps.remove(wtoken);
273 mService.mClosingApps.remove(wtoken);
274 wtoken.waitingToShow = false;
275 wtoken.hiddenRequested = !visible;
276
277 if (!visible) {
278 // If the app is dead while it was visible, we kept its dead window on screen.
279 // Now that the app is going invisible, we can remove it. It will be restarted
280 // if made visible again.
281 wtoken.removeDeadWindows();
282 wtoken.setVisibleBeforeClientHidden();
283 } else {
284 if (!mService.mAppTransition.isTransitionSet()
285 && mService.mAppTransition.isReady()) {
286 // Add the app mOpeningApps if transition is unset but ready. This means
287 // we're doing a screen freeze, and the unfreeze will wait for all opening
288 // apps to be ready.
289 mService.mOpeningApps.add(wtoken);
290 }
291 wtoken.startingMoved = false;
292 // If the token is currently hidden (should be the common case), or has been
293 // stopped, then we need to set up to wait for its windows to be ready.
294 if (wtoken.hidden || wtoken.mAppStopped) {
295 wtoken.clearAllDrawn();
296
297 // If the app was already visible, don't reset the waitingToShow state.
298 if (wtoken.hidden) {
299 wtoken.waitingToShow = true;
300 }
301
302 if (wtoken.clientHidden) {
303 // In the case where we are making an app visible
304 // but holding off for a transition, we still need
305 // to tell the client to make its windows visible so
306 // they get drawn. Otherwise, we will wait on
307 // performing the transition until all windows have
308 // been drawn, they never will be, and we are sad.
309 wtoken.clientHidden = false;
310 wtoken.sendAppVisibilityToClients();
311 }
312 }
313 wtoken.requestUpdateWallpaperIfNeeded();
314
315 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + wtoken);
316 wtoken.mAppStopped = false;
317 }
318
319 // If we are preparing an app transition, then delay changing
320 // the visibility of this token until we execute that transition.
321 if (mService.okToDisplay() && mService.mAppTransition.isTransitionSet()) {
322 // A dummy animation is a placeholder animation which informs others that an
323 // animation is going on (in this case an application transition). If the animation
324 // was transferred from another application/animator, no dummy animator should be
325 // created since an animation is already in progress.
326 if (wtoken.mAppAnimator.usingTransferredAnimation
327 && wtoken.mAppAnimator.animation == null) {
328 Slog.wtf(TAG_WM, "Will NOT set dummy animation on: " + wtoken
329 + ", using null transferred animation!");
330 }
331 if (!wtoken.mAppAnimator.usingTransferredAnimation &&
332 (!wtoken.startingDisplayed || mService.mSkipAppTransitionAnimation)) {
333 if (DEBUG_APP_TRANSITIONS) Slog.v(
334 TAG_WM, "Setting dummy animation on: " + wtoken);
335 wtoken.mAppAnimator.setDummyAnimation();
336 }
337 wtoken.inPendingTransaction = true;
338 if (visible) {
339 mService.mOpeningApps.add(wtoken);
340 wtoken.mEnteringAnimation = true;
341 } else {
342 mService.mClosingApps.add(wtoken);
343 wtoken.mEnteringAnimation = false;
344 }
345 if (mService.mAppTransition.getAppTransition()
346 == AppTransition.TRANSIT_TASK_OPEN_BEHIND) {
347 // We're launchingBehind, add the launching activity to mOpeningApps.
348 final WindowState win =
349 mService.getDefaultDisplayContentLocked().findFocusedWindow();
350 if (win != null) {
351 final AppWindowToken focusedToken = win.mAppToken;
352 if (focusedToken != null) {
353 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
354 + " adding " + focusedToken + " to mOpeningApps");
355 // Force animation to be loaded.
356 focusedToken.hidden = true;
357 mService.mOpeningApps.add(focusedToken);
358 }
359 }
360 }
361 return;
362 }
363
364 wtoken.setVisibility(null, visible, TRANSIT_UNSET, true, wtoken.mVoiceInteraction);
365 wtoken.updateReportedVisibilityLocked();
366 }
367 }
368
369 /**
370 * Notifies that we launched an app that might be visible or not visible depending on what kind
371 * of Keyguard flags it's going to set on its windows.
372 */
373 public void notifyUnknownVisibilityLaunched() {
374 synchronized(mWindowMap) {
375 if (mContainer != null) {
376 mService.mUnknownAppVisibilityController.notifyLaunched(mContainer);
377 }
378 }
379 }
380
381 public boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
382 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
Jorim Jaggi02886a82016-12-06 09:10:06 -0800383 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800384 synchronized(mWindowMap) {
385 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "setAppStartingWindow: token=" + mToken
386 + " pkg=" + pkg + " transferFrom=" + transferFrom);
387
388 if (mContainer == null) {
389 Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + mToken);
390 return false;
391 }
392
393 // If the display is frozen, we won't do anything until the actual window is
394 // displayed so there is no reason to put in the starting window.
395 if (!mService.okToDisplay()) {
396 return false;
397 }
398
399 if (mContainer.startingData != null) {
400 return false;
401 }
402
Jorim Jaggi02886a82016-12-06 09:10:06 -0800403 final int type = getStartingWindowType(newTask, taskSwitch, processRunning);
404
405 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
406 return createSnapshot();
407 }
408
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800409 // If this is a translucent window, then don't show a starting window -- the current
410 // effect (a full-screen opaque starting window that fades away to the real contents
411 // when it is ready) does not work for this.
412 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Checking theme of starting window: 0x"
413 + Integer.toHexString(theme));
414 if (theme != 0) {
415 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
416 com.android.internal.R.styleable.Window, mService.mCurrentUserId);
417 if (ent == null) {
418 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
419 // see that.
420 return false;
421 }
422 final boolean windowIsTranslucent = ent.array.getBoolean(
423 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
424 final boolean windowIsFloating = ent.array.getBoolean(
425 com.android.internal.R.styleable.Window_windowIsFloating, false);
426 final boolean windowShowWallpaper = ent.array.getBoolean(
427 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
428 final boolean windowDisableStarting = ent.array.getBoolean(
429 com.android.internal.R.styleable.Window_windowDisablePreview, false);
430 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Translucent=" + windowIsTranslucent
431 + " Floating=" + windowIsFloating
432 + " ShowWallpaper=" + windowShowWallpaper);
433 if (windowIsTranslucent) {
434 return false;
435 }
436 if (windowIsFloating || windowDisableStarting) {
437 return false;
438 }
439 if (windowShowWallpaper) {
440 if (mContainer.getDisplayContent().mWallpaperController.getWallpaperTarget()
441 == null) {
442 // If this theme is requesting a wallpaper, and the wallpaper
443 // is not currently visible, then this effectively serves as
444 // an opaque window and our starting window transition animation
445 // can still work. We just need to make sure the starting window
446 // is also showing the wallpaper.
447 windowFlags |= FLAG_SHOW_WALLPAPER;
448 } else {
449 return false;
450 }
451 }
452 }
453
454 if (mContainer.transferStartingWindow(transferFrom)) {
455 return true;
456 }
457
Jorim Jaggi02886a82016-12-06 09:10:06 -0800458 // There is no existing starting window, and we don't want to create a splash screen, so
459 // that's it!
460 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800461 return false;
462 }
463
464 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating StartingData");
Jorim Jaggi02886a82016-12-06 09:10:06 -0800465 mContainer.startingData = new SplashScreenStartingData(mService, mContainer, pkg, theme,
466 compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
467 mContainer.getMergedOverrideConfiguration());
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800468 scheduleAddStartingWindow();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800469 }
470 return true;
471 }
472
Jorim Jaggi02886a82016-12-06 09:10:06 -0800473 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning) {
474 if (newTask || !processRunning) {
475 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
476 } else if (taskSwitch) {
477 return STARTING_WINDOW_TYPE_SNAPSHOT;
478 } else {
479 return STARTING_WINDOW_TYPE_NONE;
480 }
481 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800482
Jorim Jaggi02886a82016-12-06 09:10:06 -0800483 void scheduleAddStartingWindow() {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800484 // Note: we really want to do sendMessageAtFrontOfQueue() because we
485 // want to process the message ASAP, before any other queued
486 // messages.
487 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING");
488 mHandler.postAtFrontOfQueue(mAddStartingWindow);
489 }
490
Jorim Jaggi02886a82016-12-06 09:10:06 -0800491 private boolean createSnapshot() {
492 final GraphicBuffer snapshot = mService.mTaskSnapshotController.getSnapshot(
493 mContainer.mTask);
494
495 if (snapshot == null) {
496 return false;
497 }
498
499 mContainer.startingData = new SnapshotStartingData(mService, mContainer, snapshot);
500 scheduleAddStartingWindow();
501 return true;
502 }
503
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800504 public void removeStartingWindow() {
505 synchronized (mWindowMap) {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800506 if (mHandler.hasCallbacks(mRemoveStartingWindow)) {
507 // Already scheduled.
508 return;
509 }
510
511 if (mContainer.startingWindow == null) {
512 if (mContainer.startingData != null) {
513 // Starting window has not been added yet, but it is scheduled to be added.
514 // Go ahead and cancel the request.
515 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
516 "Clearing startingData for token=" + mContainer);
517 mContainer.startingData = null;
518 }
519 return;
520 }
521
522 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, Debug.getCallers(1)
523 + ": Schedule remove starting " + mContainer
524 + " startingWindow=" + mContainer.startingWindow);
525 mHandler.post(mRemoveStartingWindow);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800526 }
527 }
528
529 public void pauseKeyDispatching() {
530 synchronized (mWindowMap) {
531 if (mContainer != null) {
532 mService.mInputMonitor.pauseDispatchingLw(mContainer);
533 }
534 }
535 }
536
537 public void resumeKeyDispatching() {
538 synchronized (mWindowMap) {
539 if (mContainer != null) {
540 mService.mInputMonitor.resumeDispatchingLw(mContainer);
541 }
542 }
543 }
544
545 public void notifyAppResumed(boolean wasStopped, boolean allowSavedSurface) {
546 synchronized(mWindowMap) {
547 if (mContainer == null) {
548 Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: " + mToken);
549 return;
550 }
551 mContainer.notifyAppResumed(wasStopped, allowSavedSurface);
552 }
553 }
554
555 public void notifyAppStopped() {
556 synchronized(mWindowMap) {
557 if (mContainer == null) {
558 Slog.w(TAG_WM, "Attempted to notify stopped of non-existing app token: "
559 + mToken);
560 return;
561 }
562 mContainer.notifyAppStopped();
563 }
564 }
565
566 public void startFreezingScreen(int configChanges) {
567 synchronized(mWindowMap) {
568 if (configChanges == 0 && mService.okToDisplay()) {
569 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + mToken);
570 return;
571 }
572
573 if (mContainer == null) {
574 Slog.w(TAG_WM,
575 "Attempted to freeze screen with non-existing app token: " + mContainer);
576 return;
577 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800578 mContainer.startFreezingScreen();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800579 }
580 }
581
582 public void stopFreezingScreen(boolean force) {
583 synchronized(mWindowMap) {
584 if (mContainer == null) {
585 return;
586 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800587 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + mToken + ": hidden="
588 + mContainer.hidden + " freezing=" + mContainer.mAppAnimator.freezingScreen);
589 mContainer.stopFreezingScreen(true, force);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800590 }
591 }
592
593 /**
594 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
595 * In portrait mode, it grabs the full screenshot.
596 *
597 * @param displayId the Display to take a screenshot of.
598 * @param width the width of the target bitmap
599 * @param height the height of the target bitmap
600 * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
601 */
602 public Bitmap screenshotApplications(int displayId, int width, int height, float frameScale) {
603 try {
604 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotApplications");
605 final DisplayContent dc;
606 synchronized(mWindowMap) {
607 dc = mRoot.getDisplayContentOrCreate(displayId);
608 if (dc == null) {
609 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + mToken
610 + ": returning null. No Display for displayId=" + displayId);
611 return null;
612 }
613 }
614 return dc.screenshotApplications(mToken.asBinder(), width, height,
615 false /* includeFullDisplay */, frameScale, Bitmap.Config.RGB_565,
Jorim Jaggi02886a82016-12-06 09:10:06 -0800616 false /* wallpaperOnly */, false /* includeDecor */, true /* toAshmem */);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800617 } finally {
618 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
619 }
620 }
621
622
623 void reportWindowsDrawn() {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800624 mHandler.post(mOnWindowsDrawn);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800625 }
626
627 void reportWindowsVisible() {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800628 mHandler.post(mOnWindowsVisible);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800629 }
630
631 void reportWindowsGone() {
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800632 mHandler.post(mOnWindowsGone);
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800633 }
634
635 /** Calls directly into activity manager so window manager lock shouldn't held. */
636 boolean keyDispatchingTimedOut(String reason) {
637 return mListener != null && mListener.keyDispatchingTimedOut(reason);
638 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800639
640 @Override
641 public String toString() {
642 return "{AppWindowContainerController token=" + mToken + "}";
643 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800644}