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