WindowManagerService.java revision 1ee99c4627eeae1a94ada9a884a76b726cf6ca4c
1/* 2 * Copyright (C) 2007 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.view.WindowManager.LayoutParams.*; 20 21import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 22import android.app.AppOpsManager; 23import android.util.ArraySet; 24import android.util.TimeUtils; 25import android.view.IWindowId; 26 27import android.view.IWindowSessionCallback; 28import android.view.WindowContentFrameStats; 29import com.android.internal.app.IBatteryStats; 30import com.android.internal.policy.PolicyManager; 31import com.android.internal.policy.impl.PhoneWindowManager; 32import com.android.internal.util.FastPrintWriter; 33import com.android.internal.view.IInputContext; 34import com.android.internal.view.IInputMethodClient; 35import com.android.internal.view.IInputMethodManager; 36import com.android.internal.view.WindowManagerPolicyThread; 37import com.android.server.AttributeCache; 38import com.android.server.DisplayThread; 39import com.android.server.EventLogTags; 40import com.android.server.LocalServices; 41import com.android.server.UiThread; 42import com.android.server.Watchdog; 43import com.android.server.am.BatteryStatsService; 44import com.android.server.input.InputManagerService; 45import com.android.server.power.ShutdownThread; 46 47import android.Manifest; 48import android.app.ActivityManagerNative; 49import android.app.IActivityManager; 50import android.app.StatusBarManager; 51import android.app.admin.DevicePolicyManager; 52import android.animation.ValueAnimator; 53import android.content.BroadcastReceiver; 54import android.content.Context; 55import android.content.Intent; 56import android.content.IntentFilter; 57import android.content.pm.ActivityInfo; 58import android.content.pm.PackageManager; 59import android.content.res.CompatibilityInfo; 60import android.content.res.Configuration; 61import android.graphics.Bitmap; 62import android.graphics.Bitmap.Config; 63import android.graphics.Canvas; 64import android.graphics.Matrix; 65import android.graphics.PixelFormat; 66import android.graphics.Point; 67import android.graphics.Rect; 68import android.graphics.RectF; 69import android.graphics.Region; 70import android.hardware.display.DisplayManager; 71import android.hardware.display.DisplayManagerInternal; 72import android.os.Binder; 73import android.os.Bundle; 74import android.os.Debug; 75import android.os.Handler; 76import android.os.IBinder; 77import android.os.IRemoteCallback; 78import android.os.Looper; 79import android.os.Message; 80import android.os.Parcel; 81import android.os.ParcelFileDescriptor; 82import android.os.PowerManager; 83import android.os.PowerManagerInternal; 84import android.os.Process; 85import android.os.RemoteException; 86import android.os.ServiceManager; 87import android.os.StrictMode; 88import android.os.SystemClock; 89import android.os.SystemProperties; 90import android.os.Trace; 91import android.os.UserHandle; 92import android.os.WorkSource; 93import android.provider.Settings; 94import android.util.DisplayMetrics; 95import android.util.EventLog; 96import android.util.FloatMath; 97import android.util.Log; 98import android.util.SparseArray; 99import android.util.Pair; 100import android.util.Slog; 101import android.util.SparseIntArray; 102import android.util.TypedValue; 103import android.view.Choreographer; 104import android.view.Display; 105import android.view.DisplayInfo; 106import android.view.Gravity; 107import android.view.IApplicationToken; 108import android.view.IInputFilter; 109import android.view.IOnKeyguardExitResult; 110import android.view.IRotationWatcher; 111import android.view.IWindow; 112import android.view.IWindowManager; 113import android.view.IWindowSession; 114import android.view.InputChannel; 115import android.view.InputDevice; 116import android.view.InputEvent; 117import android.view.InputEventReceiver; 118import android.view.KeyEvent; 119import android.view.MagnificationSpec; 120import android.view.MotionEvent; 121import android.view.WindowManagerInternal; 122import android.view.Surface.OutOfResourcesException; 123import android.view.Surface; 124import android.view.SurfaceControl; 125import android.view.SurfaceSession; 126import android.view.View; 127import android.view.ViewTreeObserver; 128import android.view.WindowManager; 129import android.view.WindowManagerGlobal; 130import android.view.WindowManagerPolicy; 131import android.view.WindowManager.LayoutParams; 132import android.view.WindowManagerPolicy.FakeWindow; 133import android.view.WindowManagerPolicy.PointerEventListener; 134import android.view.animation.Animation; 135import android.view.animation.AnimationUtils; 136import android.view.animation.Transformation; 137 138import java.io.BufferedWriter; 139import java.io.DataInputStream; 140import java.io.File; 141import java.io.FileDescriptor; 142import java.io.FileInputStream; 143import java.io.FileNotFoundException; 144import java.io.IOException; 145import java.io.OutputStream; 146import java.io.OutputStreamWriter; 147import java.io.PrintWriter; 148import java.io.StringWriter; 149import java.net.Socket; 150import java.text.DateFormat; 151import java.util.ArrayList; 152import java.util.Date; 153import java.util.HashMap; 154import java.util.HashSet; 155import java.util.Iterator; 156import java.util.List; 157 158/** {@hide} */ 159public class WindowManagerService extends IWindowManager.Stub 160 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs { 161 static final String TAG = "WindowManager"; 162 static final boolean DEBUG = false; 163 static final boolean DEBUG_ADD_REMOVE = false; 164 static final boolean DEBUG_FOCUS = false; 165 static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false; 166 static final boolean DEBUG_ANIM = false; 167 static final boolean DEBUG_LAYOUT = false; 168 static final boolean DEBUG_RESIZE = false; 169 static final boolean DEBUG_LAYERS = false; 170 static final boolean DEBUG_INPUT = false; 171 static final boolean DEBUG_INPUT_METHOD = false; 172 static final boolean DEBUG_VISIBILITY = false; 173 static final boolean DEBUG_WINDOW_MOVEMENT = false; 174 static final boolean DEBUG_TOKEN_MOVEMENT = false; 175 static final boolean DEBUG_ORIENTATION = false; 176 static final boolean DEBUG_APP_ORIENTATION = false; 177 static final boolean DEBUG_CONFIGURATION = false; 178 static final boolean DEBUG_APP_TRANSITIONS = false; 179 static final boolean DEBUG_STARTING_WINDOW = false; 180 static final boolean DEBUG_REORDER = false; 181 static final boolean DEBUG_WALLPAPER = false; 182 static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER; 183 static final boolean DEBUG_DRAG = false; 184 static final boolean DEBUG_SCREEN_ON = false; 185 static final boolean DEBUG_SCREENSHOT = false; 186 static final boolean DEBUG_BOOT = false; 187 static final boolean DEBUG_LAYOUT_REPEATS = true; 188 static final boolean DEBUG_SURFACE_TRACE = false; 189 static final boolean DEBUG_WINDOW_TRACE = false; 190 static final boolean DEBUG_TASK_MOVEMENT = false; 191 static final boolean DEBUG_STACK = false; 192 static final boolean DEBUG_DISPLAY = false; 193 static final boolean SHOW_SURFACE_ALLOC = false; 194 static final boolean SHOW_TRANSACTIONS = false; 195 static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS; 196 static final boolean HIDE_STACK_CRAWLS = true; 197 static final int LAYOUT_REPEAT_THRESHOLD = 4; 198 199 static final boolean PROFILE_ORIENTATION = false; 200 static final boolean localLOGV = DEBUG; 201 202 /** How much to multiply the policy's type layer, to reserve room 203 * for multiple windows of the same type and Z-ordering adjustment 204 * with TYPE_LAYER_OFFSET. */ 205 static final int TYPE_LAYER_MULTIPLIER = 10000; 206 207 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above 208 * or below others in the same layer. */ 209 static final int TYPE_LAYER_OFFSET = 1000; 210 211 /** How much to increment the layer for each window, to reserve room 212 * for effect surfaces between them. 213 */ 214 static final int WINDOW_LAYER_MULTIPLIER = 5; 215 216 /** 217 * Dim surface layer is immediately below target window. 218 */ 219 static final int LAYER_OFFSET_DIM = 1; 220 221 /** 222 * Blur surface layer is immediately below dim layer. 223 */ 224 static final int LAYER_OFFSET_BLUR = 2; 225 226 /** 227 * FocusedStackFrame layer is immediately above focused window. 228 */ 229 static final int LAYER_OFFSET_FOCUSED_STACK = 1; 230 231 /** 232 * Animation thumbnail is as far as possible below the window above 233 * the thumbnail (or in other words as far as possible above the window 234 * below it). 235 */ 236 static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER-1; 237 238 /** 239 * Layer at which to put the rotation freeze snapshot. 240 */ 241 static final int FREEZE_LAYER = (TYPE_LAYER_MULTIPLIER * 200) + 1; 242 243 /** 244 * Layer at which to put the mask for emulated screen sizes. 245 */ 246 static final int MASK_LAYER = TYPE_LAYER_MULTIPLIER * 200; 247 248 /** The maximum length we will accept for a loaded animation duration: 249 * this is 10 seconds. 250 */ 251 static final int MAX_ANIMATION_DURATION = 10*1000; 252 253 /** Amount of time (in milliseconds) to animate the fade-in-out transition for 254 * compatible windows. 255 */ 256 static final int DEFAULT_FADE_IN_OUT_DURATION = 400; 257 258 /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */ 259 static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000; 260 261 /** 262 * If true, the window manager will do its own custom freezing and general 263 * management of the screen during rotation. 264 */ 265 static final boolean CUSTOM_SCREEN_ROTATION = true; 266 267 // Maximum number of milliseconds to wait for input devices to be enumerated before 268 // proceding with safe mode detection. 269 private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000; 270 271 // Default input dispatching timeout in nanoseconds. 272 static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L; 273 274 /** Minimum value for attachStack and resizeStack weight value */ 275 public static final float STACK_WEIGHT_MIN = 0.2f; 276 277 /** Maximum value for attachStack and resizeStack weight value */ 278 public static final float STACK_WEIGHT_MAX = 0.8f; 279 280 static final int UPDATE_FOCUS_NORMAL = 0; 281 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1; 282 static final int UPDATE_FOCUS_PLACING_SURFACES = 2; 283 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3; 284 285 private static final String SYSTEM_SECURE = "ro.secure"; 286 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; 287 288 private static final String DENSITY_OVERRIDE = "ro.config.density_override"; 289 private static final String SIZE_OVERRIDE = "ro.config.size_override"; 290 291 private static final int MAX_SCREENSHOT_RETRIES = 3; 292 293 // The flag describing a full screen app window (where the app takes care of drawing under the 294 // SystemUI bars) 295 private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN = 296 View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 297 298 final private KeyguardDisableHandler mKeyguardDisableHandler; 299 300 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 301 @Override 302 public void onReceive(Context context, Intent intent) { 303 final String action = intent.getAction(); 304 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) { 305 mKeyguardDisableHandler.sendEmptyMessage( 306 KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED); 307 } 308 } 309 }; 310 311 /** 312 * Current user when multi-user is enabled. Don't show windows of 313 * non-current user. Also see mCurrentProfileIds. 314 */ 315 int mCurrentUserId; 316 /** 317 * Users that are profiles of the current user. These are also allowed to show windows 318 * on the current user. 319 */ 320 int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER}; 321 322 final Context mContext; 323 324 final boolean mHaveInputMethods; 325 326 final boolean mAllowBootMessages; 327 328 final boolean mLimitedAlphaCompositing; 329 330 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager(); 331 332 final IActivityManager mActivityManager; 333 334 final IBatteryStats mBatteryStats; 335 336 final AppOpsManager mAppOps; 337 338 final DisplaySettings mDisplaySettings; 339 340 /** 341 * All currently active sessions with clients. 342 */ 343 final ArraySet<Session> mSessions = new ArraySet<Session>(); 344 345 /** 346 * Mapping from an IWindow IBinder to the server's Window object. 347 * This is also used as the lock for all of our state. 348 * NOTE: Never call into methods that lock ActivityManagerService while holding this object. 349 */ 350 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>(); 351 352 /** 353 * Mapping from a token IBinder to a WindowToken object. 354 */ 355 final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>(); 356 357 /** 358 * List of window tokens that have finished starting their application, 359 * and now need to have the policy remove their windows. 360 */ 361 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>(); 362 363 /** 364 * Fake windows added to the window manager. Note: ordered from top to 365 * bottom, opposite of mWindows. 366 */ 367 final ArrayList<FakeWindowImpl> mFakeWindows = new ArrayList<FakeWindowImpl>(); 368 369 /** 370 * Windows that are being resized. Used so we can tell the client about 371 * the resize after closing the transaction in which we resized the 372 * underlying surface. 373 */ 374 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>(); 375 376 /** 377 * Windows whose animations have ended and now must be removed. 378 */ 379 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>(); 380 381 /** 382 * Stacks whose animations have ended and whose tasks, apps, selves may now be removed. 383 */ 384 final ArraySet<TaskStack> mPendingStacksRemove = new ArraySet<TaskStack>(); 385 386 /** 387 * Used when processing mPendingRemove to avoid working on the original array. 388 */ 389 WindowState[] mPendingRemoveTmp = new WindowState[20]; 390 391 /** 392 * Windows whose surface should be destroyed. 393 */ 394 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>(); 395 396 /** 397 * Windows that have lost input focus and are waiting for the new 398 * focus window to be displayed before they are told about this. 399 */ 400 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>(); 401 402 /** 403 * This is set when we have run out of memory, and will either be an empty 404 * list or contain windows that need to be force removed. 405 */ 406 ArrayList<WindowState> mForceRemoves; 407 408 /** 409 * Windows that clients are waiting to have drawn. 410 */ 411 ArrayList<WindowState> mWaitingForDrawn = new ArrayList<WindowState>(); 412 /** 413 * And the callback to make when they've all been drawn. 414 */ 415 IRemoteCallback mWaitingForDrawnCallback; 416 417 /** 418 * Windows that have called relayout() while we were running animations, 419 * so we need to tell when the animation is done. 420 */ 421 final ArrayList<WindowState> mRelayoutWhileAnimating = new ArrayList<WindowState>(); 422 423 /** 424 * Used when rebuilding window list to keep track of windows that have 425 * been removed. 426 */ 427 WindowState[] mRebuildTmp = new WindowState[20]; 428 429 IInputMethodManager mInputMethodManager; 430 431 AccessibilityController mAccessibilityController; 432 433 final SurfaceSession mFxSession; 434 Watermark mWatermark; 435 StrictModeFlash mStrictModeFlash; 436 CircularDisplayMask mCircularDisplayMask; 437 FocusedStackFrame mFocusedStackFrame; 438 439 int mFocusedStackLayer; 440 441 final float[] mTmpFloats = new float[9]; 442 final Rect mTmpContentRect = new Rect(); 443 444 boolean mDisplayReady; 445 boolean mSafeMode; 446 boolean mDisplayEnabled = false; 447 boolean mSystemBooted = false; 448 boolean mForceDisplayEnabled = false; 449 boolean mShowingBootMessages = false; 450 451 String mLastANRState; 452 453 /** All DisplayContents in the world, kept here */ 454 SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>(2); 455 456 int mRotation = 0; 457 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 458 boolean mAltOrientation = false; 459 class RotationWatcher { 460 IRotationWatcher watcher; 461 IBinder.DeathRecipient deathRecipient; 462 RotationWatcher(IRotationWatcher w, IBinder.DeathRecipient d) { 463 watcher = w; 464 deathRecipient = d; 465 } 466 } 467 ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<RotationWatcher>(); 468 int mDeferredRotationPauseCount; 469 470 int mSystemDecorLayer = 0; 471 final Rect mScreenRect = new Rect(); 472 473 boolean mTraversalScheduled = false; 474 boolean mDisplayFrozen = false; 475 long mDisplayFreezeTime = 0; 476 int mLastDisplayFreezeDuration = 0; 477 Object mLastFinishedFreezeSource = null; 478 boolean mWaitingForConfig = false; 479 boolean mWindowsFreezingScreen = false; 480 boolean mClientFreezingScreen = false; 481 int mAppsFreezingScreen = 0; 482 int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 483 484 int mLayoutSeq = 0; 485 486 int mLastStatusBarVisibility = 0; 487 488 // State while inside of layoutAndPlaceSurfacesLocked(). 489 boolean mFocusMayChange; 490 491 Configuration mCurConfiguration = new Configuration(); 492 493 // This is held as long as we have the screen frozen, to give us time to 494 // perform a rotation animation when turning off shows the lock screen which 495 // changes the orientation. 496 private final PowerManager.WakeLock mScreenFrozenLock; 497 498 final AppTransition mAppTransition; 499 boolean mStartingIconInTransition = false; 500 boolean mSkipAppTransitionAnimation = false; 501 502 final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>(); 503 final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>(); 504 505 boolean mIsTouchDevice; 506 507 final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 508 final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics(); 509 final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics(); 510 final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics(); 511 512 final H mH = new H(); 513 514 final Choreographer mChoreographer = Choreographer.getInstance(); 515 516 WindowState mCurrentFocus = null; 517 WindowState mLastFocus = null; 518 519 /** This just indicates the window the input method is on top of, not 520 * necessarily the window its input is going to. */ 521 WindowState mInputMethodTarget = null; 522 523 /** If true hold off on modifying the animation layer of mInputMethodTarget */ 524 boolean mInputMethodTargetWaitingAnim; 525 int mInputMethodAnimLayerAdjustment; 526 527 WindowState mInputMethodWindow = null; 528 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>(); 529 530 boolean mHardKeyboardAvailable; 531 boolean mHardKeyboardEnabled; 532 OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; 533 534 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>(); 535 536 // If non-null, this is the currently visible window that is associated 537 // with the wallpaper. 538 WindowState mWallpaperTarget = null; 539 // If non-null, we are in the middle of animating from one wallpaper target 540 // to another, and this is the lower one in Z-order. 541 WindowState mLowerWallpaperTarget = null; 542 // If non-null, we are in the middle of animating from one wallpaper target 543 // to another, and this is the higher one in Z-order. 544 WindowState mUpperWallpaperTarget = null; 545 int mWallpaperAnimLayerAdjustment; 546 float mLastWallpaperX = -1; 547 float mLastWallpaperY = -1; 548 float mLastWallpaperXStep = -1; 549 float mLastWallpaperYStep = -1; 550 // This is set when we are waiting for a wallpaper to tell us it is done 551 // changing its scroll position. 552 WindowState mWaitingOnWallpaper; 553 // The last time we had a timeout when waiting for a wallpaper. 554 long mLastWallpaperTimeoutTime; 555 // We give a wallpaper up to 150ms to finish scrolling. 556 static final long WALLPAPER_TIMEOUT = 150; 557 // Time we wait after a timeout before trying to wait again. 558 static final long WALLPAPER_TIMEOUT_RECOVERY = 10000; 559 boolean mAnimateWallpaperWithTarget; 560 561 AppWindowToken mFocusedApp = null; 562 563 PowerManager mPowerManager; 564 PowerManagerInternal mPowerManagerInternal; 565 566 float mWindowAnimationScaleSetting = 1.0f; 567 float mTransitionAnimationScaleSetting = 1.0f; 568 float mAnimatorDurationScaleSetting = 1.0f; 569 boolean mAnimationsDisabled = false; 570 571 final InputManagerService mInputManager; 572 final DisplayManagerInternal mDisplayManagerInternal; 573 final DisplayManager mDisplayManager; 574 575 // Who is holding the screen on. 576 Session mHoldingScreenOn; 577 PowerManager.WakeLock mHoldingScreenWakeLock; 578 579 boolean mTurnOnScreen; 580 581 DragState mDragState = null; 582 583 // For frozen screen animations. 584 int mExitAnimId, mEnterAnimId; 585 586 /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple 587 * methods. */ 588 class LayoutFields { 589 static final int SET_UPDATE_ROTATION = 1 << 0; 590 static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1; 591 static final int SET_FORCE_HIDING_CHANGED = 1 << 2; 592 static final int SET_ORIENTATION_CHANGE_COMPLETE = 1 << 3; 593 static final int SET_TURN_ON_SCREEN = 1 << 4; 594 static final int SET_WALLPAPER_ACTION_PENDING = 1 << 5; 595 596 boolean mWallpaperForceHidingChanged = false; 597 boolean mWallpaperMayChange = false; 598 boolean mOrientationChangeComplete = true; 599 Object mLastWindowFreezeSource = null; 600 private Session mHoldScreen = null; 601 private boolean mObscured = false; 602 private boolean mSyswin = false; 603 private float mScreenBrightness = -1; 604 private float mButtonBrightness = -1; 605 private long mUserActivityTimeout = -1; 606 private boolean mUpdateRotation = false; 607 boolean mWallpaperActionPending = false; 608 609 // Set to true when the display contains content to show the user. 610 // When false, the display manager may choose to mirror or blank the display. 611 boolean mDisplayHasContent = false; 612 613 // Only set while traversing the default display based on its content. 614 // Affects the behavior of mirroring on secondary displays. 615 boolean mObscureApplicationContentOnSecondaryDisplays = false; 616 } 617 final LayoutFields mInnerFields = new LayoutFields(); 618 619 boolean mAnimationScheduled; 620 621 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this 622 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */ 623 private int mTransactionSequence; 624 625 /** Only do a maximum of 6 repeated layouts. After that quit */ 626 private int mLayoutRepeatCount; 627 628 final WindowAnimator mAnimator; 629 630 SparseArray<Task> mTaskIdToTask = new SparseArray<Task>(); 631 632 /** All of the TaskStacks in the window manager, unordered. For an ordered list call 633 * DisplayContent.getStacks(). */ 634 SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>(); 635 636 private final PointerEventDispatcher mPointerEventDispatcher; 637 638 private WindowContentFrameStats mTempWindowRenderStats; 639 640 final class DragInputEventReceiver extends InputEventReceiver { 641 public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { 642 super(inputChannel, looper); 643 } 644 645 @Override 646 public void onInputEvent(InputEvent event) { 647 boolean handled = false; 648 try { 649 if (event instanceof MotionEvent 650 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0 651 && mDragState != null) { 652 final MotionEvent motionEvent = (MotionEvent)event; 653 boolean endDrag = false; 654 final float newX = motionEvent.getRawX(); 655 final float newY = motionEvent.getRawY(); 656 657 switch (motionEvent.getAction()) { 658 case MotionEvent.ACTION_DOWN: { 659 if (DEBUG_DRAG) { 660 Slog.w(TAG, "Unexpected ACTION_DOWN in drag layer"); 661 } 662 } break; 663 664 case MotionEvent.ACTION_MOVE: { 665 synchronized (mWindowMap) { 666 // move the surface and tell the involved window(s) where we are 667 mDragState.notifyMoveLw(newX, newY); 668 } 669 } break; 670 671 case MotionEvent.ACTION_UP: { 672 if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at " 673 + newX + "," + newY); 674 synchronized (mWindowMap) { 675 endDrag = mDragState.notifyDropLw(newX, newY); 676 } 677 } break; 678 679 case MotionEvent.ACTION_CANCEL: { 680 if (DEBUG_DRAG) Slog.d(TAG, "Drag cancelled!"); 681 endDrag = true; 682 } break; 683 } 684 685 if (endDrag) { 686 if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state"); 687 // tell all the windows that the drag has ended 688 synchronized (mWindowMap) { 689 mDragState.endDragLw(); 690 } 691 } 692 693 handled = true; 694 } 695 } catch (Exception e) { 696 Slog.e(TAG, "Exception caught by drag handleMotion", e); 697 } finally { 698 finishInputEvent(event, handled); 699 } 700 } 701 } 702 703 /** 704 * Whether the UI is currently running in touch mode (not showing 705 * navigational focus because the user is directly pressing the screen). 706 */ 707 boolean mInTouchMode = true; 708 709 private ViewServer mViewServer; 710 private final ArrayList<WindowChangeListener> mWindowChangeListeners = 711 new ArrayList<WindowChangeListener>(); 712 private boolean mWindowsChanged = false; 713 714 public interface WindowChangeListener { 715 public void windowsChanged(); 716 public void focusChanged(); 717 } 718 719 final Configuration mTempConfiguration = new Configuration(); 720 721 // The desired scaling factor for compatible apps. 722 float mCompatibleScreenScale; 723 724 // If true, only the core apps and services are being launched because the device 725 // is in a special boot mode, such as being encrypted or waiting for a decryption password. 726 // For example, when this flag is true, there will be no wallpaper service. 727 final boolean mOnlyCore; 728 729 public static WindowManagerService main(final Context context, 730 final InputManagerService im, 731 final boolean haveInputMethods, final boolean showBootMsgs, 732 final boolean onlyCore) { 733 final WindowManagerService[] holder = new WindowManagerService[1]; 734 DisplayThread.getHandler().runWithScissors(new Runnable() { 735 @Override 736 public void run() { 737 holder[0] = new WindowManagerService(context, im, 738 haveInputMethods, showBootMsgs, onlyCore); 739 } 740 }, 0); 741 return holder[0]; 742 } 743 744 private void initPolicy() { 745 UiThread.getHandler().runWithScissors(new Runnable() { 746 @Override 747 public void run() { 748 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper()); 749 750 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this); 751 mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer() 752 * TYPE_LAYER_MULTIPLIER 753 + TYPE_LAYER_OFFSET; 754 } 755 }, 0); 756 } 757 758 private WindowManagerService(Context context, InputManagerService inputManager, 759 boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) { 760 mContext = context; 761 mHaveInputMethods = haveInputMethods; 762 mAllowBootMessages = showBootMsgs; 763 mOnlyCore = onlyCore; 764 mLimitedAlphaCompositing = context.getResources().getBoolean( 765 com.android.internal.R.bool.config_sf_limitedAlpha); 766 mInputManager = inputManager; // Must be before createDisplayContentLocked. 767 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); 768 mDisplaySettings = new DisplaySettings(context); 769 mDisplaySettings.readSettingsLocked(); 770 771 mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG)); 772 773 mFxSession = new SurfaceSession(); 774 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); 775 Display[] displays = mDisplayManager.getDisplays(); 776 for (Display display : displays) { 777 createDisplayContentLocked(display); 778 } 779 780 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy); 781 782 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 783 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 784 mPowerManagerInternal.setPolicy(mPolicy); // TODO: register as local service instead 785 mPowerManagerInternal.registerLowPowerModeObserver( 786 new PowerManagerInternal.LowPowerModeListener() { 787 @Override 788 public void onLowPowerModeChanged(boolean enabled) { 789 synchronized (mWindowMap) { 790 if (mAnimationsDisabled != enabled) { 791 mAnimationsDisabled = enabled; 792 dispatchNewAnimatorScaleLocked(null); 793 } 794 } 795 } 796 }); 797 mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled(); 798 mScreenFrozenLock = mPowerManager.newWakeLock( 799 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN"); 800 mScreenFrozenLock.setReferenceCounted(false); 801 802 mAppTransition = new AppTransition(context, mH); 803 804 mActivityManager = ActivityManagerNative.getDefault(); 805 mBatteryStats = BatteryStatsService.getService(); 806 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 807 mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null, 808 new AppOpsManager.OnOpChangedInternalListener() { 809 @Override 810 public void onOpChanged(int op, String packageName) { 811 updateAppOpsState(); 812 } 813 } 814 ); 815 816 // Get persisted window scale setting 817 mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 818 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 819 mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 820 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting); 821 setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(), 822 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting)); 823 824 // Track changes to DevicePolicyManager state so we can enable/disable keyguard. 825 IntentFilter filter = new IntentFilter(); 826 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 827 mContext.registerReceiver(mBroadcastReceiver, filter); 828 829 mHoldingScreenWakeLock = mPowerManager.newWakeLock( 830 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG); 831 mHoldingScreenWakeLock.setReferenceCounted(false); 832 833 mAnimator = new WindowAnimator(this); 834 835 LocalServices.addService(WindowManagerInternal.class, new LocalService()); 836 initPolicy(); 837 838 // Add ourself to the Watchdog monitors. 839 Watchdog.getInstance().addMonitor(this); 840 841 SurfaceControl.openTransaction(); 842 try { 843 createWatermarkInTransaction(); 844 mFocusedStackFrame = new FocusedStackFrame( 845 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 846 } finally { 847 SurfaceControl.closeTransaction(); 848 } 849 850 showCircularDisplayMaskIfNeeded(); 851 } 852 853 public InputMonitor getInputMonitor() { 854 return mInputMonitor; 855 } 856 857 @Override 858 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 859 throws RemoteException { 860 try { 861 return super.onTransact(code, data, reply, flags); 862 } catch (RuntimeException e) { 863 // The window manager only throws security exceptions, so let's 864 // log all others. 865 if (!(e instanceof SecurityException)) { 866 Slog.wtf(TAG, "Window Manager Crash", e); 867 } 868 throw e; 869 } 870 } 871 872 private void placeWindowAfter(WindowState pos, WindowState window) { 873 final WindowList windows = pos.getWindowList(); 874 final int i = windows.indexOf(pos); 875 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 876 TAG, "Adding window " + window + " at " 877 + (i+1) + " of " + windows.size() + " (after " + pos + ")"); 878 windows.add(i+1, window); 879 mWindowsChanged = true; 880 } 881 882 private void placeWindowBefore(WindowState pos, WindowState window) { 883 final WindowList windows = pos.getWindowList(); 884 int i = windows.indexOf(pos); 885 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 886 TAG, "Adding window " + window + " at " 887 + i + " of " + windows.size() + " (before " + pos + ")"); 888 if (i < 0) { 889 Slog.w(TAG, "placeWindowBefore: Unable to find " + pos + " in " + windows); 890 i = 0; 891 } 892 windows.add(i, window); 893 mWindowsChanged = true; 894 } 895 896 //This method finds out the index of a window that has the same app token as 897 //win. used for z ordering the windows in mWindows 898 private int findIdxBasedOnAppTokens(WindowState win) { 899 WindowList windows = win.getWindowList(); 900 for(int j = windows.size() - 1; j >= 0; j--) { 901 WindowState wentry = windows.get(j); 902 if(wentry.mAppToken == win.mAppToken) { 903 return j; 904 } 905 } 906 return -1; 907 } 908 909 /** 910 * Return the list of Windows from the passed token on the given Display. 911 * @param token The token with all the windows. 912 * @param displayContent The display we are interested in. 913 * @return List of windows from token that are on displayContent. 914 */ 915 WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) { 916 final WindowList windowList = new WindowList(); 917 final int count = token.windows.size(); 918 for (int i = 0; i < count; i++) { 919 final WindowState win = token.windows.get(i); 920 if (win.getDisplayContent() == displayContent) { 921 windowList.add(win); 922 } 923 } 924 return windowList; 925 } 926 927 /** 928 * Recursive search through a WindowList and all of its windows' children. 929 * @param targetWin The window to search for. 930 * @param windows The list to search. 931 * @return The index of win in windows or of the window that is an ancestor of win. 932 */ 933 private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) { 934 for (int i = windows.size() - 1; i >= 0; i--) { 935 final WindowState w = windows.get(i); 936 if (w == targetWin) { 937 return i; 938 } 939 if (!w.mChildWindows.isEmpty()) { 940 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) { 941 return i; 942 } 943 } 944 } 945 return -1; 946 } 947 948 private int addAppWindowToListLocked(final WindowState win) { 949 final IWindow client = win.mClient; 950 final WindowToken token = win.mToken; 951 final DisplayContent displayContent = win.getDisplayContent(); 952 if (displayContent == null) { 953 // It doesn't matter this display is going away. 954 return 0; 955 } 956 957 final WindowList windows = win.getWindowList(); 958 final int N = windows.size(); 959 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 960 int tokenWindowsPos = 0; 961 int windowListPos = tokenWindowList.size(); 962 if (!tokenWindowList.isEmpty()) { 963 // If this application has existing windows, we 964 // simply place the new window on top of them... but 965 // keep the starting window on top. 966 if (win.mAttrs.type == TYPE_BASE_APPLICATION) { 967 // Base windows go behind everything else. 968 WindowState lowestWindow = tokenWindowList.get(0); 969 placeWindowBefore(lowestWindow, win); 970 tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows); 971 } else { 972 AppWindowToken atoken = win.mAppToken; 973 WindowState lastWindow = tokenWindowList.get(windowListPos - 1); 974 if (atoken != null && lastWindow == atoken.startingWindow) { 975 placeWindowBefore(lastWindow, win); 976 tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows); 977 } else { 978 int newIdx = findIdxBasedOnAppTokens(win); 979 //there is a window above this one associated with the same 980 //apptoken note that the window could be a floating window 981 //that was created later or a window at the top of the list of 982 //windows associated with this token. 983 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 984 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " + 985 N); 986 windows.add(newIdx + 1, win); 987 if (newIdx < 0) { 988 // No window from token found on win's display. 989 tokenWindowsPos = 0; 990 } else { 991 tokenWindowsPos = indexOfWinInWindowList( 992 windows.get(newIdx), token.windows) + 1; 993 } 994 mWindowsChanged = true; 995 } 996 } 997 return tokenWindowsPos; 998 } 999 1000 // No windows from this token on this display 1001 if (localLOGV) Slog.v(TAG, "Figuring out where to add app window " + client.asBinder() 1002 + " (token=" + token + ")"); 1003 // Figure out where the window should go, based on the 1004 // order of applications. 1005 WindowState pos = null; 1006 1007 final ArrayList<Task> tasks = displayContent.getTasks(); 1008 int taskNdx; 1009 int tokenNdx = -1; 1010 for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 1011 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1012 for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 1013 final AppWindowToken t = tokens.get(tokenNdx); 1014 if (t == token) { 1015 --tokenNdx; 1016 if (tokenNdx < 0) { 1017 --taskNdx; 1018 if (taskNdx >= 0) { 1019 tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1; 1020 } 1021 } 1022 break; 1023 } 1024 1025 // We haven't reached the token yet; if this token 1026 // is not going to the bottom and has windows on this display, we can 1027 // use it as an anchor for when we do reach the token. 1028 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1029 if (!t.sendingToBottom && tokenWindowList.size() > 0) { 1030 pos = tokenWindowList.get(0); 1031 } 1032 } 1033 if (tokenNdx >= 0) { 1034 // early exit 1035 break; 1036 } 1037 } 1038 1039 // We now know the index into the apps. If we found 1040 // an app window above, that gives us the position; else 1041 // we need to look some more. 1042 if (pos != null) { 1043 // Move behind any windows attached to this one. 1044 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1045 if (atoken != null) { 1046 tokenWindowList = 1047 getTokenWindowsOnDisplay(atoken, displayContent); 1048 final int NC = tokenWindowList.size(); 1049 if (NC > 0) { 1050 WindowState bottom = tokenWindowList.get(0); 1051 if (bottom.mSubLayer < 0) { 1052 pos = bottom; 1053 } 1054 } 1055 } 1056 placeWindowBefore(pos, win); 1057 return tokenWindowsPos; 1058 } 1059 1060 // Continue looking down until we find the first 1061 // token that has windows on this display. 1062 for ( ; taskNdx >= 0; --taskNdx) { 1063 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1064 for ( ; tokenNdx >= 0; --tokenNdx) { 1065 final AppWindowToken t = tokens.get(tokenNdx); 1066 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1067 final int NW = tokenWindowList.size(); 1068 if (NW > 0) { 1069 pos = tokenWindowList.get(NW-1); 1070 break; 1071 } 1072 } 1073 if (tokenNdx >= 0) { 1074 // found 1075 break; 1076 } 1077 } 1078 1079 if (pos != null) { 1080 // Move in front of any windows attached to this 1081 // one. 1082 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1083 if (atoken != null) { 1084 final int NC = atoken.windows.size(); 1085 if (NC > 0) { 1086 WindowState top = atoken.windows.get(NC-1); 1087 if (top.mSubLayer >= 0) { 1088 pos = top; 1089 } 1090 } 1091 } 1092 placeWindowAfter(pos, win); 1093 return tokenWindowsPos; 1094 } 1095 1096 // Just search for the start of this layer. 1097 final int myLayer = win.mBaseLayer; 1098 int i; 1099 for (i = 0; i < N; i++) { 1100 WindowState w = windows.get(i); 1101 if (w.mBaseLayer > myLayer) { 1102 break; 1103 } 1104 } 1105 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1106 "Based on layer: Adding window " + win + " at " + i + " of " + N); 1107 windows.add(i, win); 1108 mWindowsChanged = true; 1109 return tokenWindowsPos; 1110 } 1111 1112 private void addFreeWindowToListLocked(final WindowState win) { 1113 final WindowList windows = win.getWindowList(); 1114 1115 // Figure out where window should go, based on layer. 1116 final int myLayer = win.mBaseLayer; 1117 int i; 1118 for (i = windows.size() - 1; i >= 0; i--) { 1119 if (windows.get(i).mBaseLayer <= myLayer) { 1120 break; 1121 } 1122 } 1123 i++; 1124 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1125 "Free window: Adding window " + win + " at " + i + " of " + windows.size()); 1126 windows.add(i, win); 1127 mWindowsChanged = true; 1128 } 1129 1130 private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) { 1131 final WindowToken token = win.mToken; 1132 final DisplayContent displayContent = win.getDisplayContent(); 1133 if (displayContent == null) { 1134 return; 1135 } 1136 final WindowState attached = win.mAttachedWindow; 1137 1138 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 1139 1140 // Figure out this window's ordering relative to the window 1141 // it is attached to. 1142 final int NA = tokenWindowList.size(); 1143 final int sublayer = win.mSubLayer; 1144 int largestSublayer = Integer.MIN_VALUE; 1145 WindowState windowWithLargestSublayer = null; 1146 int i; 1147 for (i = 0; i < NA; i++) { 1148 WindowState w = tokenWindowList.get(i); 1149 final int wSublayer = w.mSubLayer; 1150 if (wSublayer >= largestSublayer) { 1151 largestSublayer = wSublayer; 1152 windowWithLargestSublayer = w; 1153 } 1154 if (sublayer < 0) { 1155 // For negative sublayers, we go below all windows 1156 // in the same sublayer. 1157 if (wSublayer >= sublayer) { 1158 if (addToToken) { 1159 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1160 token.windows.add(i, win); 1161 } 1162 placeWindowBefore(wSublayer >= 0 ? attached : w, win); 1163 break; 1164 } 1165 } else { 1166 // For positive sublayers, we go above all windows 1167 // in the same sublayer. 1168 if (wSublayer > sublayer) { 1169 if (addToToken) { 1170 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1171 token.windows.add(i, win); 1172 } 1173 placeWindowBefore(w, win); 1174 break; 1175 } 1176 } 1177 } 1178 if (i >= NA) { 1179 if (addToToken) { 1180 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1181 token.windows.add(win); 1182 } 1183 if (sublayer < 0) { 1184 placeWindowBefore(attached, win); 1185 } else { 1186 placeWindowAfter(largestSublayer >= 0 1187 ? windowWithLargestSublayer 1188 : attached, 1189 win); 1190 } 1191 } 1192 } 1193 1194 private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) { 1195 if (DEBUG_FOCUS_LIGHT) Slog.d(TAG, "addWindowToListInOrderLocked: win=" + win + 1196 " Callers=" + Debug.getCallers(4)); 1197 if (win.mAttachedWindow == null) { 1198 final WindowToken token = win.mToken; 1199 int tokenWindowsPos = 0; 1200 if (token.appWindowToken != null) { 1201 tokenWindowsPos = addAppWindowToListLocked(win); 1202 } else { 1203 addFreeWindowToListLocked(win); 1204 } 1205 if (addToToken) { 1206 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1207 token.windows.add(tokenWindowsPos, win); 1208 } 1209 } else { 1210 addAttachedWindowToListLocked(win, addToToken); 1211 } 1212 1213 if (win.mAppToken != null && addToToken) { 1214 win.mAppToken.allAppWindows.add(win); 1215 } 1216 } 1217 1218 static boolean canBeImeTarget(WindowState w) { 1219 final int fl = w.mAttrs.flags 1220 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); 1221 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM) 1222 || w.mAttrs.type == TYPE_APPLICATION_STARTING) { 1223 if (DEBUG_INPUT_METHOD) { 1224 Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding()); 1225 if (!w.isVisibleOrAdding()) { 1226 Slog.i(TAG, " mSurface=" + w.mWinAnimator.mSurfaceControl 1227 + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility 1228 + " policyVis=" + w.mPolicyVisibility 1229 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim 1230 + " attachHid=" + w.mAttachedHidden 1231 + " exiting=" + w.mExiting + " destroying=" + w.mDestroying); 1232 if (w.mAppToken != null) { 1233 Slog.i(TAG, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested); 1234 } 1235 } 1236 } 1237 return w.isVisibleOrAdding(); 1238 } 1239 return false; 1240 } 1241 1242 /** 1243 * Dig through the WindowStates and find the one that the Input Method will target. 1244 * @param willMove 1245 * @return The index+1 in mWindows of the discovered target. 1246 */ 1247 int findDesiredInputMethodWindowIndexLocked(boolean willMove) { 1248 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the 1249 // same display. Or even when the current IME/target are not on the same screen as the next 1250 // IME/target. For now only look for input windows on the main screen. 1251 WindowList windows = getDefaultWindowListLocked(); 1252 WindowState w = null; 1253 int i; 1254 for (i = windows.size() - 1; i >= 0; --i) { 1255 WindowState win = windows.get(i); 1256 1257 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i 1258 + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags)); 1259 if (canBeImeTarget(win)) { 1260 w = win; 1261 //Slog.i(TAG, "Putting input method here!"); 1262 1263 // Yet more tricksyness! If this window is a "starting" 1264 // window, we do actually want to be on top of it, but 1265 // it is not -really- where input will go. So if the caller 1266 // is not actually looking to move the IME, look down below 1267 // for a real window to target... 1268 if (!willMove 1269 && w.mAttrs.type == TYPE_APPLICATION_STARTING 1270 && i > 0) { 1271 WindowState wb = windows.get(i-1); 1272 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) { 1273 i--; 1274 w = wb; 1275 } 1276 } 1277 break; 1278 } 1279 } 1280 1281 // Now w is either mWindows[0] or an IME (or null if mWindows is empty). 1282 1283 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w); 1284 1285 // Now, a special case -- if the last target's window is in the 1286 // process of exiting, and is above the new target, keep on the 1287 // last target to avoid flicker. Consider for example a Dialog with 1288 // the IME shown: when the Dialog is dismissed, we want to keep 1289 // the IME above it until it is completely gone so it doesn't drop 1290 // behind the dialog or its full-screen scrim. 1291 final WindowState curTarget = mInputMethodTarget; 1292 if (curTarget != null 1293 && curTarget.isDisplayedLw() 1294 && curTarget.isClosing() 1295 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) { 1296 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing"); 1297 return windows.indexOf(curTarget) + 1; 1298 } 1299 1300 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target=" 1301 + w + " willMove=" + willMove); 1302 1303 if (willMove && w != null) { 1304 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken; 1305 if (token != null) { 1306 1307 // Now some fun for dealing with window animations that 1308 // modify the Z order. We need to look at all windows below 1309 // the current target that are in this app, finding the highest 1310 // visible one in layering. 1311 WindowState highestTarget = null; 1312 int highestPos = 0; 1313 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) { 1314 WindowList curWindows = curTarget.getWindowList(); 1315 int pos = curWindows.indexOf(curTarget); 1316 while (pos >= 0) { 1317 WindowState win = curWindows.get(pos); 1318 if (win.mAppToken != token) { 1319 break; 1320 } 1321 if (!win.mRemoved) { 1322 if (highestTarget == null || win.mWinAnimator.mAnimLayer > 1323 highestTarget.mWinAnimator.mAnimLayer) { 1324 highestTarget = win; 1325 highestPos = pos; 1326 } 1327 } 1328 pos--; 1329 } 1330 } 1331 1332 if (highestTarget != null) { 1333 if (DEBUG_INPUT_METHOD) Slog.v(TAG, mAppTransition + " " + highestTarget 1334 + " animating=" + highestTarget.mWinAnimator.isAnimating() 1335 + " layer=" + highestTarget.mWinAnimator.mAnimLayer 1336 + " new layer=" + w.mWinAnimator.mAnimLayer); 1337 1338 if (mAppTransition.isTransitionSet()) { 1339 // If we are currently setting up for an animation, 1340 // hold everything until we can find out what will happen. 1341 mInputMethodTargetWaitingAnim = true; 1342 mInputMethodTarget = highestTarget; 1343 return highestPos + 1; 1344 } else if (highestTarget.mWinAnimator.isAnimating() && 1345 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) { 1346 // If the window we are currently targeting is involved 1347 // with an animation, and it is on top of the next target 1348 // we will be over, then hold off on moving until 1349 // that is done. 1350 mInputMethodTargetWaitingAnim = true; 1351 mInputMethodTarget = highestTarget; 1352 return highestPos + 1; 1353 } 1354 } 1355 } 1356 } 1357 1358 //Slog.i(TAG, "Placing input method @" + (i+1)); 1359 if (w != null) { 1360 if (willMove) { 1361 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to " 1362 + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4))); 1363 mInputMethodTarget = w; 1364 mInputMethodTargetWaitingAnim = false; 1365 if (w.mAppToken != null) { 1366 setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment); 1367 } else { 1368 setInputMethodAnimLayerAdjustment(0); 1369 } 1370 } 1371 return i+1; 1372 } 1373 if (willMove) { 1374 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null." 1375 + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4))); 1376 mInputMethodTarget = null; 1377 setInputMethodAnimLayerAdjustment(0); 1378 } 1379 return -1; 1380 } 1381 1382 void addInputMethodWindowToListLocked(WindowState win) { 1383 int pos = findDesiredInputMethodWindowIndexLocked(true); 1384 if (pos >= 0) { 1385 win.mTargetAppToken = mInputMethodTarget.mAppToken; 1386 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 1387 TAG, "Adding input method window " + win + " at " + pos); 1388 // TODO(multidisplay): IMEs are only supported on the default display. 1389 getDefaultWindowListLocked().add(pos, win); 1390 mWindowsChanged = true; 1391 moveInputMethodDialogsLocked(pos+1); 1392 return; 1393 } 1394 win.mTargetAppToken = null; 1395 addWindowToListInOrderLocked(win, true); 1396 moveInputMethodDialogsLocked(pos); 1397 } 1398 1399 void setInputMethodAnimLayerAdjustment(int adj) { 1400 if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj); 1401 mInputMethodAnimLayerAdjustment = adj; 1402 WindowState imw = mInputMethodWindow; 1403 if (imw != null) { 1404 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj; 1405 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw 1406 + " anim layer: " + imw.mWinAnimator.mAnimLayer); 1407 int wi = imw.mChildWindows.size(); 1408 while (wi > 0) { 1409 wi--; 1410 WindowState cw = imw.mChildWindows.get(wi); 1411 cw.mWinAnimator.mAnimLayer = cw.mLayer + adj; 1412 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw 1413 + " anim layer: " + cw.mWinAnimator.mAnimLayer); 1414 } 1415 } 1416 int di = mInputMethodDialogs.size(); 1417 while (di > 0) { 1418 di --; 1419 imw = mInputMethodDialogs.get(di); 1420 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj; 1421 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw 1422 + " anim layer: " + imw.mWinAnimator.mAnimLayer); 1423 } 1424 } 1425 1426 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) { 1427 WindowList windows = win.getWindowList(); 1428 int wpos = windows.indexOf(win); 1429 if (wpos >= 0) { 1430 if (wpos < interestingPos) interestingPos--; 1431 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win); 1432 windows.remove(wpos); 1433 mWindowsChanged = true; 1434 int NC = win.mChildWindows.size(); 1435 while (NC > 0) { 1436 NC--; 1437 WindowState cw = win.mChildWindows.get(NC); 1438 int cpos = windows.indexOf(cw); 1439 if (cpos >= 0) { 1440 if (cpos < interestingPos) interestingPos--; 1441 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at " 1442 + cpos + ": " + cw); 1443 windows.remove(cpos); 1444 } 1445 } 1446 } 1447 return interestingPos; 1448 } 1449 1450 private void reAddWindowToListInOrderLocked(WindowState win) { 1451 addWindowToListInOrderLocked(win, false); 1452 // This is a hack to get all of the child windows added as well 1453 // at the right position. Child windows should be rare and 1454 // this case should be rare, so it shouldn't be that big a deal. 1455 WindowList windows = win.getWindowList(); 1456 int wpos = windows.indexOf(win); 1457 if (wpos >= 0) { 1458 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win); 1459 windows.remove(wpos); 1460 mWindowsChanged = true; 1461 reAddWindowLocked(wpos, win); 1462 } 1463 } 1464 1465 void logWindowList(final WindowList windows, String prefix) { 1466 int N = windows.size(); 1467 while (N > 0) { 1468 N--; 1469 Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N)); 1470 } 1471 } 1472 1473 void moveInputMethodDialogsLocked(int pos) { 1474 ArrayList<WindowState> dialogs = mInputMethodDialogs; 1475 1476 // TODO(multidisplay): IMEs are only supported on the default display. 1477 WindowList windows = getDefaultWindowListLocked(); 1478 final int N = dialogs.size(); 1479 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos); 1480 for (int i=0; i<N; i++) { 1481 pos = tmpRemoveWindowLocked(pos, dialogs.get(i)); 1482 } 1483 if (DEBUG_INPUT_METHOD) { 1484 Slog.v(TAG, "Window list w/pos=" + pos); 1485 logWindowList(windows, " "); 1486 } 1487 1488 if (pos >= 0) { 1489 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken; 1490 // Skip windows owned by the input method. 1491 if (mInputMethodWindow != null) { 1492 while (pos < windows.size()) { 1493 WindowState wp = windows.get(pos); 1494 if (wp == mInputMethodWindow || wp.mAttachedWindow == mInputMethodWindow) { 1495 pos++; 1496 continue; 1497 } 1498 break; 1499 } 1500 } 1501 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos); 1502 for (int i=0; i<N; i++) { 1503 WindowState win = dialogs.get(i); 1504 win.mTargetAppToken = targetAppToken; 1505 pos = reAddWindowLocked(pos, win); 1506 } 1507 if (DEBUG_INPUT_METHOD) { 1508 Slog.v(TAG, "Final window list:"); 1509 logWindowList(windows, " "); 1510 } 1511 return; 1512 } 1513 for (int i=0; i<N; i++) { 1514 WindowState win = dialogs.get(i); 1515 win.mTargetAppToken = null; 1516 reAddWindowToListInOrderLocked(win); 1517 if (DEBUG_INPUT_METHOD) { 1518 Slog.v(TAG, "No IM target, final list:"); 1519 logWindowList(windows, " "); 1520 } 1521 } 1522 } 1523 1524 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) { 1525 final WindowState imWin = mInputMethodWindow; 1526 final int DN = mInputMethodDialogs.size(); 1527 if (imWin == null && DN == 0) { 1528 return false; 1529 } 1530 1531 // TODO(multidisplay): IMEs are only supported on the default display. 1532 WindowList windows = getDefaultWindowListLocked(); 1533 1534 int imPos = findDesiredInputMethodWindowIndexLocked(true); 1535 if (imPos >= 0) { 1536 // In this case, the input method windows are to be placed 1537 // immediately above the window they are targeting. 1538 1539 // First check to see if the input method windows are already 1540 // located here, and contiguous. 1541 final int N = windows.size(); 1542 WindowState firstImWin = imPos < N 1543 ? windows.get(imPos) : null; 1544 1545 // Figure out the actual input method window that should be 1546 // at the bottom of their stack. 1547 WindowState baseImWin = imWin != null 1548 ? imWin : mInputMethodDialogs.get(0); 1549 if (baseImWin.mChildWindows.size() > 0) { 1550 WindowState cw = baseImWin.mChildWindows.get(0); 1551 if (cw.mSubLayer < 0) baseImWin = cw; 1552 } 1553 1554 if (firstImWin == baseImWin) { 1555 // The windows haven't moved... but are they still contiguous? 1556 // First find the top IM window. 1557 int pos = imPos+1; 1558 while (pos < N) { 1559 if (!(windows.get(pos)).mIsImWindow) { 1560 break; 1561 } 1562 pos++; 1563 } 1564 pos++; 1565 // Now there should be no more input method windows above. 1566 while (pos < N) { 1567 if ((windows.get(pos)).mIsImWindow) { 1568 break; 1569 } 1570 pos++; 1571 } 1572 if (pos >= N) { 1573 // Z order is good. 1574 // The IM target window may be changed, so update the mTargetAppToken. 1575 if (imWin != null) { 1576 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1577 } 1578 return false; 1579 } 1580 } 1581 1582 if (imWin != null) { 1583 if (DEBUG_INPUT_METHOD) { 1584 Slog.v(TAG, "Moving IM from " + imPos); 1585 logWindowList(windows, " "); 1586 } 1587 imPos = tmpRemoveWindowLocked(imPos, imWin); 1588 if (DEBUG_INPUT_METHOD) { 1589 Slog.v(TAG, "List after removing with new pos " + imPos + ":"); 1590 logWindowList(windows, " "); 1591 } 1592 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1593 reAddWindowLocked(imPos, imWin); 1594 if (DEBUG_INPUT_METHOD) { 1595 Slog.v(TAG, "List after moving IM to " + imPos + ":"); 1596 logWindowList(windows, " "); 1597 } 1598 if (DN > 0) moveInputMethodDialogsLocked(imPos+1); 1599 } else { 1600 moveInputMethodDialogsLocked(imPos); 1601 } 1602 1603 } else { 1604 // In this case, the input method windows go in a fixed layer, 1605 // because they aren't currently associated with a focus window. 1606 1607 if (imWin != null) { 1608 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos); 1609 tmpRemoveWindowLocked(0, imWin); 1610 imWin.mTargetAppToken = null; 1611 reAddWindowToListInOrderLocked(imWin); 1612 if (DEBUG_INPUT_METHOD) { 1613 Slog.v(TAG, "List with no IM target:"); 1614 logWindowList(windows, " "); 1615 } 1616 if (DN > 0) moveInputMethodDialogsLocked(-1); 1617 } else { 1618 moveInputMethodDialogsLocked(-1); 1619 } 1620 1621 } 1622 1623 if (needAssignLayers) { 1624 assignLayersLocked(windows); 1625 } 1626 1627 return true; 1628 } 1629 1630 final boolean isWallpaperVisible(WindowState wallpaperTarget) { 1631 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured=" 1632 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??") 1633 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null) 1634 ? wallpaperTarget.mAppToken.mAppAnimator.animation : null) 1635 + " upper=" + mUpperWallpaperTarget 1636 + " lower=" + mLowerWallpaperTarget); 1637 return (wallpaperTarget != null 1638 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null 1639 && wallpaperTarget.mAppToken.mAppAnimator.animation != null))) 1640 || mUpperWallpaperTarget != null 1641 || mLowerWallpaperTarget != null; 1642 } 1643 1644 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1; 1645 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2; 1646 1647 int adjustWallpaperWindowsLocked() { 1648 mInnerFields.mWallpaperMayChange = false; 1649 boolean targetChanged = false; 1650 1651 // TODO(multidisplay): Wallpapers on main screen only. 1652 final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo(); 1653 final int dw = displayInfo.logicalWidth; 1654 final int dh = displayInfo.logicalHeight; 1655 1656 // First find top-most window that has asked to be on top of the 1657 // wallpaper; all wallpapers go behind it. 1658 final WindowList windows = getDefaultWindowListLocked(); 1659 int N = windows.size(); 1660 WindowState w = null; 1661 WindowState foundW = null; 1662 int foundI = 0; 1663 WindowState topCurW = null; 1664 int topCurI = 0; 1665 int windowDetachedI = -1; 1666 int i = N; 1667 while (i > 0) { 1668 i--; 1669 w = windows.get(i); 1670 if ((w.mAttrs.type == TYPE_WALLPAPER)) { 1671 if (topCurW == null) { 1672 topCurW = w; 1673 topCurI = i; 1674 } 1675 continue; 1676 } 1677 topCurW = null; 1678 if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) { 1679 // If this window's app token is hidden and not animating, 1680 // it is of no interest to us. 1681 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) { 1682 if (DEBUG_WALLPAPER) Slog.v(TAG, 1683 "Skipping hidden and not animating token: " + w); 1684 continue; 1685 } 1686 } 1687 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen=" 1688 + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState); 1689 if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isOnScreen() 1690 && (mWallpaperTarget == w || w.isDrawFinishedLw())) { 1691 if (DEBUG_WALLPAPER) Slog.v(TAG, 1692 "Found wallpaper target: #" + i + "=" + w); 1693 foundW = w; 1694 foundI = i; 1695 if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) { 1696 // The current wallpaper target is animating, so we'll 1697 // look behind it for another possible target and figure 1698 // out what is going on below. 1699 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w 1700 + ": token animating, looking behind."); 1701 continue; 1702 } 1703 break; 1704 } else if (w == mAnimator.mWindowDetachedWallpaper) { 1705 windowDetachedI = i; 1706 } 1707 } 1708 1709 if (foundW == null && windowDetachedI >= 0) { 1710 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 1711 "Found animating detached wallpaper activity: #" + i + "=" + w); 1712 foundW = w; 1713 foundI = windowDetachedI; 1714 } 1715 1716 if (mWallpaperTarget != foundW 1717 && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) { 1718 if (DEBUG_WALLPAPER_LIGHT) { 1719 Slog.v(TAG, "New wallpaper target: " + foundW 1720 + " oldTarget: " + mWallpaperTarget); 1721 } 1722 1723 mLowerWallpaperTarget = null; 1724 mUpperWallpaperTarget = null; 1725 1726 WindowState oldW = mWallpaperTarget; 1727 mWallpaperTarget = foundW; 1728 targetChanged = true; 1729 1730 // Now what is happening... if the current and new targets are 1731 // animating, then we are in our super special mode! 1732 if (foundW != null && oldW != null) { 1733 boolean oldAnim = oldW.isAnimatingLw(); 1734 boolean foundAnim = foundW.isAnimatingLw(); 1735 if (DEBUG_WALLPAPER_LIGHT) { 1736 Slog.v(TAG, "New animation: " + foundAnim 1737 + " old animation: " + oldAnim); 1738 } 1739 if (foundAnim && oldAnim) { 1740 int oldI = windows.indexOf(oldW); 1741 if (DEBUG_WALLPAPER_LIGHT) { 1742 Slog.v(TAG, "New i: " + foundI + " old i: " + oldI); 1743 } 1744 if (oldI >= 0) { 1745 if (DEBUG_WALLPAPER_LIGHT) { 1746 Slog.v(TAG, "Animating wallpapers: old#" + oldI 1747 + "=" + oldW + "; new#" + foundI 1748 + "=" + foundW); 1749 } 1750 1751 // Set the new target correctly. 1752 if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) { 1753 if (DEBUG_WALLPAPER_LIGHT) { 1754 Slog.v(TAG, "Old wallpaper still the target."); 1755 } 1756 mWallpaperTarget = oldW; 1757 foundW = oldW; 1758 foundI = oldI; 1759 } 1760 // Now set the upper and lower wallpaper targets 1761 // correctly, and make sure that we are positioning 1762 // the wallpaper below the lower. 1763 else if (foundI > oldI) { 1764 // The new target is on top of the old one. 1765 if (DEBUG_WALLPAPER_LIGHT) { 1766 Slog.v(TAG, "Found target above old target."); 1767 } 1768 mUpperWallpaperTarget = foundW; 1769 mLowerWallpaperTarget = oldW; 1770 foundW = oldW; 1771 foundI = oldI; 1772 } else { 1773 // The new target is below the old one. 1774 if (DEBUG_WALLPAPER_LIGHT) { 1775 Slog.v(TAG, "Found target below old target."); 1776 } 1777 mUpperWallpaperTarget = oldW; 1778 mLowerWallpaperTarget = foundW; 1779 } 1780 } 1781 } 1782 } 1783 1784 } else if (mLowerWallpaperTarget != null) { 1785 // Is it time to stop animating? 1786 if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) { 1787 if (DEBUG_WALLPAPER_LIGHT) { 1788 Slog.v(TAG, "No longer animating wallpaper targets!"); 1789 } 1790 mLowerWallpaperTarget = null; 1791 mUpperWallpaperTarget = null; 1792 mWallpaperTarget = foundW; 1793 targetChanged = true; 1794 } 1795 } 1796 1797 boolean visible = foundW != null; 1798 if (visible) { 1799 // The window is visible to the compositor... but is it visible 1800 // to the user? That is what the wallpaper cares about. 1801 visible = isWallpaperVisible(foundW); 1802 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible); 1803 1804 // If the wallpaper target is animating, we may need to copy 1805 // its layer adjustment. Only do this if we are not transfering 1806 // between two wallpaper targets. 1807 mWallpaperAnimLayerAdjustment = 1808 (mLowerWallpaperTarget == null && foundW.mAppToken != null) 1809 ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0; 1810 1811 final int maxLayer = mPolicy.getMaxWallpaperLayer() 1812 * TYPE_LAYER_MULTIPLIER 1813 + TYPE_LAYER_OFFSET; 1814 1815 // Now w is the window we are supposed to be behind... but we 1816 // need to be sure to also be behind any of its attached windows, 1817 // AND any starting window associated with it, AND below the 1818 // maximum layer the policy allows for wallpapers. 1819 while (foundI > 0) { 1820 WindowState wb = windows.get(foundI-1); 1821 if (wb.mBaseLayer < maxLayer && 1822 wb.mAttachedWindow != foundW && 1823 (foundW.mAttachedWindow == null || 1824 wb.mAttachedWindow != foundW.mAttachedWindow) && 1825 (wb.mAttrs.type != TYPE_APPLICATION_STARTING || 1826 foundW.mToken == null || wb.mToken != foundW.mToken)) { 1827 // This window is not related to the previous one in any 1828 // interesting way, so stop here. 1829 break; 1830 } 1831 foundW = wb; 1832 foundI--; 1833 } 1834 } else { 1835 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target"); 1836 } 1837 1838 if (foundW == null && topCurW != null) { 1839 // There is no wallpaper target, so it goes at the bottom. 1840 // We will assume it is the same place as last time, if known. 1841 foundW = topCurW; 1842 foundI = topCurI+1; 1843 } else { 1844 // Okay i is the position immediately above the wallpaper. Look at 1845 // what is below it for later. 1846 foundW = foundI > 0 ? windows.get(foundI-1) : null; 1847 } 1848 1849 if (visible) { 1850 if (mWallpaperTarget.mWallpaperX >= 0) { 1851 mLastWallpaperX = mWallpaperTarget.mWallpaperX; 1852 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep; 1853 } 1854 if (mWallpaperTarget.mWallpaperY >= 0) { 1855 mLastWallpaperY = mWallpaperTarget.mWallpaperY; 1856 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep; 1857 } 1858 } 1859 1860 // Start stepping backwards from here, ensuring that our wallpaper windows 1861 // are correctly placed. 1862 int changed = 0; 1863 int curTokenIndex = mWallpaperTokens.size(); 1864 while (curTokenIndex > 0) { 1865 curTokenIndex--; 1866 WindowToken token = mWallpaperTokens.get(curTokenIndex); 1867 if (token.hidden == visible) { 1868 if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, 1869 "Wallpaper token " + token + " hidden=" + !visible); 1870 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED; 1871 token.hidden = !visible; 1872 // Need to do a layout to ensure the wallpaper now has the 1873 // correct size. 1874 getDefaultDisplayContentLocked().layoutNeeded = true; 1875 } 1876 1877 int curWallpaperIndex = token.windows.size(); 1878 while (curWallpaperIndex > 0) { 1879 curWallpaperIndex--; 1880 WindowState wallpaper = token.windows.get(curWallpaperIndex); 1881 1882 if (visible) { 1883 updateWallpaperOffsetLocked(wallpaper, dw, dh, false); 1884 } 1885 1886 // First, make sure the client has the current visibility 1887 // state. 1888 dispatchWallpaperVisibility(wallpaper, visible); 1889 1890 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment; 1891 if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win " 1892 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); 1893 1894 // First, if this window is at the current index, then all 1895 // is well. 1896 if (wallpaper == foundW) { 1897 foundI--; 1898 foundW = foundI > 0 1899 ? windows.get(foundI-1) : null; 1900 continue; 1901 } 1902 1903 // The window didn't match... the current wallpaper window, 1904 // wherever it is, is in the wrong place, so make sure it is 1905 // not in the list. 1906 int oldIndex = windows.indexOf(wallpaper); 1907 if (oldIndex >= 0) { 1908 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at " 1909 + oldIndex + ": " + wallpaper); 1910 windows.remove(oldIndex); 1911 mWindowsChanged = true; 1912 if (oldIndex < foundI) { 1913 foundI--; 1914 } 1915 } 1916 1917 // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost 1918 // layer. For keyguard over wallpaper put the wallpaper under the keyguard. 1919 int insertionIndex = 0; 1920 if (visible && foundW != null) { 1921 final int type = foundW.mAttrs.type; 1922 final int privateFlags = foundW.mAttrs.privateFlags; 1923 if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 1924 || type == TYPE_KEYGUARD_SCRIM) { 1925 insertionIndex = windows.indexOf(foundW); 1926 } 1927 } 1928 if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) { 1929 Slog.v(TAG, "Moving wallpaper " + wallpaper 1930 + " from " + oldIndex + " to " + insertionIndex); 1931 } 1932 1933 windows.add(insertionIndex, wallpaper); 1934 mWindowsChanged = true; 1935 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED; 1936 } 1937 } 1938 1939 /* 1940 final TaskStack targetStack = 1941 mWallpaperTarget == null ? null : mWallpaperTarget.getStack(); 1942 if ((changed & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0 && 1943 targetStack != null && !targetStack.isHomeStack()) { 1944 // If the wallpaper target is not on the home stack then make sure that all windows 1945 // from other non-home stacks are above the wallpaper. 1946 for (i = foundI - 1; i >= 0; --i) { 1947 WindowState win = windows.get(i); 1948 if (!win.isVisibleLw()) { 1949 continue; 1950 } 1951 final TaskStack winStack = win.getStack(); 1952 if (winStack != null && !winStack.isHomeStack() && winStack != targetStack) { 1953 windows.remove(i); 1954 windows.add(foundI + 1, win); 1955 } 1956 } 1957 } 1958 */ 1959 1960 if (targetChanged && DEBUG_WALLPAPER_LIGHT) { 1961 Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget 1962 + " lower=" + mLowerWallpaperTarget + " upper=" 1963 + mUpperWallpaperTarget); 1964 } 1965 1966 return changed; 1967 } 1968 1969 void setWallpaperAnimLayerAdjustmentLocked(int adj) { 1970 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, 1971 "Setting wallpaper layer adj to " + adj); 1972 mWallpaperAnimLayerAdjustment = adj; 1973 int curTokenIndex = mWallpaperTokens.size(); 1974 while (curTokenIndex > 0) { 1975 curTokenIndex--; 1976 WindowToken token = mWallpaperTokens.get(curTokenIndex); 1977 int curWallpaperIndex = token.windows.size(); 1978 while (curWallpaperIndex > 0) { 1979 curWallpaperIndex--; 1980 WindowState wallpaper = token.windows.get(curWallpaperIndex); 1981 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj; 1982 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win " 1983 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); 1984 } 1985 } 1986 } 1987 1988 boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh, 1989 boolean sync) { 1990 boolean changed = false; 1991 boolean rawChanged = false; 1992 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f; 1993 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f; 1994 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw; 1995 int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0; 1996 changed = wallpaperWin.mXOffset != offset; 1997 if (changed) { 1998 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " 1999 + wallpaperWin + " x: " + offset); 2000 wallpaperWin.mXOffset = offset; 2001 } 2002 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) { 2003 wallpaperWin.mWallpaperX = wpx; 2004 wallpaperWin.mWallpaperXStep = wpxs; 2005 rawChanged = true; 2006 } 2007 2008 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f; 2009 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f; 2010 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh; 2011 offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0; 2012 if (wallpaperWin.mYOffset != offset) { 2013 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " 2014 + wallpaperWin + " y: " + offset); 2015 changed = true; 2016 wallpaperWin.mYOffset = offset; 2017 } 2018 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) { 2019 wallpaperWin.mWallpaperY = wpy; 2020 wallpaperWin.mWallpaperYStep = wpys; 2021 rawChanged = true; 2022 } 2023 2024 if (rawChanged && (wallpaperWin.mAttrs.privateFlags & 2025 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) { 2026 try { 2027 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset " 2028 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX 2029 + " y=" + wallpaperWin.mWallpaperY); 2030 if (sync) { 2031 mWaitingOnWallpaper = wallpaperWin; 2032 } 2033 wallpaperWin.mClient.dispatchWallpaperOffsets( 2034 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY, 2035 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync); 2036 if (sync) { 2037 if (mWaitingOnWallpaper != null) { 2038 long start = SystemClock.uptimeMillis(); 2039 if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY) 2040 < start) { 2041 try { 2042 if (DEBUG_WALLPAPER) Slog.v(TAG, 2043 "Waiting for offset complete..."); 2044 mWindowMap.wait(WALLPAPER_TIMEOUT); 2045 } catch (InterruptedException e) { 2046 } 2047 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!"); 2048 if ((start+WALLPAPER_TIMEOUT) 2049 < SystemClock.uptimeMillis()) { 2050 Slog.i(TAG, "Timeout waiting for wallpaper to offset: " 2051 + wallpaperWin); 2052 mLastWallpaperTimeoutTime = start; 2053 } 2054 } 2055 mWaitingOnWallpaper = null; 2056 } 2057 } 2058 } catch (RemoteException e) { 2059 } 2060 } 2061 2062 return changed; 2063 } 2064 2065 void wallpaperOffsetsComplete(IBinder window) { 2066 synchronized (mWindowMap) { 2067 if (mWaitingOnWallpaper != null && 2068 mWaitingOnWallpaper.mClient.asBinder() == window) { 2069 mWaitingOnWallpaper = null; 2070 mWindowMap.notifyAll(); 2071 } 2072 } 2073 } 2074 2075 void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) { 2076 final DisplayContent displayContent = changingTarget.getDisplayContent(); 2077 if (displayContent == null) { 2078 return; 2079 } 2080 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2081 final int dw = displayInfo.logicalWidth; 2082 final int dh = displayInfo.logicalHeight; 2083 2084 WindowState target = mWallpaperTarget; 2085 if (target != null) { 2086 if (target.mWallpaperX >= 0) { 2087 mLastWallpaperX = target.mWallpaperX; 2088 } else if (changingTarget.mWallpaperX >= 0) { 2089 mLastWallpaperX = changingTarget.mWallpaperX; 2090 } 2091 if (target.mWallpaperY >= 0) { 2092 mLastWallpaperY = target.mWallpaperY; 2093 } else if (changingTarget.mWallpaperY >= 0) { 2094 mLastWallpaperY = changingTarget.mWallpaperY; 2095 } 2096 } 2097 2098 int curTokenIndex = mWallpaperTokens.size(); 2099 while (curTokenIndex > 0) { 2100 curTokenIndex--; 2101 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2102 int curWallpaperIndex = token.windows.size(); 2103 while (curWallpaperIndex > 0) { 2104 curWallpaperIndex--; 2105 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2106 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) { 2107 WindowStateAnimator winAnimator = wallpaper.mWinAnimator; 2108 winAnimator.computeShownFrameLocked(); 2109 // No need to lay out the windows - we can just set the wallpaper position 2110 // directly. 2111 winAnimator.setWallpaperOffset(wallpaper.mShownFrame); 2112 // We only want to be synchronous with one wallpaper. 2113 sync = false; 2114 } 2115 } 2116 } 2117 } 2118 2119 /** 2120 * Check wallpaper for visiblity change and notify window if so. 2121 * @param wallpaper The wallpaper to test and notify. 2122 * @param visible Current visibility. 2123 */ 2124 void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) { 2125 if (wallpaper.mWallpaperVisible != visible) { 2126 wallpaper.mWallpaperVisible = visible; 2127 try { 2128 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 2129 "Updating vis of wallpaper " + wallpaper 2130 + ": " + visible + " from:\n" + Debug.getCallers(4, " ")); 2131 wallpaper.mClient.dispatchAppVisibility(visible); 2132 } catch (RemoteException e) { 2133 } 2134 } 2135 } 2136 2137 void updateWallpaperVisibilityLocked() { 2138 final boolean visible = isWallpaperVisible(mWallpaperTarget); 2139 final DisplayContent displayContent = mWallpaperTarget.getDisplayContent(); 2140 if (displayContent == null) { 2141 return; 2142 } 2143 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2144 final int dw = displayInfo.logicalWidth; 2145 final int dh = displayInfo.logicalHeight; 2146 2147 int curTokenIndex = mWallpaperTokens.size(); 2148 while (curTokenIndex > 0) { 2149 curTokenIndex--; 2150 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2151 if (token.hidden == visible) { 2152 token.hidden = !visible; 2153 // Need to do a layout to ensure the wallpaper now has the 2154 // correct size. 2155 getDefaultDisplayContentLocked().layoutNeeded = true; 2156 } 2157 2158 int curWallpaperIndex = token.windows.size(); 2159 while (curWallpaperIndex > 0) { 2160 curWallpaperIndex--; 2161 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2162 if (visible) { 2163 updateWallpaperOffsetLocked(wallpaper, dw, dh, false); 2164 } 2165 2166 dispatchWallpaperVisibility(wallpaper, visible); 2167 } 2168 } 2169 } 2170 2171 public int addWindow(Session session, IWindow client, int seq, 2172 WindowManager.LayoutParams attrs, int viewVisibility, int displayId, 2173 Rect outContentInsets, InputChannel outInputChannel) { 2174 int[] appOp = new int[1]; 2175 int res = mPolicy.checkAddPermission(attrs, appOp); 2176 if (res != WindowManagerGlobal.ADD_OKAY) { 2177 return res; 2178 } 2179 2180 boolean reportNewConfig = false; 2181 WindowState attachedWindow = null; 2182 WindowState win = null; 2183 long origId; 2184 final int type = attrs.type; 2185 2186 synchronized(mWindowMap) { 2187 if (!mDisplayReady) { 2188 throw new IllegalStateException("Display has not been initialialized"); 2189 } 2190 2191 final DisplayContent displayContent = getDisplayContentLocked(displayId); 2192 if (displayContent == null) { 2193 Slog.w(TAG, "Attempted to add window to a display that does not exist: " 2194 + displayId + ". Aborting."); 2195 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2196 } 2197 if (!displayContent.hasAccess(session.mUid)) { 2198 Slog.w(TAG, "Attempted to add window to a display for which the application " 2199 + "does not have access: " + displayId + ". Aborting."); 2200 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2201 } 2202 2203 if (mWindowMap.containsKey(client.asBinder())) { 2204 Slog.w(TAG, "Window " + client + " is already added"); 2205 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 2206 } 2207 2208 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) { 2209 attachedWindow = windowForClientLocked(null, attrs.token, false); 2210 if (attachedWindow == null) { 2211 Slog.w(TAG, "Attempted to add window with token that is not a window: " 2212 + attrs.token + ". Aborting."); 2213 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 2214 } 2215 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW 2216 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) { 2217 Slog.w(TAG, "Attempted to add window with token that is a sub-window: " 2218 + attrs.token + ". Aborting."); 2219 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 2220 } 2221 } 2222 2223 if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) { 2224 Slog.w(TAG, "Attempted to add private presentation window to a non-private display. Aborting."); 2225 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 2226 } 2227 2228 boolean addToken = false; 2229 WindowToken token = mTokenMap.get(attrs.token); 2230 if (token == null) { 2231 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2232 Slog.w(TAG, "Attempted to add application window with unknown token " 2233 + attrs.token + ". Aborting."); 2234 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2235 } 2236 if (type == TYPE_INPUT_METHOD) { 2237 Slog.w(TAG, "Attempted to add input method window with unknown token " 2238 + attrs.token + ". Aborting."); 2239 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2240 } 2241 if (type == TYPE_VOICE_INTERACTION) { 2242 Slog.w(TAG, "Attempted to add voice interaction window with unknown token " 2243 + attrs.token + ". Aborting."); 2244 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2245 } 2246 if (type == TYPE_WALLPAPER) { 2247 Slog.w(TAG, "Attempted to add wallpaper window with unknown token " 2248 + attrs.token + ". Aborting."); 2249 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2250 } 2251 if (type == TYPE_DREAM) { 2252 Slog.w(TAG, "Attempted to add Dream window with unknown token " 2253 + attrs.token + ". Aborting."); 2254 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2255 } 2256 token = new WindowToken(this, attrs.token, -1, false); 2257 addToken = true; 2258 } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2259 AppWindowToken atoken = token.appWindowToken; 2260 if (atoken == null) { 2261 Slog.w(TAG, "Attempted to add window with non-application token " 2262 + token + ". Aborting."); 2263 return WindowManagerGlobal.ADD_NOT_APP_TOKEN; 2264 } else if (atoken.removed) { 2265 Slog.w(TAG, "Attempted to add window with exiting application token " 2266 + token + ". Aborting."); 2267 return WindowManagerGlobal.ADD_APP_EXITING; 2268 } 2269 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) { 2270 // No need for this guy! 2271 if (localLOGV) Slog.v( 2272 TAG, "**** NO NEED TO START: " + attrs.getTitle()); 2273 return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED; 2274 } 2275 } else if (type == TYPE_INPUT_METHOD) { 2276 if (token.windowType != TYPE_INPUT_METHOD) { 2277 Slog.w(TAG, "Attempted to add input method window with bad token " 2278 + attrs.token + ". Aborting."); 2279 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2280 } 2281 } else if (type == TYPE_VOICE_INTERACTION) { 2282 if (token.windowType != TYPE_VOICE_INTERACTION) { 2283 Slog.w(TAG, "Attempted to add voice interaction window with bad token " 2284 + attrs.token + ". Aborting."); 2285 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2286 } 2287 } else if (type == TYPE_WALLPAPER) { 2288 if (token.windowType != TYPE_WALLPAPER) { 2289 Slog.w(TAG, "Attempted to add wallpaper window with bad token " 2290 + attrs.token + ". Aborting."); 2291 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2292 } 2293 } else if (type == TYPE_DREAM) { 2294 if (token.windowType != TYPE_DREAM) { 2295 Slog.w(TAG, "Attempted to add Dream window with bad token " 2296 + attrs.token + ". Aborting."); 2297 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2298 } 2299 } 2300 2301 win = new WindowState(this, session, client, token, 2302 attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent); 2303 if (win.mDeathRecipient == null) { 2304 // Client has apparently died, so there is no reason to 2305 // continue. 2306 Slog.w(TAG, "Adding window client " + client.asBinder() 2307 + " that is dead, aborting."); 2308 return WindowManagerGlobal.ADD_APP_EXITING; 2309 } 2310 2311 if (win.getDisplayContent() == null) { 2312 Slog.w(TAG, "Adding window to Display that has been removed."); 2313 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2314 } 2315 2316 mPolicy.adjustWindowParamsLw(win.mAttrs); 2317 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs)); 2318 2319 res = mPolicy.prepareAddWindowLw(win, attrs); 2320 if (res != WindowManagerGlobal.ADD_OKAY) { 2321 return res; 2322 } 2323 2324 if (outInputChannel != null && (attrs.inputFeatures 2325 & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) { 2326 String name = win.makeInputChannelName(); 2327 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); 2328 win.setInputChannel(inputChannels[0]); 2329 inputChannels[1].transferTo(outInputChannel); 2330 2331 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle); 2332 } 2333 2334 // From now on, no exceptions or errors allowed! 2335 2336 res = WindowManagerGlobal.ADD_OKAY; 2337 2338 origId = Binder.clearCallingIdentity(); 2339 2340 if (addToken) { 2341 mTokenMap.put(attrs.token, token); 2342 } 2343 win.attach(); 2344 mWindowMap.put(client.asBinder(), win); 2345 if (win.mAppOp != AppOpsManager.OP_NONE) { 2346 if (mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage()) 2347 != AppOpsManager.MODE_ALLOWED) { 2348 win.setAppOpVisibilityLw(false); 2349 } 2350 } 2351 2352 if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) { 2353 token.appWindowToken.startingWindow = win; 2354 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken 2355 + " startingWindow=" + win); 2356 } 2357 2358 boolean imMayMove = true; 2359 2360 if (type == TYPE_INPUT_METHOD) { 2361 win.mGivenInsetsPending = true; 2362 mInputMethodWindow = win; 2363 addInputMethodWindowToListLocked(win); 2364 imMayMove = false; 2365 } else if (type == TYPE_INPUT_METHOD_DIALOG) { 2366 mInputMethodDialogs.add(win); 2367 addWindowToListInOrderLocked(win, true); 2368 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true)); 2369 imMayMove = false; 2370 } else { 2371 addWindowToListInOrderLocked(win, true); 2372 if (type == TYPE_WALLPAPER) { 2373 mLastWallpaperTimeoutTime = 0; 2374 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2375 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2376 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2377 } else if (mWallpaperTarget != null 2378 && mWallpaperTarget.mLayer >= win.mBaseLayer) { 2379 // If there is currently a wallpaper being shown, and 2380 // the base layer of the new window is below the current 2381 // layer of the target window, then adjust the wallpaper. 2382 // This is to avoid a new window being placed between the 2383 // wallpaper and its target. 2384 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2385 } 2386 } 2387 2388 win.mWinAnimator.mEnterAnimationPending = true; 2389 2390 if (displayContent.isDefaultDisplay) { 2391 mPolicy.getContentInsetHintLw(attrs, outContentInsets); 2392 } else { 2393 outContentInsets.setEmpty(); 2394 } 2395 2396 if (mInTouchMode) { 2397 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE; 2398 } 2399 if (win.mAppToken == null || !win.mAppToken.clientHidden) { 2400 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE; 2401 } 2402 2403 mInputMonitor.setUpdateInputWindowsNeededLw(); 2404 2405 boolean focusChanged = false; 2406 if (win.canReceiveKeys()) { 2407 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, 2408 false /*updateInputWindows*/); 2409 if (focusChanged) { 2410 imMayMove = false; 2411 } 2412 } 2413 2414 if (imMayMove) { 2415 moveInputMethodWindowsIfNeededLocked(false); 2416 } 2417 2418 assignLayersLocked(displayContent.getWindowList()); 2419 // Don't do layout here, the window must call 2420 // relayout to be displayed, so we'll do it there. 2421 2422 if (focusChanged) { 2423 finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/); 2424 } 2425 mInputMonitor.updateInputWindowsLw(false /*force*/); 2426 2427 if (localLOGV) Slog.v( 2428 TAG, "New client " + client.asBinder() 2429 + ": window=" + win); 2430 2431 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) { 2432 reportNewConfig = true; 2433 } 2434 } 2435 2436 if (reportNewConfig) { 2437 sendNewConfiguration(); 2438 } 2439 2440 Binder.restoreCallingIdentity(origId); 2441 2442 return res; 2443 } 2444 2445 public void removeWindow(Session session, IWindow client) { 2446 synchronized(mWindowMap) { 2447 WindowState win = windowForClientLocked(session, client, false); 2448 if (win == null) { 2449 return; 2450 } 2451 removeWindowLocked(session, win); 2452 } 2453 } 2454 2455 public void removeWindowLocked(Session session, WindowState win) { 2456 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2457 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Starting window removed " + win); 2458 } 2459 2460 if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v( 2461 TAG, "Remove " + win + " client=" 2462 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder())) 2463 + ", surface=" + win.mWinAnimator.mSurfaceControl + " Callers=" 2464 + Debug.getCallers(4)); 2465 2466 final long origId = Binder.clearCallingIdentity(); 2467 2468 win.disposeInputChannel(); 2469 2470 if (DEBUG_APP_TRANSITIONS) Slog.v( 2471 TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurfaceControl 2472 + " mExiting=" + win.mExiting 2473 + " isAnimating=" + win.mWinAnimator.isAnimating() 2474 + " app-animation=" 2475 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null) 2476 + " inPendingTransaction=" 2477 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false) 2478 + " mDisplayFrozen=" + mDisplayFrozen); 2479 // Visibility of the removed window. Will be used later to update orientation later on. 2480 boolean wasVisible = false; 2481 // First, see if we need to run an animation. If we do, we have 2482 // to hold off on removing the window until the animation is done. 2483 // If the display is frozen, just remove immediately, since the 2484 // animation wouldn't be seen. 2485 if (win.mHasSurface && okToDisplay()) { 2486 // If we are not currently running the exit animation, we 2487 // need to see about starting one. 2488 wasVisible = win.isWinVisibleLw(); 2489 if (wasVisible) { 2490 2491 int transit = WindowManagerPolicy.TRANSIT_EXIT; 2492 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2493 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 2494 } 2495 // Try starting an animation. 2496 if (win.mWinAnimator.applyAnimationLocked(transit, false)) { 2497 win.mExiting = true; 2498 } 2499 //TODO (multidisplay): Magnification is supported only for the default display. 2500 if (mAccessibilityController != null 2501 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 2502 mAccessibilityController.onWindowTransitionLocked(win, transit); 2503 } 2504 } 2505 if (win.mExiting || win.mWinAnimator.isAnimating()) { 2506 // The exit animation is running... wait for it! 2507 //Slog.i(TAG, "*** Running exit animation..."); 2508 win.mExiting = true; 2509 win.mRemoveOnExit = true; 2510 final DisplayContent displayContent = win.getDisplayContent(); 2511 if (displayContent != null) { 2512 displayContent.layoutNeeded = true; 2513 } 2514 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 2515 false /*updateInputWindows*/); 2516 performLayoutAndPlaceSurfacesLocked(); 2517 if (win.mAppToken != null) { 2518 win.mAppToken.updateReportedVisibilityLocked(); 2519 } 2520 //dump(); 2521 Binder.restoreCallingIdentity(origId); 2522 return; 2523 } 2524 } 2525 2526 removeWindowInnerLocked(session, win); 2527 // Removing a visible window will effect the computed orientation 2528 // So just update orientation if needed. 2529 if (wasVisible && updateOrientationFromAppTokensLocked(false)) { 2530 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 2531 } 2532 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 2533 Binder.restoreCallingIdentity(origId); 2534 } 2535 2536 private void removeWindowInnerLocked(Session session, WindowState win) { 2537 if (win.mRemoved) { 2538 // Nothing to do. 2539 return; 2540 } 2541 2542 for (int i=win.mChildWindows.size()-1; i>=0; i--) { 2543 WindowState cwin = win.mChildWindows.get(i); 2544 Slog.w(TAG, "Force-removing child win " + cwin + " from container " 2545 + win); 2546 removeWindowInnerLocked(cwin.mSession, cwin); 2547 } 2548 2549 win.mRemoved = true; 2550 2551 if (mInputMethodTarget == win) { 2552 moveInputMethodWindowsIfNeededLocked(false); 2553 } 2554 2555 if (false) { 2556 RuntimeException e = new RuntimeException("here"); 2557 e.fillInStackTrace(); 2558 Slog.w(TAG, "Removing window " + win, e); 2559 } 2560 2561 mPolicy.removeWindowLw(win); 2562 win.removeLocked(); 2563 2564 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win); 2565 mWindowMap.remove(win.mClient.asBinder()); 2566 if (win.mAppOp != AppOpsManager.OP_NONE) { 2567 mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage()); 2568 } 2569 2570 mPendingRemove.remove(win); 2571 mResizingWindows.remove(win); 2572 mWindowsChanged = true; 2573 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win); 2574 2575 if (mInputMethodWindow == win) { 2576 mInputMethodWindow = null; 2577 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) { 2578 mInputMethodDialogs.remove(win); 2579 } 2580 2581 final WindowToken token = win.mToken; 2582 final AppWindowToken atoken = win.mAppToken; 2583 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token); 2584 token.windows.remove(win); 2585 if (atoken != null) { 2586 atoken.allAppWindows.remove(win); 2587 } 2588 if (localLOGV) Slog.v( 2589 TAG, "**** Removing window " + win + ": count=" 2590 + token.windows.size()); 2591 if (token.windows.size() == 0) { 2592 if (!token.explicit) { 2593 mTokenMap.remove(token.token); 2594 } else if (atoken != null) { 2595 atoken.firstWindowDrawn = false; 2596 } 2597 } 2598 2599 if (atoken != null) { 2600 if (atoken.startingWindow == win) { 2601 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling startingWindow " + win); 2602 atoken.startingWindow = null; 2603 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) { 2604 // If this is the last window and we had requested a starting 2605 // transition window, well there is no point now. 2606 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling last startingWindow"); 2607 atoken.startingData = null; 2608 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) { 2609 // If this is the last window except for a starting transition 2610 // window, we need to get rid of the starting transition. 2611 scheduleRemoveStartingWindow(atoken); 2612 } 2613 } 2614 2615 if (win.mAttrs.type == TYPE_WALLPAPER) { 2616 mLastWallpaperTimeoutTime = 0; 2617 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2618 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2619 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2620 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2621 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2622 } 2623 2624 final WindowList windows = win.getWindowList(); 2625 if (windows != null) { 2626 windows.remove(win); 2627 if (!mInLayout) { 2628 assignLayersLocked(windows); 2629 final DisplayContent displayContent = win.getDisplayContent(); 2630 if (displayContent != null) { 2631 displayContent.layoutNeeded = true; 2632 } 2633 performLayoutAndPlaceSurfacesLocked(); 2634 if (win.mAppToken != null) { 2635 win.mAppToken.updateReportedVisibilityLocked(); 2636 } 2637 } 2638 } 2639 2640 mInputMonitor.updateInputWindowsLw(true /*force*/); 2641 } 2642 2643 public void updateAppOpsState() { 2644 synchronized(mWindowMap) { 2645 final int numDisplays = mDisplayContents.size(); 2646 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 2647 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 2648 final int numWindows = windows.size(); 2649 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 2650 final WindowState win = windows.get(winNdx); 2651 if (win.mAppOp != AppOpsManager.OP_NONE) { 2652 final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(), 2653 win.getOwningPackage()); 2654 win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED); 2655 } 2656 } 2657 } 2658 } 2659 } 2660 2661 static void logSurface(WindowState w, String msg, RuntimeException where) { 2662 String str = " SURFACE " + msg + ": " + w; 2663 if (where != null) { 2664 Slog.i(TAG, str, where); 2665 } else { 2666 Slog.i(TAG, str); 2667 } 2668 } 2669 2670 static void logSurface(SurfaceControl s, String title, String msg, RuntimeException where) { 2671 String str = " SURFACE " + s + ": " + msg + " / " + title; 2672 if (where != null) { 2673 Slog.i(TAG, str, where); 2674 } else { 2675 Slog.i(TAG, str); 2676 } 2677 } 2678 2679 void setTransparentRegionWindow(Session session, IWindow client, Region region) { 2680 long origId = Binder.clearCallingIdentity(); 2681 try { 2682 synchronized (mWindowMap) { 2683 WindowState w = windowForClientLocked(session, client, false); 2684 if ((w != null) && w.mHasSurface) { 2685 w.mWinAnimator.setTransparentRegionHintLocked(region); 2686 } 2687 } 2688 } finally { 2689 Binder.restoreCallingIdentity(origId); 2690 } 2691 } 2692 2693 void setInsetsWindow(Session session, IWindow client, 2694 int touchableInsets, Rect contentInsets, 2695 Rect visibleInsets, Region touchableRegion) { 2696 long origId = Binder.clearCallingIdentity(); 2697 try { 2698 synchronized (mWindowMap) { 2699 WindowState w = windowForClientLocked(session, client, false); 2700 if (w != null) { 2701 w.mGivenInsetsPending = false; 2702 w.mGivenContentInsets.set(contentInsets); 2703 w.mGivenVisibleInsets.set(visibleInsets); 2704 w.mGivenTouchableRegion.set(touchableRegion); 2705 w.mTouchableInsets = touchableInsets; 2706 if (w.mGlobalScale != 1) { 2707 w.mGivenContentInsets.scale(w.mGlobalScale); 2708 w.mGivenVisibleInsets.scale(w.mGlobalScale); 2709 w.mGivenTouchableRegion.scale(w.mGlobalScale); 2710 } 2711 final DisplayContent displayContent = w.getDisplayContent(); 2712 if (displayContent != null) { 2713 displayContent.layoutNeeded = true; 2714 } 2715 performLayoutAndPlaceSurfacesLocked(); 2716 } 2717 } 2718 } finally { 2719 Binder.restoreCallingIdentity(origId); 2720 } 2721 } 2722 2723 public void getWindowDisplayFrame(Session session, IWindow client, 2724 Rect outDisplayFrame) { 2725 synchronized(mWindowMap) { 2726 WindowState win = windowForClientLocked(session, client, false); 2727 if (win == null) { 2728 outDisplayFrame.setEmpty(); 2729 return; 2730 } 2731 outDisplayFrame.set(win.mDisplayFrame); 2732 } 2733 } 2734 2735 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y, 2736 float xStep, float yStep) { 2737 if (window.mWallpaperX != x || window.mWallpaperY != y) { 2738 window.mWallpaperX = x; 2739 window.mWallpaperY = y; 2740 window.mWallpaperXStep = xStep; 2741 window.mWallpaperYStep = yStep; 2742 updateWallpaperOffsetLocked(window, true); 2743 } 2744 } 2745 2746 void wallpaperCommandComplete(IBinder window, Bundle result) { 2747 synchronized (mWindowMap) { 2748 if (mWaitingOnWallpaper != null && 2749 mWaitingOnWallpaper.mClient.asBinder() == window) { 2750 mWaitingOnWallpaper = null; 2751 mWindowMap.notifyAll(); 2752 } 2753 } 2754 } 2755 2756 public Bundle sendWindowWallpaperCommandLocked(WindowState window, 2757 String action, int x, int y, int z, Bundle extras, boolean sync) { 2758 if (window == mWallpaperTarget || window == mLowerWallpaperTarget 2759 || window == mUpperWallpaperTarget) { 2760 boolean doWait = sync; 2761 int curTokenIndex = mWallpaperTokens.size(); 2762 while (curTokenIndex > 0) { 2763 curTokenIndex--; 2764 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2765 int curWallpaperIndex = token.windows.size(); 2766 while (curWallpaperIndex > 0) { 2767 curWallpaperIndex--; 2768 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2769 try { 2770 wallpaper.mClient.dispatchWallpaperCommand(action, 2771 x, y, z, extras, sync); 2772 // We only want to be synchronous with one wallpaper. 2773 sync = false; 2774 } catch (RemoteException e) { 2775 } 2776 } 2777 } 2778 2779 if (doWait) { 2780 // XXX Need to wait for result. 2781 } 2782 } 2783 2784 return null; 2785 } 2786 2787 public void setUniverseTransformLocked(WindowState window, float alpha, 2788 float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) { 2789 Transformation transform = window.mWinAnimator.mUniverseTransform; 2790 transform.setAlpha(alpha); 2791 Matrix matrix = transform.getMatrix(); 2792 matrix.getValues(mTmpFloats); 2793 mTmpFloats[Matrix.MTRANS_X] = offx; 2794 mTmpFloats[Matrix.MTRANS_Y] = offy; 2795 mTmpFloats[Matrix.MSCALE_X] = dsdx; 2796 mTmpFloats[Matrix.MSKEW_Y] = dtdx; 2797 mTmpFloats[Matrix.MSKEW_X] = dsdy; 2798 mTmpFloats[Matrix.MSCALE_Y] = dtdy; 2799 matrix.setValues(mTmpFloats); 2800 final DisplayContent displayContent = window.getDisplayContent(); 2801 if (displayContent == null) { 2802 return; 2803 } 2804 2805 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2806 final RectF dispRect = new RectF(0, 0, 2807 displayInfo.logicalWidth, displayInfo.logicalHeight); 2808 matrix.mapRect(dispRect); 2809 window.mGivenTouchableRegion.set(0, 0, 2810 displayInfo.logicalWidth, displayInfo.logicalHeight); 2811 window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top, 2812 (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE); 2813 window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; 2814 displayContent.layoutNeeded = true; 2815 performLayoutAndPlaceSurfacesLocked(); 2816 } 2817 2818 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle, boolean immediate) { 2819 synchronized (mWindowMap) { 2820 if (mAccessibilityController != null) { 2821 WindowState window = mWindowMap.get(token); 2822 //TODO (multidisplay): Magnification is supported only for the default display. 2823 if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 2824 mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle, 2825 immediate); 2826 } 2827 } 2828 } 2829 } 2830 2831 public IWindowId getWindowId(IBinder token) { 2832 synchronized (mWindowMap) { 2833 WindowState window = mWindowMap.get(token); 2834 return window != null ? window.mWindowId : null; 2835 } 2836 } 2837 2838 public int relayoutWindow(Session session, IWindow client, int seq, 2839 WindowManager.LayoutParams attrs, int requestedWidth, 2840 int requestedHeight, int viewVisibility, int flags, 2841 Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, 2842 Rect outVisibleInsets, Configuration outConfig, Surface outSurface) { 2843 boolean toBeDisplayed = false; 2844 boolean inTouchMode; 2845 boolean configChanged; 2846 boolean surfaceChanged = false; 2847 boolean animating; 2848 boolean hasStatusBarPermission = 2849 mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 2850 == PackageManager.PERMISSION_GRANTED; 2851 2852 long origId = Binder.clearCallingIdentity(); 2853 2854 synchronized(mWindowMap) { 2855 WindowState win = windowForClientLocked(session, client, false); 2856 if (win == null) { 2857 return 0; 2858 } 2859 WindowStateAnimator winAnimator = win.mWinAnimator; 2860 if (win.mRequestedWidth != requestedWidth 2861 || win.mRequestedHeight != requestedHeight) { 2862 win.mLayoutNeeded = true; 2863 win.mRequestedWidth = requestedWidth; 2864 win.mRequestedHeight = requestedHeight; 2865 } 2866 2867 if (attrs != null) { 2868 mPolicy.adjustWindowParamsLw(attrs); 2869 } 2870 2871 // if they don't have the permission, mask out the status bar bits 2872 int systemUiVisibility = 0; 2873 if (attrs != null) { 2874 systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility); 2875 if ((systemUiVisibility & StatusBarManager.DISABLE_MASK) != 0) { 2876 if (!hasStatusBarPermission) { 2877 systemUiVisibility &= ~StatusBarManager.DISABLE_MASK; 2878 } 2879 } 2880 } 2881 2882 if (attrs != null && seq == win.mSeq) { 2883 win.mSystemUiVisibility = systemUiVisibility; 2884 } 2885 2886 winAnimator.mSurfaceDestroyDeferred = 2887 (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0; 2888 2889 int attrChanges = 0; 2890 int flagChanges = 0; 2891 if (attrs != null) { 2892 if (win.mAttrs.type != attrs.type) { 2893 throw new IllegalArgumentException( 2894 "Window type can not be changed after the window is added."); 2895 } 2896 flagChanges = win.mAttrs.flags ^= attrs.flags; 2897 attrChanges = win.mAttrs.copyFrom(attrs); 2898 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED 2899 | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) { 2900 win.mLayoutNeeded = true; 2901 } 2902 } 2903 2904 if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility 2905 + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs); 2906 2907 win.mEnforceSizeCompat = 2908 (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0; 2909 2910 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) { 2911 winAnimator.mAlpha = attrs.alpha; 2912 } 2913 2914 final boolean scaledWindow = 2915 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0); 2916 2917 if (scaledWindow) { 2918 // requested{Width|Height} Surface's physical size 2919 // attrs.{width|height} Size on screen 2920 win.mHScale = (attrs.width != requestedWidth) ? 2921 (attrs.width / (float)requestedWidth) : 1.0f; 2922 win.mVScale = (attrs.height != requestedHeight) ? 2923 (attrs.height / (float)requestedHeight) : 1.0f; 2924 } else { 2925 win.mHScale = win.mVScale = 1; 2926 } 2927 2928 boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0; 2929 2930 final boolean isDefaultDisplay = win.isDefaultDisplay(); 2931 boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility 2932 || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0) 2933 || (!win.mRelayoutCalled)); 2934 2935 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility 2936 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0; 2937 wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0; 2938 2939 win.mRelayoutCalled = true; 2940 final int oldVisibility = win.mViewVisibility; 2941 win.mViewVisibility = viewVisibility; 2942 if (DEBUG_SCREEN_ON) { 2943 RuntimeException stack = new RuntimeException(); 2944 stack.fillInStackTrace(); 2945 Slog.i(TAG, "Relayout " + win + ": oldVis=" + oldVisibility 2946 + " newVis=" + viewVisibility, stack); 2947 } 2948 if (viewVisibility == View.VISIBLE && 2949 (win.mAppToken == null || !win.mAppToken.clientHidden)) { 2950 toBeDisplayed = !win.isVisibleLw(); 2951 if (win.mExiting) { 2952 winAnimator.cancelExitAnimationForNextAnimationLocked(); 2953 win.mExiting = false; 2954 } 2955 if (win.mDestroying) { 2956 win.mDestroying = false; 2957 mDestroySurface.remove(win); 2958 } 2959 if (oldVisibility == View.GONE) { 2960 winAnimator.mEnterAnimationPending = true; 2961 } 2962 if (toBeDisplayed) { 2963 if (win.isDrawnLw() && okToDisplay()) { 2964 winAnimator.applyEnterAnimationLocked(); 2965 } 2966 if ((win.mAttrs.flags 2967 & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) { 2968 if (DEBUG_VISIBILITY) Slog.v(TAG, 2969 "Relayout window turning screen on: " + win); 2970 win.mTurnOnScreen = true; 2971 } 2972 if (win.isConfigChanged()) { 2973 if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win 2974 + " visible with new config: " + mCurConfiguration); 2975 outConfig.setTo(mCurConfiguration); 2976 } 2977 } 2978 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) { 2979 // To change the format, we need to re-build the surface. 2980 winAnimator.destroySurfaceLocked(); 2981 toBeDisplayed = true; 2982 surfaceChanged = true; 2983 } 2984 try { 2985 if (!win.mHasSurface) { 2986 surfaceChanged = true; 2987 } 2988 SurfaceControl surfaceControl = winAnimator.createSurfaceLocked(); 2989 if (surfaceControl != null) { 2990 outSurface.copyFrom(surfaceControl); 2991 if (SHOW_TRANSACTIONS) Slog.i(TAG, 2992 " OUT SURFACE " + outSurface + ": copied"); 2993 } else { 2994 // For some reason there isn't a surface. Clear the 2995 // caller's object so they see the same state. 2996 outSurface.release(); 2997 } 2998 } catch (Exception e) { 2999 mInputMonitor.updateInputWindowsLw(true /*force*/); 3000 3001 Slog.w(TAG, "Exception thrown when creating surface for client " 3002 + client + " (" + win.mAttrs.getTitle() + ")", 3003 e); 3004 Binder.restoreCallingIdentity(origId); 3005 return 0; 3006 } 3007 if (toBeDisplayed) { 3008 focusMayChange = isDefaultDisplay; 3009 } 3010 if (win.mAttrs.type == TYPE_INPUT_METHOD 3011 && mInputMethodWindow == null) { 3012 mInputMethodWindow = win; 3013 imMayMove = true; 3014 } 3015 if (win.mAttrs.type == TYPE_BASE_APPLICATION 3016 && win.mAppToken != null 3017 && win.mAppToken.startingWindow != null) { 3018 // Special handling of starting window over the base 3019 // window of the app: propagate lock screen flags to it, 3020 // to provide the correct semantics while starting. 3021 final int mask = 3022 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED 3023 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD 3024 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; 3025 WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs; 3026 sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask); 3027 } 3028 } else { 3029 winAnimator.mEnterAnimationPending = false; 3030 if (winAnimator.mSurfaceControl != null) { 3031 if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win 3032 + ": mExiting=" + win.mExiting); 3033 // If we are not currently running the exit animation, we 3034 // need to see about starting one. 3035 if (!win.mExiting) { 3036 surfaceChanged = true; 3037 // Try starting an animation; if there isn't one, we 3038 // can destroy the surface right away. 3039 int transit = WindowManagerPolicy.TRANSIT_EXIT; 3040 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 3041 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 3042 } 3043 if (win.isWinVisibleLw() && 3044 winAnimator.applyAnimationLocked(transit, false)) { 3045 focusMayChange = isDefaultDisplay; 3046 win.mExiting = true; 3047 } else if (win.mWinAnimator.isAnimating()) { 3048 // Currently in a hide animation... turn this into 3049 // an exit. 3050 win.mExiting = true; 3051 } else if (win == mWallpaperTarget) { 3052 // If the wallpaper is currently behind this 3053 // window, we need to change both of them inside 3054 // of a transaction to avoid artifacts. 3055 win.mExiting = true; 3056 win.mWinAnimator.mAnimating = true; 3057 } else { 3058 if (mInputMethodWindow == win) { 3059 mInputMethodWindow = null; 3060 } 3061 winAnimator.destroySurfaceLocked(); 3062 } 3063 //TODO (multidisplay): Magnification is supported only for the default 3064 if (mAccessibilityController != null 3065 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 3066 mAccessibilityController.onWindowTransitionLocked(win, transit); 3067 } 3068 } 3069 } 3070 3071 outSurface.release(); 3072 if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win); 3073 } 3074 3075 if (focusMayChange) { 3076 //System.out.println("Focus may change: " + win.mAttrs.getTitle()); 3077 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 3078 false /*updateInputWindows*/)) { 3079 imMayMove = false; 3080 } 3081 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus); 3082 } 3083 3084 // updateFocusedWindowLocked() already assigned layers so we only need to 3085 // reassign them at this point if the IM window state gets shuffled 3086 if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) { 3087 // Little hack here -- we -should- be able to rely on the 3088 // function to return true if the IME has moved and needs 3089 // its layer recomputed. However, if the IME was hidden 3090 // and isn't actually moved in the list, its layer may be 3091 // out of data so we make sure to recompute it. 3092 assignLayersLocked(win.getWindowList()); 3093 } 3094 3095 if (wallpaperMayMove) { 3096 getDefaultDisplayContentLocked().pendingLayoutChanges |= 3097 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 3098 } 3099 3100 final DisplayContent displayContent = win.getDisplayContent(); 3101 if (displayContent != null) { 3102 displayContent.layoutNeeded = true; 3103 } 3104 win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0; 3105 configChanged = updateOrientationFromAppTokensLocked(false); 3106 performLayoutAndPlaceSurfacesLocked(); 3107 if (toBeDisplayed && win.mIsWallpaper) { 3108 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 3109 updateWallpaperOffsetLocked(win, 3110 displayInfo.logicalWidth, displayInfo.logicalHeight, false); 3111 } 3112 if (win.mAppToken != null) { 3113 win.mAppToken.updateReportedVisibilityLocked(); 3114 } 3115 outFrame.set(win.mCompatFrame); 3116 outOverscanInsets.set(win.mOverscanInsets); 3117 outContentInsets.set(win.mContentInsets); 3118 outVisibleInsets.set(win.mVisibleInsets); 3119 if (localLOGV) Slog.v( 3120 TAG, "Relayout given client " + client.asBinder() 3121 + ", requestedWidth=" + requestedWidth 3122 + ", requestedHeight=" + requestedHeight 3123 + ", viewVisibility=" + viewVisibility 3124 + "\nRelayout returning frame=" + outFrame 3125 + ", surface=" + outSurface); 3126 3127 if (localLOGV || DEBUG_FOCUS) Slog.v( 3128 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange); 3129 3130 inTouchMode = mInTouchMode; 3131 animating = mAnimator.mAnimating && win.mWinAnimator.isAnimating(); 3132 if (animating && !mRelayoutWhileAnimating.contains(win)) { 3133 mRelayoutWhileAnimating.add(win); 3134 } 3135 3136 mInputMonitor.updateInputWindowsLw(true /*force*/); 3137 3138 if (DEBUG_LAYOUT) { 3139 Slog.v(TAG, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString()); 3140 } 3141 } 3142 3143 if (configChanged) { 3144 sendNewConfiguration(); 3145 } 3146 3147 Binder.restoreCallingIdentity(origId); 3148 3149 return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0) 3150 | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0) 3151 | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0) 3152 | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0); 3153 } 3154 3155 public void performDeferredDestroyWindow(Session session, IWindow client) { 3156 long origId = Binder.clearCallingIdentity(); 3157 3158 try { 3159 synchronized (mWindowMap) { 3160 WindowState win = windowForClientLocked(session, client, false); 3161 if (win == null) { 3162 return; 3163 } 3164 win.mWinAnimator.destroyDeferredSurfaceLocked(); 3165 } 3166 } finally { 3167 Binder.restoreCallingIdentity(origId); 3168 } 3169 } 3170 3171 public boolean outOfMemoryWindow(Session session, IWindow client) { 3172 long origId = Binder.clearCallingIdentity(); 3173 3174 try { 3175 synchronized (mWindowMap) { 3176 WindowState win = windowForClientLocked(session, client, false); 3177 if (win == null) { 3178 return false; 3179 } 3180 return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false); 3181 } 3182 } finally { 3183 Binder.restoreCallingIdentity(origId); 3184 } 3185 } 3186 3187 public void finishDrawingWindow(Session session, IWindow client) { 3188 final long origId = Binder.clearCallingIdentity(); 3189 try { 3190 synchronized (mWindowMap) { 3191 WindowState win = windowForClientLocked(session, client, false); 3192 if (win != null && win.mWinAnimator.finishDrawingLocked()) { 3193 if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 3194 getDefaultDisplayContentLocked().pendingLayoutChanges |= 3195 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 3196 } 3197 final DisplayContent displayContent = win.getDisplayContent(); 3198 if (displayContent != null) { 3199 displayContent.layoutNeeded = true; 3200 } 3201 requestTraversalLocked(); 3202 } 3203 } 3204 } finally { 3205 Binder.restoreCallingIdentity(origId); 3206 } 3207 } 3208 3209 private boolean applyAnimationLocked(AppWindowToken atoken, 3210 WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction) { 3211 // Only apply an animation if the display isn't frozen. If it is 3212 // frozen, there is no reason to animate and it can cause strange 3213 // artifacts when we unfreeze the display if some different animation 3214 // is running. 3215 if (okToDisplay()) { 3216 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 3217 final int width = displayInfo.appWidth; 3218 final int height = displayInfo.appHeight; 3219 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation: atoken=" 3220 + atoken); 3221 3222 // Determine the visible rect to calculate the thumbnail clip 3223 WindowState win = atoken.findMainWindow(); 3224 Rect containingFrame = new Rect(0, 0, width, height); 3225 Rect contentInsets = new Rect(); 3226 boolean isFullScreen = true; 3227 if (win != null) { 3228 if (win.mContainingFrame != null) { 3229 containingFrame.set(win.mContainingFrame); 3230 } 3231 if (win.mContentInsets != null) { 3232 contentInsets.set(win.mContentInsets); 3233 } 3234 isFullScreen = 3235 ((win.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN) == 3236 SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN); 3237 } 3238 3239 Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height, 3240 mCurConfiguration.orientation, containingFrame, contentInsets, isFullScreen, 3241 isVoiceInteraction); 3242 if (a != null) { 3243 if (DEBUG_ANIM) { 3244 RuntimeException e = null; 3245 if (!HIDE_STACK_CRAWLS) { 3246 e = new RuntimeException(); 3247 e.fillInStackTrace(); 3248 } 3249 Slog.v(TAG, "Loaded animation " + a + " for " + atoken, e); 3250 } 3251 atoken.mAppAnimator.setAnimation(a, width, height); 3252 } 3253 } else { 3254 atoken.mAppAnimator.clearAnimation(); 3255 } 3256 3257 return atoken.mAppAnimator.animation != null; 3258 } 3259 3260 // ------------------------------------------------------------- 3261 // Application Window Tokens 3262 // ------------------------------------------------------------- 3263 3264 public void validateAppTokens(int stackId, List<TaskGroup> tasks) { 3265 synchronized (mWindowMap) { 3266 int t = tasks.size() - 1; 3267 if (t < 0) { 3268 Slog.w(TAG, "validateAppTokens: empty task list"); 3269 return; 3270 } 3271 3272 TaskGroup task = tasks.get(0); 3273 int taskId = task.taskId; 3274 Task targetTask = mTaskIdToTask.get(taskId); 3275 DisplayContent displayContent = targetTask.getDisplayContent(); 3276 if (displayContent == null) { 3277 Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId); 3278 return; 3279 } 3280 3281 final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks(); 3282 int taskNdx; 3283 for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) { 3284 AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens; 3285 task = tasks.get(t); 3286 List<IApplicationToken> tokens = task.tokens; 3287 3288 DisplayContent lastDisplayContent = displayContent; 3289 displayContent = mTaskIdToTask.get(taskId).getDisplayContent(); 3290 if (displayContent != lastDisplayContent) { 3291 Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!"); 3292 return; 3293 } 3294 3295 int tokenNdx; 3296 int v; 3297 for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1; 3298 tokenNdx >= 0 && v >= 0; ) { 3299 final AppWindowToken atoken = localTokens.get(tokenNdx); 3300 if (atoken.removed) { 3301 --tokenNdx; 3302 continue; 3303 } 3304 if (tokens.get(v) != atoken.token) { 3305 break; 3306 } 3307 --tokenNdx; 3308 v--; 3309 } 3310 3311 if (tokenNdx >= 0 || v >= 0) { 3312 break; 3313 } 3314 } 3315 3316 if (taskNdx >= 0 || t >= 0) { 3317 Slog.w(TAG, "validateAppTokens: Mismatch! ActivityManager=" + tasks); 3318 Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager=" + localTasks); 3319 Slog.w(TAG, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4)); 3320 } 3321 } 3322 } 3323 3324 public void validateStackOrder(Integer[] remoteStackIds) { 3325 // TODO: 3326 } 3327 3328 boolean checkCallingPermission(String permission, String func) { 3329 // Quick check: if the calling permission is me, it's all okay. 3330 if (Binder.getCallingPid() == Process.myPid()) { 3331 return true; 3332 } 3333 3334 if (mContext.checkCallingPermission(permission) 3335 == PackageManager.PERMISSION_GRANTED) { 3336 return true; 3337 } 3338 String msg = "Permission Denial: " + func + " from pid=" 3339 + Binder.getCallingPid() 3340 + ", uid=" + Binder.getCallingUid() 3341 + " requires " + permission; 3342 Slog.w(TAG, msg); 3343 return false; 3344 } 3345 3346 boolean okToDisplay() { 3347 return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully(); 3348 } 3349 3350 AppWindowToken findAppWindowToken(IBinder token) { 3351 WindowToken wtoken = mTokenMap.get(token); 3352 if (wtoken == null) { 3353 return null; 3354 } 3355 return wtoken.appWindowToken; 3356 } 3357 3358 @Override 3359 public void addWindowToken(IBinder token, int type) { 3360 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3361 "addWindowToken()")) { 3362 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3363 } 3364 3365 synchronized(mWindowMap) { 3366 WindowToken wtoken = mTokenMap.get(token); 3367 if (wtoken != null) { 3368 Slog.w(TAG, "Attempted to add existing input method token: " + token); 3369 return; 3370 } 3371 wtoken = new WindowToken(this, token, type, true); 3372 mTokenMap.put(token, wtoken); 3373 if (type == TYPE_WALLPAPER) { 3374 mWallpaperTokens.add(wtoken); 3375 } 3376 } 3377 } 3378 3379 @Override 3380 public void removeWindowToken(IBinder token) { 3381 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3382 "removeWindowToken()")) { 3383 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3384 } 3385 3386 final long origId = Binder.clearCallingIdentity(); 3387 synchronized(mWindowMap) { 3388 DisplayContent displayContent = null; 3389 WindowToken wtoken = mTokenMap.remove(token); 3390 if (wtoken != null) { 3391 boolean delayed = false; 3392 if (!wtoken.hidden) { 3393 final int N = wtoken.windows.size(); 3394 boolean changed = false; 3395 3396 for (int i=0; i<N; i++) { 3397 WindowState win = wtoken.windows.get(i); 3398 displayContent = win.getDisplayContent(); 3399 3400 if (win.mWinAnimator.isAnimating()) { 3401 delayed = true; 3402 } 3403 3404 if (win.isVisibleNow()) { 3405 win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, 3406 false); 3407 //TODO (multidisplay): Magnification is supported only for the default 3408 if (mAccessibilityController != null && win.isDefaultDisplay()) { 3409 mAccessibilityController.onWindowTransitionLocked(win, 3410 WindowManagerPolicy.TRANSIT_EXIT); 3411 } 3412 changed = true; 3413 if (displayContent != null) { 3414 displayContent.layoutNeeded = true; 3415 } 3416 } 3417 } 3418 3419 wtoken.hidden = true; 3420 3421 if (changed) { 3422 performLayoutAndPlaceSurfacesLocked(); 3423 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, 3424 false /*updateInputWindows*/); 3425 } 3426 3427 if (delayed) { 3428 if (displayContent != null) { 3429 displayContent.mExitingTokens.add(wtoken); 3430 } 3431 } else if (wtoken.windowType == TYPE_WALLPAPER) { 3432 mWallpaperTokens.remove(wtoken); 3433 } 3434 } 3435 3436 mInputMonitor.updateInputWindowsLw(true /*force*/); 3437 } else { 3438 Slog.w(TAG, "Attempted to remove non-existing token: " + token); 3439 } 3440 } 3441 Binder.restoreCallingIdentity(origId); 3442 } 3443 3444 private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) { 3445 if (DEBUG_STACK) Slog.i(TAG, "createTask: taskId=" + taskId + " stackId=" + stackId 3446 + " atoken=" + atoken); 3447 final TaskStack stack = mStackIdToStack.get(stackId); 3448 if (stack == null) { 3449 throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId); 3450 } 3451 EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId); 3452 Task task = new Task(atoken, stack, userId); 3453 mTaskIdToTask.put(taskId, task); 3454 stack.addTask(task, true); 3455 return task; 3456 } 3457 3458 @Override 3459 public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId, 3460 int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId, 3461 int configChanges, boolean voiceInteraction) { 3462 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3463 "addAppToken()")) { 3464 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3465 } 3466 3467 // Get the dispatching timeout here while we are not holding any locks so that it 3468 // can be cached by the AppWindowToken. The timeout value is used later by the 3469 // input dispatcher in code that does hold locks. If we did not cache the value 3470 // here we would run the chance of introducing a deadlock between the window manager 3471 // (which holds locks while updating the input dispatcher state) and the activity manager 3472 // (which holds locks while querying the application token). 3473 long inputDispatchingTimeoutNanos; 3474 try { 3475 inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L; 3476 } catch (RemoteException ex) { 3477 Slog.w(TAG, "Could not get dispatching timeout.", ex); 3478 inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 3479 } 3480 3481 synchronized(mWindowMap) { 3482 AppWindowToken atoken = findAppWindowToken(token.asBinder()); 3483 if (atoken != null) { 3484 Slog.w(TAG, "Attempted to add existing app token: " + token); 3485 return; 3486 } 3487 atoken = new AppWindowToken(this, token, voiceInteraction); 3488 atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos; 3489 atoken.groupId = taskId; 3490 atoken.appFullscreen = fullscreen; 3491 atoken.showWhenLocked = showWhenLocked; 3492 atoken.requestedOrientation = requestedOrientation; 3493 atoken.layoutConfigChanges = (configChanges & 3494 (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0; 3495 if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken 3496 + " to stack=" + stackId + " task=" + taskId + " at " + addPos); 3497 3498 Task task = mTaskIdToTask.get(taskId); 3499 if (task == null) { 3500 createTask(taskId, stackId, userId, atoken); 3501 } else { 3502 task.addAppToken(addPos, atoken); 3503 } 3504 3505 mTokenMap.put(token.asBinder(), atoken); 3506 3507 // Application tokens start out hidden. 3508 atoken.hidden = true; 3509 atoken.hiddenRequested = true; 3510 3511 //dump(); 3512 } 3513 } 3514 3515 @Override 3516 public void setAppGroupId(IBinder token, int groupId) { 3517 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3518 "setAppGroupId()")) { 3519 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3520 } 3521 3522 synchronized(mWindowMap) { 3523 final AppWindowToken atoken = findAppWindowToken(token); 3524 if (atoken == null) { 3525 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token); 3526 return; 3527 } 3528 final Task oldTask = mTaskIdToTask.get(atoken.groupId); 3529 removeAppFromTaskLocked(atoken); 3530 3531 atoken.groupId = groupId; 3532 Task newTask = mTaskIdToTask.get(groupId); 3533 if (newTask == null) { 3534 newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken); 3535 } else { 3536 newTask.mAppTokens.add(atoken); 3537 } 3538 } 3539 } 3540 3541 public int getOrientationFromWindowsLocked() { 3542 if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 3543 // If the display is frozen, some activities may be in the middle 3544 // of restarting, and thus have removed their old window. If the 3545 // window has the flag to hide the lock screen, then the lock screen 3546 // can re-appear and inflict its own orientation on us. Keep the 3547 // orientation stable until this all settles down. 3548 return mLastWindowForcedOrientation; 3549 } 3550 3551 // TODO(multidisplay): Change to the correct display. 3552 final WindowList windows = getDefaultWindowListLocked(); 3553 int pos = windows.size() - 1; 3554 while (pos >= 0) { 3555 WindowState win = windows.get(pos); 3556 pos--; 3557 if (win.mAppToken != null) { 3558 // We hit an application window. so the orientation will be determined by the 3559 // app window. No point in continuing further. 3560 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3561 } 3562 if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) { 3563 continue; 3564 } 3565 int req = win.mAttrs.screenOrientation; 3566 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) || 3567 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){ 3568 continue; 3569 } 3570 3571 if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req); 3572 return (mLastWindowForcedOrientation=req); 3573 } 3574 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3575 } 3576 3577 public int getOrientationFromAppTokensLocked() { 3578 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3579 boolean findingBehind = false; 3580 boolean lastFullscreen = false; 3581 // TODO: Multi window. 3582 DisplayContent displayContent = getDefaultDisplayContentLocked(); 3583 final ArrayList<Task> tasks = displayContent.getTasks(); 3584 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 3585 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 3586 final int firstToken = tokens.size() - 1; 3587 for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) { 3588 final AppWindowToken atoken = tokens.get(tokenNdx); 3589 3590 if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken); 3591 3592 // if we're about to tear down this window and not seek for 3593 // the behind activity, don't use it for orientation 3594 if (!findingBehind 3595 && (!atoken.hidden && atoken.hiddenRequested)) { 3596 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken 3597 + " -- going to hide"); 3598 continue; 3599 } 3600 3601 if (tokenNdx == firstToken) { 3602 // If we have hit a new Task, and the bottom 3603 // of the previous group didn't explicitly say to use 3604 // the orientation behind it, and the last app was 3605 // full screen, then we'll stick with the 3606 // user's orientation. 3607 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND 3608 && lastFullscreen) { 3609 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3610 + " -- end of group, return " + lastOrientation); 3611 return lastOrientation; 3612 } 3613 } 3614 3615 // We ignore any hidden applications on the top. 3616 if (atoken.hiddenRequested || atoken.willBeHidden) { 3617 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken 3618 + " -- hidden on top"); 3619 continue; 3620 } 3621 3622 if (tokenNdx == 0) { 3623 // Last token in this task. 3624 lastOrientation = atoken.requestedOrientation; 3625 } 3626 3627 int or = atoken.requestedOrientation; 3628 // If this application is fullscreen, and didn't explicitly say 3629 // to use the orientation behind it, then just take whatever 3630 // orientation it has and ignores whatever is under it. 3631 lastFullscreen = atoken.appFullscreen; 3632 if (lastFullscreen 3633 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { 3634 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3635 + " -- full screen, return " + or); 3636 return or; 3637 } 3638 // If this application has requested an explicit orientation, 3639 // then use it. 3640 if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 3641 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { 3642 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3643 + " -- explicitly set, return " + or); 3644 return or; 3645 } 3646 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND); 3647 } 3648 } 3649 if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation"); 3650 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3651 } 3652 3653 @Override 3654 public Configuration updateOrientationFromAppTokens( 3655 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3656 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3657 "updateOrientationFromAppTokens()")) { 3658 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3659 } 3660 3661 Configuration config = null; 3662 long ident = Binder.clearCallingIdentity(); 3663 3664 synchronized(mWindowMap) { 3665 config = updateOrientationFromAppTokensLocked(currentConfig, 3666 freezeThisOneIfNeeded); 3667 } 3668 3669 Binder.restoreCallingIdentity(ident); 3670 return config; 3671 } 3672 3673 private Configuration updateOrientationFromAppTokensLocked( 3674 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3675 Configuration config = null; 3676 3677 if (updateOrientationFromAppTokensLocked(false)) { 3678 if (freezeThisOneIfNeeded != null) { 3679 AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded); 3680 if (atoken != null) { 3681 startAppFreezingScreenLocked(atoken); 3682 } 3683 } 3684 config = computeNewConfigurationLocked(); 3685 3686 } else if (currentConfig != null) { 3687 // No obvious action we need to take, but if our current 3688 // state mismatches the activity manager's, update it, 3689 // disregarding font scale, which should remain set to 3690 // the value of the previous configuration. 3691 mTempConfiguration.setToDefaults(); 3692 mTempConfiguration.fontScale = currentConfig.fontScale; 3693 if (computeScreenConfigurationLocked(mTempConfiguration)) { 3694 if (currentConfig.diff(mTempConfiguration) != 0) { 3695 mWaitingForConfig = true; 3696 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 3697 displayContent.layoutNeeded = true; 3698 int anim[] = new int[2]; 3699 if (displayContent.isDimming()) { 3700 anim[0] = anim[1] = 0; 3701 } else { 3702 mPolicy.selectRotationAnimationLw(anim); 3703 } 3704 startFreezingDisplayLocked(false, anim[0], anim[1]); 3705 config = new Configuration(mTempConfiguration); 3706 } 3707 } 3708 } 3709 3710 return config; 3711 } 3712 3713 /* 3714 * Determine the new desired orientation of the display, returning 3715 * a non-null new Configuration if it has changed from the current 3716 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL 3717 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE 3718 * SCREEN. This will typically be done for you if you call 3719 * sendNewConfiguration(). 3720 * 3721 * The orientation is computed from non-application windows first. If none of 3722 * the non-application windows specify orientation, the orientation is computed from 3723 * application tokens. 3724 * @see android.view.IWindowManager#updateOrientationFromAppTokens( 3725 * android.os.IBinder) 3726 */ 3727 boolean updateOrientationFromAppTokensLocked(boolean inTransaction) { 3728 long ident = Binder.clearCallingIdentity(); 3729 try { 3730 int req = getOrientationFromWindowsLocked(); 3731 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) { 3732 req = getOrientationFromAppTokensLocked(); 3733 } 3734 3735 if (req != mForcedAppOrientation) { 3736 mForcedAppOrientation = req; 3737 //send a message to Policy indicating orientation change to take 3738 //action like disabling/enabling sensors etc., 3739 mPolicy.setCurrentOrientationLw(req); 3740 if (updateRotationUncheckedLocked(inTransaction)) { 3741 // changed 3742 return true; 3743 } 3744 } 3745 3746 return false; 3747 } finally { 3748 Binder.restoreCallingIdentity(ident); 3749 } 3750 } 3751 3752 @Override 3753 public void setNewConfiguration(Configuration config) { 3754 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3755 "setNewConfiguration()")) { 3756 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3757 } 3758 3759 synchronized(mWindowMap) { 3760 mCurConfiguration = new Configuration(config); 3761 if (mWaitingForConfig) { 3762 mWaitingForConfig = false; 3763 mLastFinishedFreezeSource = "new-config"; 3764 } 3765 performLayoutAndPlaceSurfacesLocked(); 3766 } 3767 } 3768 3769 @Override 3770 public void setAppOrientation(IApplicationToken token, int requestedOrientation) { 3771 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3772 "setAppOrientation()")) { 3773 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3774 } 3775 3776 synchronized(mWindowMap) { 3777 AppWindowToken atoken = findAppWindowToken(token.asBinder()); 3778 if (atoken == null) { 3779 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token); 3780 return; 3781 } 3782 3783 atoken.requestedOrientation = requestedOrientation; 3784 } 3785 } 3786 3787 @Override 3788 public int getAppOrientation(IApplicationToken token) { 3789 synchronized(mWindowMap) { 3790 AppWindowToken wtoken = findAppWindowToken(token.asBinder()); 3791 if (wtoken == null) { 3792 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3793 } 3794 3795 return wtoken.requestedOrientation; 3796 } 3797 } 3798 3799 /** Call while in a Surface transaction. */ 3800 void setFocusedStackLayer() { 3801 mFocusedStackLayer = 0; 3802 if (mFocusedApp != null) { 3803 final WindowList windows = mFocusedApp.allAppWindows; 3804 for (int i = windows.size() - 1; i >= 0; --i) { 3805 final WindowState win = windows.get(i); 3806 final int animLayer = win.mWinAnimator.mAnimLayer; 3807 if (win.mAttachedWindow == null && win.isVisibleLw() && 3808 animLayer > mFocusedStackLayer) { 3809 mFocusedStackLayer = animLayer + LAYER_OFFSET_FOCUSED_STACK; 3810 } 3811 } 3812 } 3813 if (DEBUG_LAYERS) Slog.v(TAG, "Setting FocusedStackFrame to layer=" + 3814 mFocusedStackLayer); 3815 mFocusedStackFrame.setLayer(mFocusedStackLayer); 3816 } 3817 3818 void setFocusedStackFrame() { 3819 final TaskStack stack; 3820 if (mFocusedApp != null) { 3821 Task task = mTaskIdToTask.get(mFocusedApp.groupId); 3822 stack = task.mStack; 3823 final DisplayContent displayContent = task.getDisplayContent(); 3824 if (displayContent != null) { 3825 displayContent.setTouchExcludeRegion(stack); 3826 } 3827 } else { 3828 stack = null; 3829 } 3830 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame"); 3831 SurfaceControl.openTransaction(); 3832 try { 3833 if (stack == null) { 3834 mFocusedStackFrame.setVisibility(false); 3835 } else { 3836 mFocusedStackFrame.setBounds(stack); 3837 final boolean multipleStacks = !stack.isFullscreen(); 3838 mFocusedStackFrame.setVisibility(multipleStacks); 3839 } 3840 } finally { 3841 SurfaceControl.closeTransaction(); 3842 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame"); 3843 } 3844 } 3845 3846 @Override 3847 public void setFocusedApp(IBinder token, boolean moveFocusNow) { 3848 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3849 "setFocusedApp()")) { 3850 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3851 } 3852 3853 synchronized(mWindowMap) { 3854 final AppWindowToken newFocus; 3855 if (token == null) { 3856 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp); 3857 newFocus = null; 3858 } else { 3859 newFocus = findAppWindowToken(token); 3860 if (newFocus == null) { 3861 Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token); 3862 } 3863 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus 3864 + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow); 3865 } 3866 3867 final boolean changed = mFocusedApp != newFocus; 3868 if (changed) { 3869 mFocusedApp = newFocus; 3870 mInputMonitor.setFocusedAppLw(null); 3871 } 3872 3873 if (moveFocusNow && changed) { 3874 final long origId = Binder.clearCallingIdentity(); 3875 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 3876 Binder.restoreCallingIdentity(origId); 3877 } 3878 } 3879 } 3880 3881 @Override 3882 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) { 3883 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3884 "prepareAppTransition()")) { 3885 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3886 } 3887 3888 synchronized(mWindowMap) { 3889 if (DEBUG_APP_TRANSITIONS) Slog.v( 3890 TAG, "Prepare app transition: transit=" + transit 3891 + " " + mAppTransition 3892 + " alwaysKeepCurrent=" + alwaysKeepCurrent 3893 + " Callers=" + Debug.getCallers(3)); 3894 if (!mAppTransition.isTransitionSet() || mAppTransition.isTransitionNone()) { 3895 mAppTransition.setAppTransition(transit); 3896 } else if (!alwaysKeepCurrent) { 3897 if (transit == AppTransition.TRANSIT_TASK_OPEN 3898 && mAppTransition.isTransitionEqual( 3899 AppTransition.TRANSIT_TASK_CLOSE)) { 3900 // Opening a new task always supersedes a close for the anim. 3901 mAppTransition.setAppTransition(transit); 3902 } else if (transit == AppTransition.TRANSIT_ACTIVITY_OPEN 3903 && mAppTransition.isTransitionEqual( 3904 AppTransition.TRANSIT_ACTIVITY_CLOSE)) { 3905 // Opening a new activity always supersedes a close for the anim. 3906 mAppTransition.setAppTransition(transit); 3907 } 3908 } 3909 if (okToDisplay()) { 3910 mAppTransition.prepare(); 3911 mStartingIconInTransition = false; 3912 mSkipAppTransitionAnimation = false; 3913 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 3914 mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000); 3915 } 3916 } 3917 } 3918 3919 @Override 3920 public int getPendingAppTransition() { 3921 return mAppTransition.getAppTransition(); 3922 } 3923 3924 @Override 3925 public void overridePendingAppTransition(String packageName, 3926 int enterAnim, int exitAnim, IRemoteCallback startedCallback) { 3927 synchronized(mWindowMap) { 3928 mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim, 3929 startedCallback); 3930 } 3931 } 3932 3933 @Override 3934 public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, 3935 int startHeight) { 3936 synchronized(mWindowMap) { 3937 mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth, 3938 startHeight); 3939 } 3940 } 3941 3942 @Override 3943 public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, 3944 int startY, IRemoteCallback startedCallback, boolean scaleUp) { 3945 synchronized(mWindowMap) { 3946 mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY, 3947 startedCallback, scaleUp); 3948 } 3949 } 3950 3951 @Override 3952 public void executeAppTransition() { 3953 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3954 "executeAppTransition()")) { 3955 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3956 } 3957 3958 synchronized(mWindowMap) { 3959 if (DEBUG_APP_TRANSITIONS) { 3960 RuntimeException e = new RuntimeException("here"); 3961 e.fillInStackTrace(); 3962 Slog.w(TAG, "Execute app transition: " + mAppTransition, e); 3963 } 3964 if (mAppTransition.isTransitionSet()) { 3965 mAppTransition.setReady(); 3966 final long origId = Binder.clearCallingIdentity(); 3967 performLayoutAndPlaceSurfacesLocked(); 3968 Binder.restoreCallingIdentity(origId); 3969 } 3970 } 3971 } 3972 3973 @Override 3974 public void setAppStartingWindow(IBinder token, String pkg, 3975 int theme, CompatibilityInfo compatInfo, 3976 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, 3977 int windowFlags, IBinder transferFrom, boolean createIfNeeded) { 3978 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3979 "setAppStartingWindow()")) { 3980 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3981 } 3982 3983 synchronized(mWindowMap) { 3984 if (DEBUG_STARTING_WINDOW) Slog.v( 3985 TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg 3986 + " transferFrom=" + transferFrom); 3987 3988 AppWindowToken wtoken = findAppWindowToken(token); 3989 if (wtoken == null) { 3990 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token); 3991 return; 3992 } 3993 3994 // If the display is frozen, we won't do anything until the 3995 // actual window is displayed so there is no reason to put in 3996 // the starting window. 3997 if (!okToDisplay()) { 3998 return; 3999 } 4000 4001 if (wtoken.startingData != null) { 4002 return; 4003 } 4004 4005 if (transferFrom != null) { 4006 AppWindowToken ttoken = findAppWindowToken(transferFrom); 4007 if (ttoken != null) { 4008 WindowState startingWindow = ttoken.startingWindow; 4009 if (startingWindow != null) { 4010 if (mStartingIconInTransition) { 4011 // In this case, the starting icon has already 4012 // been displayed, so start letting windows get 4013 // shown immediately without any more transitions. 4014 mSkipAppTransitionAnimation = true; 4015 } 4016 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4017 "Moving existing starting " + startingWindow + " from " + ttoken 4018 + " to " + wtoken); 4019 final long origId = Binder.clearCallingIdentity(); 4020 4021 // Transfer the starting window over to the new 4022 // token. 4023 wtoken.startingData = ttoken.startingData; 4024 wtoken.startingView = ttoken.startingView; 4025 wtoken.startingDisplayed = ttoken.startingDisplayed; 4026 ttoken.startingDisplayed = false; 4027 wtoken.startingWindow = startingWindow; 4028 wtoken.reportedVisible = ttoken.reportedVisible; 4029 ttoken.startingData = null; 4030 ttoken.startingView = null; 4031 ttoken.startingWindow = null; 4032 ttoken.startingMoved = true; 4033 startingWindow.mToken = wtoken; 4034 startingWindow.mRootToken = wtoken; 4035 startingWindow.mAppToken = wtoken; 4036 startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator; 4037 4038 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) { 4039 Slog.v(TAG, "Removing starting window: " + startingWindow); 4040 } 4041 startingWindow.getWindowList().remove(startingWindow); 4042 mWindowsChanged = true; 4043 if (DEBUG_ADD_REMOVE) Slog.v(TAG, 4044 "Removing starting " + startingWindow + " from " + ttoken); 4045 ttoken.windows.remove(startingWindow); 4046 ttoken.allAppWindows.remove(startingWindow); 4047 addWindowToListInOrderLocked(startingWindow, true); 4048 4049 // Propagate other interesting state between the 4050 // tokens. If the old token is displayed, we should 4051 // immediately force the new one to be displayed. If 4052 // it is animating, we need to move that animation to 4053 // the new one. 4054 if (ttoken.allDrawn) { 4055 wtoken.allDrawn = true; 4056 wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn; 4057 } 4058 if (ttoken.firstWindowDrawn) { 4059 wtoken.firstWindowDrawn = true; 4060 } 4061 if (!ttoken.hidden) { 4062 wtoken.hidden = false; 4063 wtoken.hiddenRequested = false; 4064 wtoken.willBeHidden = false; 4065 } 4066 if (wtoken.clientHidden != ttoken.clientHidden) { 4067 wtoken.clientHidden = ttoken.clientHidden; 4068 wtoken.sendAppVisibilityToClients(); 4069 } 4070 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4071 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4072 if (tAppAnimator.animation != null) { 4073 wAppAnimator.animation = tAppAnimator.animation; 4074 wAppAnimator.animating = tAppAnimator.animating; 4075 wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment; 4076 tAppAnimator.animation = null; 4077 tAppAnimator.animLayerAdjustment = 0; 4078 wAppAnimator.updateLayers(); 4079 tAppAnimator.updateLayers(); 4080 } 4081 4082 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4083 true /*updateInputWindows*/); 4084 getDefaultDisplayContentLocked().layoutNeeded = true; 4085 performLayoutAndPlaceSurfacesLocked(); 4086 Binder.restoreCallingIdentity(origId); 4087 return; 4088 } else if (ttoken.startingData != null) { 4089 // The previous app was getting ready to show a 4090 // starting window, but hasn't yet done so. Steal it! 4091 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4092 "Moving pending starting from " + ttoken 4093 + " to " + wtoken); 4094 wtoken.startingData = ttoken.startingData; 4095 ttoken.startingData = null; 4096 ttoken.startingMoved = true; 4097 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4098 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4099 // want to process the message ASAP, before any other queued 4100 // messages. 4101 mH.sendMessageAtFrontOfQueue(m); 4102 return; 4103 } 4104 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4105 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4106 if (tAppAnimator.thumbnail != null) { 4107 // The old token is animating with a thumbnail, transfer 4108 // that to the new token. 4109 if (wAppAnimator.thumbnail != null) { 4110 wAppAnimator.thumbnail.destroy(); 4111 } 4112 wAppAnimator.thumbnail = tAppAnimator.thumbnail; 4113 wAppAnimator.thumbnailX = tAppAnimator.thumbnailX; 4114 wAppAnimator.thumbnailY = tAppAnimator.thumbnailY; 4115 wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer; 4116 wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation; 4117 tAppAnimator.thumbnail = null; 4118 } 4119 } 4120 } 4121 4122 // There is no existing starting window, and the caller doesn't 4123 // want us to create one, so that's it! 4124 if (!createIfNeeded) { 4125 return; 4126 } 4127 4128 // If this is a translucent window, then don't 4129 // show a starting window -- the current effect (a full-screen 4130 // opaque starting window that fades away to the real contents 4131 // when it is ready) does not work for this. 4132 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x" 4133 + Integer.toHexString(theme)); 4134 if (theme != 0) { 4135 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme, 4136 com.android.internal.R.styleable.Window, mCurrentUserId); 4137 if (ent == null) { 4138 // Whoops! App doesn't exist. Um. Okay. We'll just 4139 // pretend like we didn't see that. 4140 return; 4141 } 4142 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent=" 4143 + ent.array.getBoolean( 4144 com.android.internal.R.styleable.Window_windowIsTranslucent, false) 4145 + " Floating=" 4146 + ent.array.getBoolean( 4147 com.android.internal.R.styleable.Window_windowIsFloating, false) 4148 + " ShowWallpaper=" 4149 + ent.array.getBoolean( 4150 com.android.internal.R.styleable.Window_windowShowWallpaper, false)); 4151 if (ent.array.getBoolean( 4152 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) { 4153 return; 4154 } 4155 if (ent.array.getBoolean( 4156 com.android.internal.R.styleable.Window_windowIsFloating, false)) { 4157 return; 4158 } 4159 if (ent.array.getBoolean( 4160 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) { 4161 if (mWallpaperTarget == null) { 4162 // If this theme is requesting a wallpaper, and the wallpaper 4163 // is not curently visible, then this effectively serves as 4164 // an opaque window and our starting window transition animation 4165 // can still work. We just need to make sure the starting window 4166 // is also showing the wallpaper. 4167 windowFlags |= FLAG_SHOW_WALLPAPER; 4168 } else { 4169 return; 4170 } 4171 } 4172 } 4173 4174 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData"); 4175 mStartingIconInTransition = true; 4176 wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel, 4177 labelRes, icon, logo, windowFlags); 4178 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4179 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4180 // want to process the message ASAP, before any other queued 4181 // messages. 4182 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING"); 4183 mH.sendMessageAtFrontOfQueue(m); 4184 } 4185 } 4186 4187 public void removeAppStartingWindow(IBinder token) { 4188 synchronized (mWindowMap) { 4189 AppWindowToken wtoken = mTokenMap.get(token).appWindowToken; 4190 if (wtoken.startingWindow != null) { 4191 scheduleRemoveStartingWindow(wtoken); 4192 } 4193 } 4194 } 4195 4196 @Override 4197 public void setAppWillBeHidden(IBinder token) { 4198 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4199 "setAppWillBeHidden()")) { 4200 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4201 } 4202 4203 AppWindowToken wtoken; 4204 4205 synchronized(mWindowMap) { 4206 wtoken = findAppWindowToken(token); 4207 if (wtoken == null) { 4208 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token); 4209 return; 4210 } 4211 wtoken.willBeHidden = true; 4212 } 4213 } 4214 4215 public void setAppFullscreen(IBinder token, boolean toOpaque) { 4216 AppWindowToken atoken = findAppWindowToken(token); 4217 if (atoken != null) { 4218 atoken.appFullscreen = toOpaque; 4219 // When making translucent, wait until windows below have been drawn. 4220 if (toOpaque) { 4221 // Making opaque so do it now. 4222 setWindowOpaque(token, true); 4223 } 4224 requestTraversal(); 4225 } 4226 } 4227 4228 public void setWindowOpaque(IBinder token, boolean isOpaque) { 4229 AppWindowToken wtoken = findAppWindowToken(token); 4230 if (wtoken != null) { 4231 WindowState win = wtoken.findMainWindow(); 4232 if (win != null) { 4233 win.mWinAnimator.setOpaque(isOpaque); 4234 } 4235 } 4236 } 4237 4238 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp, 4239 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) { 4240 boolean delayed = false; 4241 4242 if (wtoken.clientHidden == visible) { 4243 wtoken.clientHidden = !visible; 4244 wtoken.sendAppVisibilityToClients(); 4245 } 4246 4247 wtoken.willBeHidden = false; 4248 if (wtoken.hidden == visible) { 4249 boolean changed = false; 4250 if (DEBUG_APP_TRANSITIONS) Slog.v( 4251 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden 4252 + " performLayout=" + performLayout); 4253 4254 boolean runningAppAnimation = false; 4255 4256 if (transit != AppTransition.TRANSIT_UNSET) { 4257 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { 4258 wtoken.mAppAnimator.animation = null; 4259 } 4260 if (applyAnimationLocked(wtoken, lp, transit, visible, isVoiceInteraction)) { 4261 delayed = runningAppAnimation = true; 4262 } 4263 WindowState window = wtoken.findMainWindow(); 4264 //TODO (multidisplay): Magnification is supported only for the default display. 4265 if (window != null && mAccessibilityController != null 4266 && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 4267 mAccessibilityController.onAppWindowTransitionLocked(window, transit); 4268 } 4269 changed = true; 4270 } 4271 4272 final int N = wtoken.allAppWindows.size(); 4273 for (int i=0; i<N; i++) { 4274 WindowState win = wtoken.allAppWindows.get(i); 4275 if (win == wtoken.startingWindow) { 4276 continue; 4277 } 4278 4279 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible()); 4280 //win.dump(" "); 4281 if (visible) { 4282 if (!win.isVisibleNow()) { 4283 if (!runningAppAnimation) { 4284 win.mWinAnimator.applyAnimationLocked( 4285 WindowManagerPolicy.TRANSIT_ENTER, true); 4286 //TODO (multidisplay): Magnification is supported only for the default 4287 if (mAccessibilityController != null 4288 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4289 mAccessibilityController.onWindowTransitionLocked(win, 4290 WindowManagerPolicy.TRANSIT_ENTER); 4291 } 4292 } 4293 changed = true; 4294 final DisplayContent displayContent = win.getDisplayContent(); 4295 if (displayContent != null) { 4296 displayContent.layoutNeeded = true; 4297 } 4298 } 4299 } else if (win.isVisibleNow()) { 4300 if (!runningAppAnimation) { 4301 win.mWinAnimator.applyAnimationLocked( 4302 WindowManagerPolicy.TRANSIT_EXIT, false); 4303 //TODO (multidisplay): Magnification is supported only for the default 4304 if (mAccessibilityController != null 4305 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4306 mAccessibilityController.onWindowTransitionLocked(win, 4307 WindowManagerPolicy.TRANSIT_EXIT); 4308 } 4309 } 4310 changed = true; 4311 final DisplayContent displayContent = win.getDisplayContent(); 4312 if (displayContent != null) { 4313 displayContent.layoutNeeded = true; 4314 } 4315 } 4316 } 4317 4318 wtoken.hidden = wtoken.hiddenRequested = !visible; 4319 if (!visible) { 4320 unsetAppFreezingScreenLocked(wtoken, true, true); 4321 } else { 4322 // If we are being set visible, and the starting window is 4323 // not yet displayed, then make sure it doesn't get displayed. 4324 WindowState swin = wtoken.startingWindow; 4325 if (swin != null && !swin.isDrawnLw()) { 4326 swin.mPolicyVisibility = false; 4327 swin.mPolicyVisibilityAfterAnim = false; 4328 } 4329 } 4330 4331 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken 4332 + ": hidden=" + wtoken.hidden + " hiddenRequested=" 4333 + wtoken.hiddenRequested); 4334 4335 if (changed) { 4336 mInputMonitor.setUpdateInputWindowsNeededLw(); 4337 if (performLayout) { 4338 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4339 false /*updateInputWindows*/); 4340 performLayoutAndPlaceSurfacesLocked(); 4341 } 4342 mInputMonitor.updateInputWindowsLw(false /*force*/); 4343 } 4344 } 4345 4346 if (wtoken.mAppAnimator.animation != null) { 4347 delayed = true; 4348 } 4349 4350 for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) { 4351 if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) { 4352 delayed = true; 4353 } 4354 } 4355 4356 return delayed; 4357 } 4358 4359 @Override 4360 public void setAppVisibility(IBinder token, boolean visible) { 4361 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4362 "setAppVisibility()")) { 4363 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4364 } 4365 4366 AppWindowToken wtoken; 4367 4368 synchronized(mWindowMap) { 4369 wtoken = findAppWindowToken(token); 4370 if (wtoken == null) { 4371 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token); 4372 return; 4373 } 4374 4375 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) { 4376 RuntimeException e = null; 4377 if (!HIDE_STACK_CRAWLS) { 4378 e = new RuntimeException(); 4379 e.fillInStackTrace(); 4380 } 4381 Slog.v(TAG, "setAppVisibility(" + token + ", visible=" + visible 4382 + "): " + mAppTransition 4383 + " hidden=" + wtoken.hidden 4384 + " hiddenRequested=" + wtoken.hiddenRequested, e); 4385 } 4386 4387 // If we are preparing an app transition, then delay changing 4388 // the visibility of this token until we execute that transition. 4389 if (okToDisplay() && mAppTransition.isTransitionSet()) { 4390 wtoken.hiddenRequested = !visible; 4391 4392 if (!wtoken.startingDisplayed) { 4393 if (DEBUG_APP_TRANSITIONS) Slog.v( 4394 TAG, "Setting dummy animation on: " + wtoken); 4395 wtoken.mAppAnimator.setDummyAnimation(); 4396 } 4397 mOpeningApps.remove(wtoken); 4398 mClosingApps.remove(wtoken); 4399 wtoken.waitingToShow = wtoken.waitingToHide = false; 4400 wtoken.inPendingTransaction = true; 4401 if (visible) { 4402 mOpeningApps.add(wtoken); 4403 wtoken.startingMoved = false; 4404 4405 // If the token is currently hidden (should be the 4406 // common case), then we need to set up to wait for 4407 // its windows to be ready. 4408 if (wtoken.hidden) { 4409 wtoken.allDrawn = false; 4410 wtoken.deferClearAllDrawn = false; 4411 wtoken.waitingToShow = true; 4412 4413 if (wtoken.clientHidden) { 4414 // In the case where we are making an app visible 4415 // but holding off for a transition, we still need 4416 // to tell the client to make its windows visible so 4417 // they get drawn. Otherwise, we will wait on 4418 // performing the transition until all windows have 4419 // been drawn, they never will be, and we are sad. 4420 wtoken.clientHidden = false; 4421 wtoken.sendAppVisibilityToClients(); 4422 } 4423 } 4424 } else { 4425 mClosingApps.add(wtoken); 4426 4427 // If the token is currently visible (should be the 4428 // common case), then set up to wait for it to be hidden. 4429 if (!wtoken.hidden) { 4430 wtoken.waitingToHide = true; 4431 } 4432 } 4433 return; 4434 } 4435 4436 final long origId = Binder.clearCallingIdentity(); 4437 setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET, 4438 true, wtoken.voiceInteraction); 4439 wtoken.updateReportedVisibilityLocked(); 4440 Binder.restoreCallingIdentity(origId); 4441 } 4442 } 4443 4444 void unsetAppFreezingScreenLocked(AppWindowToken wtoken, 4445 boolean unfreezeSurfaceNow, boolean force) { 4446 if (wtoken.mAppAnimator.freezingScreen) { 4447 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken 4448 + " force=" + force); 4449 final int N = wtoken.allAppWindows.size(); 4450 boolean unfrozeWindows = false; 4451 for (int i=0; i<N; i++) { 4452 WindowState w = wtoken.allAppWindows.get(i); 4453 if (w.mAppFreezing) { 4454 w.mAppFreezing = false; 4455 if (w.mHasSurface && !w.mOrientationChanging) { 4456 if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w); 4457 w.mOrientationChanging = true; 4458 mInnerFields.mOrientationChangeComplete = false; 4459 } 4460 w.mLastFreezeDuration = 0; 4461 unfrozeWindows = true; 4462 final DisplayContent displayContent = w.getDisplayContent(); 4463 if (displayContent != null) { 4464 displayContent.layoutNeeded = true; 4465 } 4466 } 4467 } 4468 if (force || unfrozeWindows) { 4469 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken); 4470 wtoken.mAppAnimator.freezingScreen = false; 4471 wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime() 4472 - mDisplayFreezeTime); 4473 mAppsFreezingScreen--; 4474 mLastFinishedFreezeSource = wtoken; 4475 } 4476 if (unfreezeSurfaceNow) { 4477 if (unfrozeWindows) { 4478 performLayoutAndPlaceSurfacesLocked(); 4479 } 4480 stopFreezingDisplayLocked(); 4481 } 4482 } 4483 } 4484 4485 private void startAppFreezingScreenLocked(AppWindowToken wtoken) { 4486 if (DEBUG_ORIENTATION) { 4487 RuntimeException e = null; 4488 if (!HIDE_STACK_CRAWLS) { 4489 e = new RuntimeException(); 4490 e.fillInStackTrace(); 4491 } 4492 Slog.i(TAG, "Set freezing of " + wtoken.appToken 4493 + ": hidden=" + wtoken.hidden + " freezing=" 4494 + wtoken.mAppAnimator.freezingScreen, e); 4495 } 4496 if (!wtoken.hiddenRequested) { 4497 if (!wtoken.mAppAnimator.freezingScreen) { 4498 wtoken.mAppAnimator.freezingScreen = true; 4499 wtoken.mAppAnimator.lastFreezeDuration = 0; 4500 mAppsFreezingScreen++; 4501 if (mAppsFreezingScreen == 1) { 4502 startFreezingDisplayLocked(false, 0, 0); 4503 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 4504 mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000); 4505 } 4506 } 4507 final int N = wtoken.allAppWindows.size(); 4508 for (int i=0; i<N; i++) { 4509 WindowState w = wtoken.allAppWindows.get(i); 4510 w.mAppFreezing = true; 4511 } 4512 } 4513 } 4514 4515 @Override 4516 public void startAppFreezingScreen(IBinder token, int configChanges) { 4517 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4518 "setAppFreezingScreen()")) { 4519 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4520 } 4521 4522 synchronized(mWindowMap) { 4523 if (configChanges == 0 && okToDisplay()) { 4524 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token); 4525 return; 4526 } 4527 4528 AppWindowToken wtoken = findAppWindowToken(token); 4529 if (wtoken == null || wtoken.appToken == null) { 4530 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken); 4531 return; 4532 } 4533 final long origId = Binder.clearCallingIdentity(); 4534 startAppFreezingScreenLocked(wtoken); 4535 Binder.restoreCallingIdentity(origId); 4536 } 4537 } 4538 4539 @Override 4540 public void stopAppFreezingScreen(IBinder token, boolean force) { 4541 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4542 "setAppFreezingScreen()")) { 4543 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4544 } 4545 4546 synchronized(mWindowMap) { 4547 AppWindowToken wtoken = findAppWindowToken(token); 4548 if (wtoken == null || wtoken.appToken == null) { 4549 return; 4550 } 4551 final long origId = Binder.clearCallingIdentity(); 4552 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token 4553 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen); 4554 unsetAppFreezingScreenLocked(wtoken, true, force); 4555 Binder.restoreCallingIdentity(origId); 4556 } 4557 } 4558 4559 void removeAppFromTaskLocked(AppWindowToken wtoken) { 4560 final Task task = mTaskIdToTask.get(wtoken.groupId); 4561 if (task != null) { 4562 if (!task.removeAppToken(wtoken)) { 4563 Slog.e(TAG, "removeAppFromTaskLocked: token=" + wtoken + " not found."); 4564 } 4565 } 4566 } 4567 4568 @Override 4569 public void removeAppToken(IBinder token) { 4570 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4571 "removeAppToken()")) { 4572 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4573 } 4574 4575 AppWindowToken wtoken = null; 4576 AppWindowToken startingToken = null; 4577 boolean delayed = false; 4578 4579 final long origId = Binder.clearCallingIdentity(); 4580 synchronized(mWindowMap) { 4581 WindowToken basewtoken = mTokenMap.remove(token); 4582 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) { 4583 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken); 4584 delayed = setTokenVisibilityLocked(wtoken, null, false, 4585 AppTransition.TRANSIT_UNSET, true, wtoken.voiceInteraction); 4586 wtoken.inPendingTransaction = false; 4587 mOpeningApps.remove(wtoken); 4588 wtoken.waitingToShow = false; 4589 if (mClosingApps.contains(wtoken)) { 4590 delayed = true; 4591 } else if (mAppTransition.isTransitionSet()) { 4592 mClosingApps.add(wtoken); 4593 wtoken.waitingToHide = true; 4594 delayed = true; 4595 } 4596 if (DEBUG_APP_TRANSITIONS) Slog.v( 4597 TAG, "Removing app " + wtoken + " delayed=" + delayed 4598 + " animation=" + wtoken.mAppAnimator.animation 4599 + " animating=" + wtoken.mAppAnimator.animating); 4600 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: " 4601 + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4)); 4602 final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack; 4603 if (delayed) { 4604 // set the token aside because it has an active animation to be finished 4605 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4606 "removeAppToken make exiting: " + wtoken); 4607 stack.mExitingAppTokens.add(wtoken); 4608 wtoken.mDeferRemoval = true; 4609 } else { 4610 // Make sure there is no animation running on this token, 4611 // so any windows associated with it will be removed as 4612 // soon as their animations are complete 4613 wtoken.mAppAnimator.clearAnimation(); 4614 wtoken.mAppAnimator.animating = false; 4615 removeAppFromTaskLocked(wtoken); 4616 } 4617 4618 wtoken.removed = true; 4619 if (wtoken.startingData != null) { 4620 startingToken = wtoken; 4621 } 4622 unsetAppFreezingScreenLocked(wtoken, true, true); 4623 if (mFocusedApp == wtoken) { 4624 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Removing focused app token:" + wtoken); 4625 mFocusedApp = null; 4626 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 4627 mInputMonitor.setFocusedAppLw(null); 4628 } 4629 } else { 4630 Slog.w(TAG, "Attempted to remove non-existing app token: " + token); 4631 } 4632 4633 if (!delayed && wtoken != null) { 4634 wtoken.updateReportedVisibilityLocked(); 4635 } 4636 } 4637 Binder.restoreCallingIdentity(origId); 4638 4639 // Will only remove if startingToken non null. 4640 scheduleRemoveStartingWindow(startingToken); 4641 } 4642 4643 void scheduleRemoveStartingWindow(AppWindowToken wtoken) { 4644 if (wtoken != null && wtoken.startingWindow != null) { 4645 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) + 4646 ": Schedule remove starting " + wtoken + (wtoken != null ? 4647 " startingWindow=" + wtoken.startingWindow : "")); 4648 Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken); 4649 mH.sendMessage(m); 4650 } 4651 } 4652 4653 private boolean tmpRemoveAppWindowsLocked(WindowToken token) { 4654 WindowList windows = token.windows; 4655 final int NW = windows.size(); 4656 if (NW > 0) { 4657 mWindowsChanged = true; 4658 } 4659 for (int i = 0; i < NW; i++) { 4660 WindowState win = windows.get(i); 4661 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win); 4662 win.getWindowList().remove(win); 4663 int j = win.mChildWindows.size(); 4664 while (j > 0) { 4665 j--; 4666 WindowState cwin = win.mChildWindows.get(j); 4667 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 4668 "Tmp removing child window " + cwin); 4669 cwin.getWindowList().remove(cwin); 4670 } 4671 } 4672 return NW > 0; 4673 } 4674 4675 void dumpAppTokensLocked() { 4676 final int numStacks = mStackIdToStack.size(); 4677 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 4678 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 4679 Slog.v(TAG, " Stack #" + stack.mStackId + " tasks from bottom to top:"); 4680 final ArrayList<Task> tasks = stack.getTasks(); 4681 final int numTasks = tasks.size(); 4682 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4683 final Task task = tasks.get(taskNdx); 4684 Slog.v(TAG, " Task #" + task.taskId + " activities from bottom to top:"); 4685 AppTokenList tokens = task.mAppTokens; 4686 final int numTokens = tokens.size(); 4687 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 4688 Slog.v(TAG, " activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token); 4689 } 4690 } 4691 } 4692 } 4693 4694 void dumpWindowsLocked() { 4695 final int numDisplays = mDisplayContents.size(); 4696 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 4697 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 4698 Slog.v(TAG, " Display #" + displayContent.getDisplayId()); 4699 final WindowList windows = displayContent.getWindowList(); 4700 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 4701 Slog.v(TAG, " #" + winNdx + ": " + windows.get(winNdx)); 4702 } 4703 } 4704 } 4705 4706 private int findAppWindowInsertionPointLocked(AppWindowToken target) { 4707 final int taskId = target.groupId; 4708 Task targetTask = mTaskIdToTask.get(taskId); 4709 if (targetTask == null) { 4710 Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId=" 4711 + taskId); 4712 return 0; 4713 } 4714 DisplayContent displayContent = targetTask.getDisplayContent(); 4715 if (displayContent == null) { 4716 Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target); 4717 return 0; 4718 } 4719 final WindowList windows = displayContent.getWindowList(); 4720 final int NW = windows.size(); 4721 4722 boolean found = false; 4723 final ArrayList<Task> tasks = displayContent.getTasks(); 4724 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 4725 final Task task = tasks.get(taskNdx); 4726 if (!found && task.taskId != taskId) { 4727 continue; 4728 } 4729 AppTokenList tokens = task.mAppTokens; 4730 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 4731 final AppWindowToken wtoken = tokens.get(tokenNdx); 4732 if (!found && wtoken == target) { 4733 found = true; 4734 } 4735 if (found) { 4736 // Find the first app token below the new position that has 4737 // a window displayed. 4738 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token); 4739 if (wtoken.sendingToBottom) { 4740 if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom"); 4741 continue; 4742 } 4743 for (int i = wtoken.windows.size() - 1; i >= 0; --i) { 4744 WindowState win = wtoken.windows.get(i); 4745 for (int j = win.mChildWindows.size() - 1; j >= 0; --j) { 4746 WindowState cwin = win.mChildWindows.get(j); 4747 if (cwin.mSubLayer >= 0) { 4748 for (int pos = NW - 1; pos >= 0; pos--) { 4749 if (windows.get(pos) == cwin) { 4750 if (DEBUG_REORDER) Slog.v(TAG, 4751 "Found child win @" + (pos + 1)); 4752 return pos + 1; 4753 } 4754 } 4755 } 4756 } 4757 for (int pos = NW - 1; pos >= 0; pos--) { 4758 if (windows.get(pos) == win) { 4759 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1)); 4760 return pos + 1; 4761 } 4762 } 4763 } 4764 } 4765 } 4766 } 4767 // Never put an app window underneath wallpaper. 4768 for (int pos = NW - 1; pos >= 0; pos--) { 4769 if (windows.get(pos).mIsWallpaper) { 4770 if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos); 4771 return pos + 1; 4772 } 4773 } 4774 return 0; 4775 } 4776 4777 private final int reAddWindowLocked(int index, WindowState win) { 4778 final WindowList windows = win.getWindowList(); 4779 final int NCW = win.mChildWindows.size(); 4780 boolean added = false; 4781 for (int j=0; j<NCW; j++) { 4782 WindowState cwin = win.mChildWindows.get(j); 4783 if (!added && cwin.mSubLayer >= 0) { 4784 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at " 4785 + index + ": " + cwin); 4786 win.mRebuilding = false; 4787 windows.add(index, win); 4788 index++; 4789 added = true; 4790 } 4791 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4792 + index + ": " + cwin); 4793 cwin.mRebuilding = false; 4794 windows.add(index, cwin); 4795 index++; 4796 } 4797 if (!added) { 4798 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4799 + index + ": " + win); 4800 win.mRebuilding = false; 4801 windows.add(index, win); 4802 index++; 4803 } 4804 mWindowsChanged = true; 4805 return index; 4806 } 4807 4808 private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index, 4809 WindowToken token) { 4810 final int NW = token.windows.size(); 4811 for (int i=0; i<NW; i++) { 4812 final WindowState win = token.windows.get(i); 4813 final DisplayContent winDisplayContent = win.getDisplayContent(); 4814 if (winDisplayContent == displayContent || winDisplayContent == null) { 4815 win.mDisplayContent = displayContent; 4816 index = reAddWindowLocked(index, win); 4817 } 4818 } 4819 return index; 4820 } 4821 4822 void tmpRemoveTaskWindowsLocked(Task task) { 4823 AppTokenList tokens = task.mAppTokens; 4824 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 4825 tmpRemoveAppWindowsLocked(tokens.get(tokenNdx)); 4826 } 4827 } 4828 4829 void moveStackWindowsLocked(DisplayContent displayContent) { 4830 // First remove all of the windows from the list. 4831 final ArrayList<Task> tasks = displayContent.getTasks(); 4832 final int numTasks = tasks.size(); 4833 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4834 tmpRemoveTaskWindowsLocked(tasks.get(taskNdx)); 4835 } 4836 4837 // And now add them back at the correct place. 4838 // Where to start adding? 4839 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4840 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 4841 int pos = findAppWindowInsertionPointLocked(tokens.get(0)); 4842 final int numTokens = tokens.size(); 4843 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 4844 final AppWindowToken wtoken = tokens.get(tokenNdx); 4845 if (wtoken != null) { 4846 final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken); 4847 if (newPos != pos) { 4848 displayContent.layoutNeeded = true; 4849 } 4850 pos = newPos; 4851 } 4852 } 4853 } 4854 4855 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4856 false /*updateInputWindows*/)) { 4857 assignLayersLocked(displayContent.getWindowList()); 4858 } 4859 4860 mInputMonitor.setUpdateInputWindowsNeededLw(); 4861 performLayoutAndPlaceSurfacesLocked(); 4862 mInputMonitor.updateInputWindowsLw(false /*force*/); 4863 4864 //dump(); 4865 } 4866 4867 public void moveTaskToTop(int taskId) { 4868 final long origId = Binder.clearCallingIdentity(); 4869 try { 4870 synchronized(mWindowMap) { 4871 Task task = mTaskIdToTask.get(taskId); 4872 if (task == null) { 4873 // Normal behavior, addAppToken will be called next and task will be created. 4874 return; 4875 } 4876 final TaskStack stack = task.mStack; 4877 final DisplayContent displayContent = task.getDisplayContent(); 4878 displayContent.moveStack(stack, true); 4879 if (displayContent.isDefaultDisplay) { 4880 final TaskStack homeStack = displayContent.getHomeStack(); 4881 if (homeStack != stack) { 4882 // When a non-home stack moves to the top, the home stack moves to the 4883 // bottom. 4884 displayContent.moveStack(homeStack, false); 4885 } 4886 } 4887 stack.moveTaskToTop(task); 4888 } 4889 } finally { 4890 Binder.restoreCallingIdentity(origId); 4891 } 4892 } 4893 4894 public void moveTaskToBottom(int taskId) { 4895 final long origId = Binder.clearCallingIdentity(); 4896 try { 4897 synchronized(mWindowMap) { 4898 Task task = mTaskIdToTask.get(taskId); 4899 if (task == null) { 4900 Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId 4901 + " not found in mTaskIdToTask"); 4902 return; 4903 } 4904 final TaskStack stack = task.mStack; 4905 stack.moveTaskToBottom(task); 4906 moveStackWindowsLocked(stack.getDisplayContent()); 4907 } 4908 } finally { 4909 Binder.restoreCallingIdentity(origId); 4910 } 4911 } 4912 4913 /** 4914 * Create a new TaskStack and place it on a DisplayContent. 4915 * @param stackId The unique identifier of the new stack. 4916 * @param displayId The unique identifier of the DisplayContent. 4917 */ 4918 public void attachStack(int stackId, int displayId) { 4919 final long origId = Binder.clearCallingIdentity(); 4920 try { 4921 synchronized (mWindowMap) { 4922 final DisplayContent displayContent = mDisplayContents.get(displayId); 4923 if (displayContent != null) { 4924 TaskStack stack = mStackIdToStack.get(stackId); 4925 if (stack == null) { 4926 if (DEBUG_STACK) Slog.d(TAG, "attachStack: stackId=" + stackId); 4927 stack = new TaskStack(this, stackId); 4928 mStackIdToStack.put(stackId, stack); 4929 } 4930 stack.attachDisplayContent(displayContent); 4931 displayContent.attachStack(stack); 4932 moveStackWindowsLocked(displayContent); 4933 final WindowList windows = displayContent.getWindowList(); 4934 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 4935 windows.get(winNdx).reportResized(); 4936 } 4937 } 4938 } 4939 } finally { 4940 Binder.restoreCallingIdentity(origId); 4941 } 4942 } 4943 4944 void detachStackLocked(DisplayContent displayContent, TaskStack stack) { 4945 displayContent.detachStack(stack); 4946 stack.detachDisplay(); 4947 } 4948 4949 public void detachStack(int stackId) { 4950 synchronized (mWindowMap) { 4951 TaskStack stack = mStackIdToStack.get(stackId); 4952 if (stack != null) { 4953 final DisplayContent displayContent = stack.getDisplayContent(); 4954 if (displayContent != null) { 4955 if (stack.isAnimating()) { 4956 stack.mDeferDetach = true; 4957 return; 4958 } 4959 detachStackLocked(displayContent, stack); 4960 } 4961 } 4962 } 4963 } 4964 4965 public void removeStack(int stackId) { 4966 mStackIdToStack.remove(stackId); 4967 } 4968 4969 void removeTaskLocked(Task task) { 4970 final int taskId = task.taskId; 4971 final TaskStack stack = task.mStack; 4972 if (stack.isAnimating()) { 4973 if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId); 4974 task.mDeferRemoval = true; 4975 return; 4976 } 4977 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId); 4978 EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask"); 4979 task.mDeferRemoval = false; 4980 task.mStack.removeTask(task); 4981 mTaskIdToTask.delete(task.taskId); 4982 } 4983 4984 public void removeTask(int taskId) { 4985 synchronized (mWindowMap) { 4986 Task task = mTaskIdToTask.get(taskId); 4987 if (task == null) { 4988 if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId); 4989 return; 4990 } 4991 removeTaskLocked(task); 4992 } 4993 } 4994 4995 public void addTask(int taskId, int stackId, boolean toTop) { 4996 synchronized (mWindowMap) { 4997 if (DEBUG_STACK) Slog.i(TAG, "addTask: adding taskId=" + taskId 4998 + " to " + (toTop ? "top" : "bottom")); 4999 Task task = mTaskIdToTask.get(taskId); 5000 if (task == null) { 5001 return; 5002 } 5003 TaskStack stack = mStackIdToStack.get(stackId); 5004 stack.addTask(task, toTop); 5005 final DisplayContent displayContent = stack.getDisplayContent(); 5006 displayContent.layoutNeeded = true; 5007 performLayoutAndPlaceSurfacesLocked(); 5008 } 5009 } 5010 5011 public void resizeStack(int stackId, Rect bounds) { 5012 synchronized (mWindowMap) { 5013 final TaskStack stack = mStackIdToStack.get(stackId); 5014 if (stack == null) { 5015 throw new IllegalArgumentException("resizeStack: stackId " + stackId 5016 + " not found."); 5017 } 5018 if (stack.setBounds(bounds)) { 5019 stack.resizeWindows(); 5020 stack.getDisplayContent().layoutNeeded = true; 5021 performLayoutAndPlaceSurfacesLocked(); 5022 } 5023 } 5024 } 5025 5026 public void getStackBounds(int stackId, Rect bounds) { 5027 final TaskStack stack = mStackIdToStack.get(stackId); 5028 if (stack != null) { 5029 stack.getBounds(bounds); 5030 return; 5031 } 5032 bounds.setEmpty(); 5033 } 5034 5035 // ------------------------------------------------------------- 5036 // Misc IWindowSession methods 5037 // ------------------------------------------------------------- 5038 5039 @Override 5040 public void startFreezingScreen(int exitAnim, int enterAnim) { 5041 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5042 "startFreezingScreen()")) { 5043 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5044 } 5045 5046 synchronized(mWindowMap) { 5047 if (!mClientFreezingScreen) { 5048 mClientFreezingScreen = true; 5049 final long origId = Binder.clearCallingIdentity(); 5050 try { 5051 startFreezingDisplayLocked(false, exitAnim, enterAnim); 5052 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 5053 mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000); 5054 } finally { 5055 Binder.restoreCallingIdentity(origId); 5056 } 5057 } 5058 } 5059 } 5060 5061 @Override 5062 public void stopFreezingScreen() { 5063 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5064 "stopFreezingScreen()")) { 5065 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5066 } 5067 5068 synchronized(mWindowMap) { 5069 if (mClientFreezingScreen) { 5070 mClientFreezingScreen = false; 5071 mLastFinishedFreezeSource = "client"; 5072 final long origId = Binder.clearCallingIdentity(); 5073 try { 5074 stopFreezingDisplayLocked(); 5075 } finally { 5076 Binder.restoreCallingIdentity(origId); 5077 } 5078 } 5079 } 5080 } 5081 5082 @Override 5083 public void disableKeyguard(IBinder token, String tag) { 5084 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5085 != PackageManager.PERMISSION_GRANTED) { 5086 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5087 } 5088 5089 if (token == null) { 5090 throw new IllegalArgumentException("token == null"); 5091 } 5092 5093 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5094 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag))); 5095 } 5096 5097 @Override 5098 public void reenableKeyguard(IBinder token) { 5099 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5100 != PackageManager.PERMISSION_GRANTED) { 5101 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5102 } 5103 5104 if (token == null) { 5105 throw new IllegalArgumentException("token == null"); 5106 } 5107 5108 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5109 KeyguardDisableHandler.KEYGUARD_REENABLE, token)); 5110 } 5111 5112 /** 5113 * @see android.app.KeyguardManager#exitKeyguardSecurely 5114 */ 5115 @Override 5116 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) { 5117 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5118 != PackageManager.PERMISSION_GRANTED) { 5119 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5120 } 5121 5122 if (callback == null) { 5123 throw new IllegalArgumentException("callback == null"); 5124 } 5125 5126 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() { 5127 @Override 5128 public void onKeyguardExitResult(boolean success) { 5129 try { 5130 callback.onKeyguardExitResult(success); 5131 } catch (RemoteException e) { 5132 // Client has died, we don't care. 5133 } 5134 } 5135 }); 5136 } 5137 5138 @Override 5139 public boolean inKeyguardRestrictedInputMode() { 5140 return mPolicy.inKeyguardRestrictedKeyInputMode(); 5141 } 5142 5143 @Override 5144 public boolean isKeyguardLocked() { 5145 return mPolicy.isKeyguardLocked(); 5146 } 5147 5148 @Override 5149 public boolean isKeyguardSecure() { 5150 return mPolicy.isKeyguardSecure(); 5151 } 5152 5153 @Override 5154 public void dismissKeyguard() { 5155 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5156 != PackageManager.PERMISSION_GRANTED) { 5157 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5158 } 5159 synchronized(mWindowMap) { 5160 mPolicy.dismissKeyguardLw(); 5161 } 5162 } 5163 5164 @Override 5165 public void keyguardGoingAway() { 5166 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5167 != PackageManager.PERMISSION_GRANTED) { 5168 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5169 } 5170 synchronized (mWindowMap) { 5171 mAnimator.mKeyguardGoingAway = true; 5172 requestTraversalLocked(); 5173 } 5174 } 5175 5176 @Override 5177 public void closeSystemDialogs(String reason) { 5178 synchronized(mWindowMap) { 5179 final int numDisplays = mDisplayContents.size(); 5180 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5181 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5182 final int numWindows = windows.size(); 5183 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5184 final WindowState w = windows.get(winNdx); 5185 if (w.mHasSurface) { 5186 try { 5187 w.mClient.closeSystemDialogs(reason); 5188 } catch (RemoteException e) { 5189 } 5190 } 5191 } 5192 } 5193 } 5194 } 5195 5196 static float fixScale(float scale) { 5197 if (scale < 0) scale = 0; 5198 else if (scale > 20) scale = 20; 5199 return Math.abs(scale); 5200 } 5201 5202 @Override 5203 public void setAnimationScale(int which, float scale) { 5204 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5205 "setAnimationScale()")) { 5206 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5207 } 5208 5209 scale = fixScale(scale); 5210 switch (which) { 5211 case 0: mWindowAnimationScaleSetting = scale; break; 5212 case 1: mTransitionAnimationScaleSetting = scale; break; 5213 case 2: mAnimatorDurationScaleSetting = scale; break; 5214 } 5215 5216 // Persist setting 5217 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5218 } 5219 5220 @Override 5221 public void setAnimationScales(float[] scales) { 5222 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5223 "setAnimationScale()")) { 5224 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5225 } 5226 5227 if (scales != null) { 5228 if (scales.length >= 1) { 5229 mWindowAnimationScaleSetting = fixScale(scales[0]); 5230 } 5231 if (scales.length >= 2) { 5232 mTransitionAnimationScaleSetting = fixScale(scales[1]); 5233 } 5234 if (scales.length >= 3) { 5235 mAnimatorDurationScaleSetting = fixScale(scales[2]); 5236 dispatchNewAnimatorScaleLocked(null); 5237 } 5238 } 5239 5240 // Persist setting 5241 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5242 } 5243 5244 private void setAnimatorDurationScale(float scale) { 5245 mAnimatorDurationScaleSetting = scale; 5246 ValueAnimator.setDurationScale(scale); 5247 } 5248 5249 public float getWindowAnimationScaleLocked() { 5250 return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting; 5251 } 5252 5253 public float getTransitionAnimationScaleLocked() { 5254 return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting; 5255 } 5256 5257 @Override 5258 public float getAnimationScale(int which) { 5259 switch (which) { 5260 case 0: return mWindowAnimationScaleSetting; 5261 case 1: return mTransitionAnimationScaleSetting; 5262 case 2: return mAnimatorDurationScaleSetting; 5263 } 5264 return 0; 5265 } 5266 5267 @Override 5268 public float[] getAnimationScales() { 5269 return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting, 5270 mAnimatorDurationScaleSetting }; 5271 } 5272 5273 @Override 5274 public float getCurrentAnimatorScale() { 5275 synchronized(mWindowMap) { 5276 return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting; 5277 } 5278 } 5279 5280 void dispatchNewAnimatorScaleLocked(Session session) { 5281 mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget(); 5282 } 5283 5284 @Override 5285 public void registerPointerEventListener(PointerEventListener listener) { 5286 mPointerEventDispatcher.registerInputEventListener(listener); 5287 } 5288 5289 @Override 5290 public void unregisterPointerEventListener(PointerEventListener listener) { 5291 mPointerEventDispatcher.unregisterInputEventListener(listener); 5292 } 5293 5294 // Called by window manager policy. Not exposed externally. 5295 @Override 5296 public int getLidState() { 5297 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 5298 InputManagerService.SW_LID); 5299 if (sw > 0) { 5300 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 5301 return LID_CLOSED; 5302 } else if (sw == 0) { 5303 // Switch state: AKEY_STATE_UP. 5304 return LID_OPEN; 5305 } else { 5306 // Switch state: AKEY_STATE_UNKNOWN. 5307 return LID_ABSENT; 5308 } 5309 } 5310 5311 // Called by window manager policy. Not exposed externally. 5312 @Override 5313 public void switchKeyboardLayout(int deviceId, int direction) { 5314 mInputManager.switchKeyboardLayout(deviceId, direction); 5315 } 5316 5317 // Called by window manager policy. Not exposed externally. 5318 @Override 5319 public void shutdown(boolean confirm) { 5320 ShutdownThread.shutdown(mContext, confirm); 5321 } 5322 5323 // Called by window manager policy. Not exposed externally. 5324 @Override 5325 public void rebootSafeMode(boolean confirm) { 5326 ShutdownThread.rebootSafeMode(mContext, confirm); 5327 } 5328 5329 public void setCurrentProfileIds(final int[] currentProfileIds) { 5330 synchronized (mWindowMap) { 5331 mCurrentProfileIds = currentProfileIds; 5332 } 5333 } 5334 5335 public void setCurrentUser(final int newUserId, final int[] currentProfileIds) { 5336 synchronized (mWindowMap) { 5337 mCurrentUserId = newUserId; 5338 mCurrentProfileIds = currentProfileIds; 5339 mAppTransition.setCurrentUser(newUserId); 5340 mPolicy.setCurrentUserLw(newUserId); 5341 5342 // Hide windows that should not be seen by the new user. 5343 final int numDisplays = mDisplayContents.size(); 5344 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5345 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 5346 displayContent.switchUserStacks(newUserId); 5347 rebuildAppWindowListLocked(displayContent); 5348 } 5349 performLayoutAndPlaceSurfacesLocked(); 5350 } 5351 } 5352 5353 /* Called by WindowState */ 5354 boolean isCurrentProfileLocked(int userId) { 5355 if (userId == mCurrentUserId) return true; 5356 for (int i = 0; i < mCurrentProfileIds.length; i++) { 5357 if (mCurrentProfileIds[i] == userId) return true; 5358 } 5359 return false; 5360 } 5361 5362 public void enableScreenAfterBoot() { 5363 synchronized(mWindowMap) { 5364 if (DEBUG_BOOT) { 5365 RuntimeException here = new RuntimeException("here"); 5366 here.fillInStackTrace(); 5367 Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled 5368 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5369 + " mShowingBootMessages=" + mShowingBootMessages 5370 + " mSystemBooted=" + mSystemBooted, here); 5371 } 5372 if (mSystemBooted) { 5373 return; 5374 } 5375 mSystemBooted = true; 5376 hideBootMessagesLocked(); 5377 // If the screen still doesn't come up after 30 seconds, give 5378 // up and turn it on. 5379 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000); 5380 } 5381 5382 mPolicy.systemBooted(); 5383 5384 performEnableScreen(); 5385 } 5386 5387 @Override 5388 public void enableScreenIfNeeded() { 5389 synchronized (mWindowMap) { 5390 enableScreenIfNeededLocked(); 5391 } 5392 } 5393 5394 void enableScreenIfNeededLocked() { 5395 if (DEBUG_BOOT) { 5396 RuntimeException here = new RuntimeException("here"); 5397 here.fillInStackTrace(); 5398 Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled 5399 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5400 + " mShowingBootMessages=" + mShowingBootMessages 5401 + " mSystemBooted=" + mSystemBooted, here); 5402 } 5403 if (mDisplayEnabled) { 5404 return; 5405 } 5406 if (!mSystemBooted && !mShowingBootMessages) { 5407 return; 5408 } 5409 mH.sendEmptyMessage(H.ENABLE_SCREEN); 5410 } 5411 5412 public void performBootTimeout() { 5413 synchronized(mWindowMap) { 5414 if (mDisplayEnabled) { 5415 return; 5416 } 5417 Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled"); 5418 mForceDisplayEnabled = true; 5419 } 5420 performEnableScreen(); 5421 } 5422 5423 public void performEnableScreen() { 5424 synchronized(mWindowMap) { 5425 if (DEBUG_BOOT) { 5426 RuntimeException here = new RuntimeException("here"); 5427 here.fillInStackTrace(); 5428 Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled 5429 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5430 + " mShowingBootMessages=" + mShowingBootMessages 5431 + " mSystemBooted=" + mSystemBooted 5432 + " mOnlyCore=" + mOnlyCore, here); 5433 } 5434 if (mDisplayEnabled) { 5435 return; 5436 } 5437 if (!mSystemBooted && !mShowingBootMessages) { 5438 return; 5439 } 5440 5441 if (!mForceDisplayEnabled) { 5442 // Don't enable the screen until all existing windows 5443 // have been drawn. 5444 boolean haveBootMsg = false; 5445 boolean haveApp = false; 5446 // if the wallpaper service is disabled on the device, we're never going to have 5447 // wallpaper, don't bother waiting for it 5448 boolean haveWallpaper = false; 5449 boolean wallpaperEnabled = mContext.getResources().getBoolean( 5450 com.android.internal.R.bool.config_enableWallpaperService) 5451 && !mOnlyCore; 5452 boolean haveKeyguard = true; 5453 // TODO(multidisplay): Expand to all displays? 5454 final WindowList windows = getDefaultWindowListLocked(); 5455 final int N = windows.size(); 5456 for (int i=0; i<N; i++) { 5457 WindowState w = windows.get(i); 5458 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 5459 return; 5460 } 5461 if (w.isDrawnLw()) { 5462 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { 5463 haveBootMsg = true; 5464 } else if (w.mAttrs.type == TYPE_APPLICATION) { 5465 haveApp = true; 5466 } else if (w.mAttrs.type == TYPE_WALLPAPER) { 5467 haveWallpaper = true; 5468 } else if (w.mAttrs.type == TYPE_STATUS_BAR) { 5469 haveKeyguard = mPolicy.isKeyguardDrawnLw(); 5470 } 5471 } 5472 } 5473 5474 if (DEBUG_SCREEN_ON || DEBUG_BOOT) { 5475 Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages 5476 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp 5477 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled 5478 + " haveKeyguard=" + haveKeyguard); 5479 } 5480 5481 // If we are turning on the screen to show the boot message, 5482 // don't do it until the boot message is actually displayed. 5483 if (!mSystemBooted && !haveBootMsg) { 5484 return; 5485 } 5486 5487 // If we are turning on the screen after the boot is completed 5488 // normally, don't do so until we have the application and 5489 // wallpaper. 5490 if (mSystemBooted && ((!haveApp && !haveKeyguard) || 5491 (wallpaperEnabled && !haveWallpaper))) { 5492 return; 5493 } 5494 } 5495 5496 mDisplayEnabled = true; 5497 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!"); 5498 if (false) { 5499 StringWriter sw = new StringWriter(); 5500 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 5501 this.dump(null, pw, null); 5502 pw.flush(); 5503 Slog.i(TAG, sw.toString()); 5504 } 5505 try { 5506 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); 5507 if (surfaceFlinger != null) { 5508 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); 5509 Parcel data = Parcel.obtain(); 5510 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 5511 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED 5512 data, null, 0); 5513 data.recycle(); 5514 } 5515 } catch (RemoteException ex) { 5516 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); 5517 } 5518 5519 // Enable input dispatch. 5520 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled); 5521 } 5522 5523 mPolicy.enableScreenAfterBoot(); 5524 5525 // Make sure the last requested orientation has been applied. 5526 updateRotationUnchecked(false, false); 5527 } 5528 5529 public void showBootMessage(final CharSequence msg, final boolean always) { 5530 boolean first = false; 5531 synchronized(mWindowMap) { 5532 if (DEBUG_BOOT) { 5533 RuntimeException here = new RuntimeException("here"); 5534 here.fillInStackTrace(); 5535 Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always 5536 + " mAllowBootMessages=" + mAllowBootMessages 5537 + " mShowingBootMessages=" + mShowingBootMessages 5538 + " mSystemBooted=" + mSystemBooted, here); 5539 } 5540 if (!mAllowBootMessages) { 5541 return; 5542 } 5543 if (!mShowingBootMessages) { 5544 if (!always) { 5545 return; 5546 } 5547 first = true; 5548 } 5549 if (mSystemBooted) { 5550 return; 5551 } 5552 mShowingBootMessages = true; 5553 mPolicy.showBootMessage(msg, always); 5554 } 5555 if (first) { 5556 performEnableScreen(); 5557 } 5558 } 5559 5560 public void hideBootMessagesLocked() { 5561 if (DEBUG_BOOT) { 5562 RuntimeException here = new RuntimeException("here"); 5563 here.fillInStackTrace(); 5564 Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled 5565 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5566 + " mShowingBootMessages=" + mShowingBootMessages 5567 + " mSystemBooted=" + mSystemBooted, here); 5568 } 5569 if (mShowingBootMessages) { 5570 mShowingBootMessages = false; 5571 mPolicy.hideBootMessages(); 5572 } 5573 } 5574 5575 @Override 5576 public void setInTouchMode(boolean mode) { 5577 synchronized(mWindowMap) { 5578 mInTouchMode = mode; 5579 } 5580 } 5581 5582 public void showCircularDisplayMaskIfNeeded() { 5583 // we're fullscreen and not hosted in an ActivityView 5584 if (mContext.getResources().getBoolean( 5585 com.android.internal.R.bool.config_windowIsRound)) { 5586 mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK)); 5587 } 5588 } 5589 5590 public void showCircularMask() { 5591 synchronized(mWindowMap) { 5592 5593 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5594 ">>> OPEN TRANSACTION showDisplayMask"); 5595 SurfaceControl.openTransaction(); 5596 try { 5597 // TODO(multi-display): support multiple displays 5598 if (mCircularDisplayMask == null) { 5599 mCircularDisplayMask = new CircularDisplayMask( 5600 getDefaultDisplayContentLocked().getDisplay(), 5601 mFxSession, 5602 mPolicy.windowTypeToLayerLw( 5603 WindowManager.LayoutParams.TYPE_POINTER) 5604 * TYPE_LAYER_MULTIPLIER + 10); 5605 } 5606 mCircularDisplayMask.setVisibility(true); 5607 } finally { 5608 SurfaceControl.closeTransaction(); 5609 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5610 "<<< CLOSE TRANSACTION showDisplayMask"); 5611 } 5612 } 5613 } 5614 5615 // TODO: more accounting of which pid(s) turned it on, keep count, 5616 // only allow disables from pids which have count on, etc. 5617 @Override 5618 public void showStrictModeViolation(boolean on) { 5619 int pid = Binder.getCallingPid(); 5620 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid)); 5621 } 5622 5623 private void showStrictModeViolation(int arg, int pid) { 5624 final boolean on = arg != 0; 5625 synchronized(mWindowMap) { 5626 // Ignoring requests to enable the red border from clients 5627 // which aren't on screen. (e.g. Broadcast Receivers in 5628 // the background..) 5629 if (on) { 5630 boolean isVisible = false; 5631 final int numDisplays = mDisplayContents.size(); 5632 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5633 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5634 final int numWindows = windows.size(); 5635 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5636 final WindowState ws = windows.get(winNdx); 5637 if (ws.mSession.mPid == pid && ws.isVisibleLw()) { 5638 isVisible = true; 5639 break; 5640 } 5641 } 5642 } 5643 if (!isVisible) { 5644 return; 5645 } 5646 } 5647 5648 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5649 ">>> OPEN TRANSACTION showStrictModeViolation"); 5650 SurfaceControl.openTransaction(); 5651 try { 5652 // TODO(multi-display): support multiple displays 5653 if (mStrictModeFlash == null) { 5654 mStrictModeFlash = new StrictModeFlash( 5655 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 5656 } 5657 mStrictModeFlash.setVisibility(on); 5658 } finally { 5659 SurfaceControl.closeTransaction(); 5660 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5661 "<<< CLOSE TRANSACTION showStrictModeViolation"); 5662 } 5663 } 5664 } 5665 5666 @Override 5667 public void setStrictModeVisualIndicatorPreference(String value) { 5668 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 5669 } 5670 5671 /** 5672 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 5673 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 5674 * of the target image. 5675 * 5676 * @param displayId the Display to take a screenshot of. 5677 * @param width the width of the target bitmap 5678 * @param height the height of the target bitmap 5679 * @param force565 if true the returned bitmap will be RGB_565, otherwise it 5680 * will be the same config as the surface 5681 */ 5682 @Override 5683 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, 5684 int height, boolean force565) { 5685 if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, 5686 "screenshotApplications()")) { 5687 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 5688 } 5689 5690 Bitmap rawss = null; 5691 5692 int maxLayer = 0; 5693 final Rect frame = new Rect(); 5694 5695 float scale = 0; 5696 int dw, dh; 5697 int rot = Surface.ROTATION_0; 5698 5699 boolean screenshotReady; 5700 int minLayer; 5701 if (appToken == null) { 5702 screenshotReady = true; 5703 minLayer = 0; 5704 } else { 5705 screenshotReady = false; 5706 minLayer = Integer.MAX_VALUE; 5707 } 5708 5709 int retryCount = 0; 5710 WindowState appWin = null; 5711 5712 do { 5713 if (retryCount++ > 0) { 5714 try { 5715 Thread.sleep(100); 5716 } catch (InterruptedException e) { 5717 } 5718 } 5719 synchronized(mWindowMap) { 5720 final DisplayContent displayContent = getDisplayContentLocked(displayId); 5721 if (displayContent == null) { 5722 return null; 5723 } 5724 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 5725 dw = displayInfo.logicalWidth; 5726 dh = displayInfo.logicalHeight; 5727 5728 int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) 5729 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 5730 aboveAppLayer += TYPE_LAYER_MULTIPLIER; 5731 5732 boolean isImeTarget = mInputMethodTarget != null 5733 && mInputMethodTarget.mAppToken != null 5734 && mInputMethodTarget.mAppToken.appToken != null 5735 && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken; 5736 5737 // Figure out the part of the screen that is actually the app. 5738 boolean including = false; 5739 appWin = null; 5740 final WindowList windows = displayContent.getWindowList(); 5741 final Rect stackBounds = new Rect(); 5742 for (int i = windows.size() - 1; i >= 0; i--) { 5743 WindowState ws = windows.get(i); 5744 if (!ws.mHasSurface) { 5745 continue; 5746 } 5747 if (ws.mLayer >= aboveAppLayer) { 5748 continue; 5749 } 5750 // When we will skip windows: when we are not including 5751 // ones behind a window we didn't skip, and we are actually 5752 // taking a screenshot of a specific app. 5753 if (!including && appToken != null) { 5754 // Also, we can possibly skip this window if it is not 5755 // an IME target or the application for the screenshot 5756 // is not the current IME target. 5757 if (!ws.mIsImWindow || !isImeTarget) { 5758 // And finally, this window is of no interest if it 5759 // is not associated with the screenshot app. 5760 if (ws.mAppToken == null || ws.mAppToken.token != appToken) { 5761 continue; 5762 } 5763 appWin = ws; 5764 ws.getStackBounds(stackBounds); 5765 } 5766 } 5767 5768 // We keep on including windows until we go past a full-screen 5769 // window. 5770 including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh); 5771 5772 final WindowStateAnimator winAnim = ws.mWinAnimator; 5773 if (maxLayer < winAnim.mSurfaceLayer) { 5774 maxLayer = winAnim.mSurfaceLayer; 5775 } 5776 if (minLayer > winAnim.mSurfaceLayer) { 5777 minLayer = winAnim.mSurfaceLayer; 5778 } 5779 5780 // Don't include wallpaper in bounds calculation 5781 if (!ws.mIsWallpaper) { 5782 final Rect wf = ws.mFrame; 5783 final Rect cr = ws.mContentInsets; 5784 int left = wf.left + cr.left; 5785 int top = wf.top + cr.top; 5786 int right = wf.right - cr.right; 5787 int bottom = wf.bottom - cr.bottom; 5788 frame.union(left, top, right, bottom); 5789 frame.intersect(stackBounds); 5790 } 5791 5792 if (ws.mAppToken != null && ws.mAppToken.token == appToken && 5793 ws.isDisplayedLw()) { 5794 screenshotReady = true; 5795 } 5796 } 5797 5798 if (appToken != null && appWin == null) { 5799 // Can't find a window to snapshot. 5800 if (DEBUG_SCREENSHOT) Slog.i(TAG, 5801 "Screenshot: Couldn't find a surface matching " + appToken); 5802 return null; 5803 } 5804 if (!screenshotReady) { 5805 // Delay and hope that window gets drawn. 5806 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken 5807 + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState); 5808 continue; 5809 } 5810 5811 // Constrain frame to the screen size. 5812 frame.intersect(0, 0, dw, dh); 5813 5814 if (frame.isEmpty() || maxLayer == 0) { 5815 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 5816 + ": returning null frame=" + frame.toShortString() + " maxLayer=" 5817 + maxLayer); 5818 return null; 5819 } 5820 5821 // The screenshot API does not apply the current screen rotation. 5822 rot = getDefaultDisplayContentLocked().getDisplay().getRotation(); 5823 int fw = frame.width(); 5824 int fh = frame.height(); 5825 5826 // Constrain thumbnail to smaller of screen width or height. Assumes aspect 5827 // of thumbnail is the same as the screen (in landscape) or square. 5828 scale = Math.max(width / (float) fw, height / (float) fh); 5829 /* 5830 float targetWidthScale = width / (float) fw; 5831 float targetHeightScale = height / (float) fh; 5832 if (fw <= fh) { 5833 scale = targetWidthScale; 5834 // If aspect of thumbnail is the same as the screen (in landscape), 5835 // select the slightly larger value so we fill the entire bitmap 5836 if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) { 5837 scale = targetHeightScale; 5838 } 5839 } else { 5840 scale = targetHeightScale; 5841 // If aspect of thumbnail is the same as the screen (in landscape), 5842 // select the slightly larger value so we fill the entire bitmap 5843 if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) { 5844 scale = targetWidthScale; 5845 } 5846 } 5847 */ 5848 5849 // The screen shot will contain the entire screen. 5850 dw = (int)(dw*scale); 5851 dh = (int)(dh*scale); 5852 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 5853 int tmp = dw; 5854 dw = dh; 5855 dh = tmp; 5856 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; 5857 } 5858 if (DEBUG_SCREENSHOT) { 5859 Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 5860 + maxLayer + " appToken=" + appToken); 5861 for (int i = 0; i < windows.size(); i++) { 5862 WindowState win = windows.get(i); 5863 Slog.i(TAG, win + ": " + win.mLayer 5864 + " animLayer=" + win.mWinAnimator.mAnimLayer 5865 + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer); 5866 } 5867 } 5868 // TODO: Replace 'false' in the following line with a variable that indicates 5869 // whether the screenshot should use the identity transformation matrix 5870 // (e.g., enable it when taking a screenshot for recents, since we might be in 5871 // the middle of the rotation animation, but don't want a rotated recent image). 5872 // TODO: Replace 'new Rect()' with the portion of the screen to capture for the 5873 // screenshot. 5874 rawss = SurfaceControl.screenshot(new Rect(), dw, dh, minLayer, maxLayer, false); 5875 } 5876 } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES); 5877 if (retryCount > MAX_SCREENSHOT_RETRIES) Slog.i(TAG, "Screenshot max retries " + 5878 retryCount + " of " + appToken + " appWin=" + (appWin == null ? 5879 "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState))); 5880 5881 if (rawss == null) { 5882 Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh 5883 + ") to layer " + maxLayer); 5884 return null; 5885 } 5886 5887 Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig()); 5888 bm.eraseColor(0xFF000000); 5889 frame.scale(scale); 5890 Matrix matrix = new Matrix(); 5891 ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix); 5892 // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left 5893 matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top)); 5894 Canvas canvas = new Canvas(bm); 5895 canvas.drawBitmap(rawss, matrix, null); 5896 canvas.setBitmap(null); 5897 5898 if (DEBUG_SCREENSHOT) { 5899 // TEST IF IT's ALL BLACK 5900 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 5901 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 5902 boolean allBlack = true; 5903 final int firstColor = buffer[0]; 5904 for (int i = 0; i < buffer.length; i++) { 5905 if (buffer[i] != firstColor) { 5906 allBlack = false; 5907 break; 5908 } 5909 } 5910 if (allBlack) { 5911 Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" + 5912 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 5913 (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") + 5914 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 5915 } 5916 } 5917 5918 rawss.recycle(); 5919 return bm; 5920 } 5921 5922 /** 5923 * Freeze rotation changes. (Enable "rotation lock".) 5924 * Persists across reboots. 5925 * @param rotation The desired rotation to freeze to, or -1 to use the 5926 * current rotation. 5927 */ 5928 @Override 5929 public void freezeRotation(int rotation) { 5930 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5931 "freezeRotation()")) { 5932 throw new SecurityException("Requires SET_ORIENTATION permission"); 5933 } 5934 if (rotation < -1 || rotation > Surface.ROTATION_270) { 5935 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 5936 + "rotation constant."); 5937 } 5938 5939 if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); 5940 5941 long origId = Binder.clearCallingIdentity(); 5942 try { 5943 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, 5944 rotation == -1 ? mRotation : rotation); 5945 } finally { 5946 Binder.restoreCallingIdentity(origId); 5947 } 5948 5949 updateRotationUnchecked(false, false); 5950 } 5951 5952 /** 5953 * Thaw rotation changes. (Disable "rotation lock".) 5954 * Persists across reboots. 5955 */ 5956 @Override 5957 public void thawRotation() { 5958 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5959 "thawRotation()")) { 5960 throw new SecurityException("Requires SET_ORIENTATION permission"); 5961 } 5962 5963 if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); 5964 5965 long origId = Binder.clearCallingIdentity(); 5966 try { 5967 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 5968 777); // rot not used 5969 } finally { 5970 Binder.restoreCallingIdentity(origId); 5971 } 5972 5973 updateRotationUnchecked(false, false); 5974 } 5975 5976 /** 5977 * Recalculate the current rotation. 5978 * 5979 * Called by the window manager policy whenever the state of the system changes 5980 * such that the current rotation might need to be updated, such as when the 5981 * device is docked or rotated into a new posture. 5982 */ 5983 @Override 5984 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 5985 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 5986 } 5987 5988 /** 5989 * Temporarily pauses rotation changes until resumed. 5990 * 5991 * This can be used to prevent rotation changes from occurring while the user is 5992 * performing certain operations, such as drag and drop. 5993 * 5994 * This call nests and must be matched by an equal number of calls to 5995 * {@link #resumeRotationLocked}. 5996 */ 5997 void pauseRotationLocked() { 5998 mDeferredRotationPauseCount += 1; 5999 } 6000 6001 /** 6002 * Resumes normal rotation changes after being paused. 6003 */ 6004 void resumeRotationLocked() { 6005 if (mDeferredRotationPauseCount > 0) { 6006 mDeferredRotationPauseCount -= 1; 6007 if (mDeferredRotationPauseCount == 0) { 6008 boolean changed = updateRotationUncheckedLocked(false); 6009 if (changed) { 6010 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6011 } 6012 } 6013 } 6014 } 6015 6016 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 6017 if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" 6018 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); 6019 6020 long origId = Binder.clearCallingIdentity(); 6021 boolean changed; 6022 synchronized(mWindowMap) { 6023 changed = updateRotationUncheckedLocked(false); 6024 if (!changed || forceRelayout) { 6025 getDefaultDisplayContentLocked().layoutNeeded = true; 6026 performLayoutAndPlaceSurfacesLocked(); 6027 } 6028 } 6029 6030 if (changed || alwaysSendConfiguration) { 6031 sendNewConfiguration(); 6032 } 6033 6034 Binder.restoreCallingIdentity(origId); 6035 } 6036 6037 // TODO(multidisplay): Rotate any display? 6038 /** 6039 * Updates the current rotation. 6040 * 6041 * Returns true if the rotation has been changed. In this case YOU 6042 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. 6043 */ 6044 public boolean updateRotationUncheckedLocked(boolean inTransaction) { 6045 if (mDeferredRotationPauseCount > 0) { 6046 // Rotation updates have been paused temporarily. Defer the update until 6047 // updates have been resumed. 6048 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused."); 6049 return false; 6050 } 6051 6052 ScreenRotationAnimation screenRotationAnimation = 6053 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6054 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 6055 // Rotation updates cannot be performed while the previous rotation change 6056 // animation is still in progress. Skip this update. We will try updating 6057 // again after the animation is finished and the display is unfrozen. 6058 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress."); 6059 return false; 6060 } 6061 6062 if (!mDisplayEnabled) { 6063 // No point choosing a rotation if the display is not enabled. 6064 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled."); 6065 return false; 6066 } 6067 6068 // TODO: Implement forced rotation changes. 6069 // Set mAltOrientation to indicate that the application is receiving 6070 // an orientation that has different metrics than it expected. 6071 // eg. Portrait instead of Landscape. 6072 6073 int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation); 6074 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 6075 mForcedAppOrientation, rotation); 6076 6077 if (DEBUG_ORIENTATION) { 6078 Slog.v(TAG, "Application requested orientation " 6079 + mForcedAppOrientation + ", got rotation " + rotation 6080 + " which has " + (altOrientation ? "incompatible" : "compatible") 6081 + " metrics"); 6082 } 6083 6084 if (mRotation == rotation && mAltOrientation == altOrientation) { 6085 // No change. 6086 return false; 6087 } 6088 6089 if (DEBUG_ORIENTATION) { 6090 Slog.v(TAG, 6091 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") 6092 + " from " + mRotation + (mAltOrientation ? " (alt)" : "") 6093 + ", forceApp=" + mForcedAppOrientation); 6094 } 6095 6096 mRotation = rotation; 6097 mAltOrientation = altOrientation; 6098 mPolicy.setRotationLw(mRotation); 6099 6100 mWindowsFreezingScreen = true; 6101 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 6102 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION); 6103 mWaitingForConfig = true; 6104 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6105 displayContent.layoutNeeded = true; 6106 final int[] anim = new int[2]; 6107 if (displayContent.isDimming()) { 6108 anim[0] = anim[1] = 0; 6109 } else { 6110 mPolicy.selectRotationAnimationLw(anim); 6111 } 6112 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]); 6113 // startFreezingDisplayLocked can reset the ScreenRotationAnimation. 6114 screenRotationAnimation = 6115 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6116 6117 // We need to update our screen size information to match the new 6118 // rotation. Note that this is redundant with the later call to 6119 // sendNewConfiguration() that must be called after this function 6120 // returns... however we need to do the screen size part of that 6121 // before then so we have the correct size to use when initializing 6122 // the rotation animation for the new rotation. 6123 computeScreenConfigurationLocked(null); 6124 6125 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6126 if (!inTransaction) { 6127 if (SHOW_TRANSACTIONS) { 6128 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked"); 6129 } 6130 SurfaceControl.openTransaction(); 6131 } 6132 try { 6133 // NOTE: We disable the rotation in the emulator because 6134 // it doesn't support hardware OpenGL emulation yet. 6135 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 6136 && screenRotationAnimation.hasScreenshot()) { 6137 if (screenRotationAnimation.setRotationInTransaction( 6138 rotation, mFxSession, 6139 MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(), 6140 displayInfo.logicalWidth, displayInfo.logicalHeight)) { 6141 scheduleAnimationLocked(); 6142 } 6143 } 6144 6145 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 6146 } finally { 6147 if (!inTransaction) { 6148 SurfaceControl.closeTransaction(); 6149 if (SHOW_LIGHT_TRANSACTIONS) { 6150 Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked"); 6151 } 6152 } 6153 } 6154 6155 final WindowList windows = displayContent.getWindowList(); 6156 for (int i = windows.size() - 1; i >= 0; i--) { 6157 WindowState w = windows.get(i); 6158 if (w.mHasSurface) { 6159 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w); 6160 w.mOrientationChanging = true; 6161 mInnerFields.mOrientationChangeComplete = false; 6162 } 6163 w.mLastFreezeDuration = 0; 6164 } 6165 6166 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 6167 try { 6168 mRotationWatchers.get(i).watcher.onRotationChanged(rotation); 6169 } catch (RemoteException e) { 6170 } 6171 } 6172 6173 //TODO (multidisplay): Magnification is supported only for the default display. 6174 if (mAccessibilityController != null 6175 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 6176 mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation); 6177 } 6178 6179 return true; 6180 } 6181 6182 @Override 6183 public int getRotation() { 6184 return mRotation; 6185 } 6186 6187 @Override 6188 public boolean isRotationFrozen() { 6189 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED; 6190 } 6191 6192 @Override 6193 public int watchRotation(IRotationWatcher watcher) { 6194 final IBinder watcherBinder = watcher.asBinder(); 6195 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 6196 @Override 6197 public void binderDied() { 6198 synchronized (mWindowMap) { 6199 for (int i=0; i<mRotationWatchers.size(); i++) { 6200 if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) { 6201 RotationWatcher removed = mRotationWatchers.remove(i); 6202 IBinder binder = removed.watcher.asBinder(); 6203 if (binder != null) { 6204 binder.unlinkToDeath(this, 0); 6205 } 6206 i--; 6207 } 6208 } 6209 } 6210 } 6211 }; 6212 6213 synchronized (mWindowMap) { 6214 try { 6215 watcher.asBinder().linkToDeath(dr, 0); 6216 mRotationWatchers.add(new RotationWatcher(watcher, dr)); 6217 } catch (RemoteException e) { 6218 // Client died, no cleanup needed. 6219 } 6220 6221 return mRotation; 6222 } 6223 } 6224 6225 @Override 6226 public void removeRotationWatcher(IRotationWatcher watcher) { 6227 final IBinder watcherBinder = watcher.asBinder(); 6228 synchronized (mWindowMap) { 6229 for (int i=0; i<mRotationWatchers.size(); i++) { 6230 RotationWatcher rotationWatcher = mRotationWatchers.get(i); 6231 if (watcherBinder == rotationWatcher.watcher.asBinder()) { 6232 RotationWatcher removed = mRotationWatchers.remove(i); 6233 IBinder binder = removed.watcher.asBinder(); 6234 if (binder != null) { 6235 binder.unlinkToDeath(removed.deathRecipient, 0); 6236 } 6237 i--; 6238 } 6239 } 6240 } 6241 } 6242 6243 /** 6244 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 6245 * theme attribute) on devices that feature a physical options menu key attempt to position 6246 * their menu panel window along the edge of the screen nearest the physical menu key. 6247 * This lowers the travel distance between invoking the menu panel and selecting 6248 * a menu option. 6249 * 6250 * This method helps control where that menu is placed. Its current implementation makes 6251 * assumptions about the menu key and its relationship to the screen based on whether 6252 * the device's natural orientation is portrait (width < height) or landscape. 6253 * 6254 * The menu key is assumed to be located along the bottom edge of natural-portrait 6255 * devices and along the right edge of natural-landscape devices. If these assumptions 6256 * do not hold for the target device, this method should be changed to reflect that. 6257 * 6258 * @return A {@link Gravity} value for placing the options menu window 6259 */ 6260 @Override 6261 public int getPreferredOptionsPanelGravity() { 6262 synchronized (mWindowMap) { 6263 final int rotation = getRotation(); 6264 6265 // TODO(multidisplay): Assume that such devices physical keys are on the main screen. 6266 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6267 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) { 6268 // On devices with a natural orientation of portrait 6269 switch (rotation) { 6270 default: 6271 case Surface.ROTATION_0: 6272 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6273 case Surface.ROTATION_90: 6274 return Gravity.RIGHT | Gravity.BOTTOM; 6275 case Surface.ROTATION_180: 6276 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6277 case Surface.ROTATION_270: 6278 return Gravity.START | Gravity.BOTTOM; 6279 } 6280 } 6281 6282 // On devices with a natural orientation of landscape 6283 switch (rotation) { 6284 default: 6285 case Surface.ROTATION_0: 6286 return Gravity.RIGHT | Gravity.BOTTOM; 6287 case Surface.ROTATION_90: 6288 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6289 case Surface.ROTATION_180: 6290 return Gravity.START | Gravity.BOTTOM; 6291 case Surface.ROTATION_270: 6292 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6293 } 6294 } 6295 } 6296 6297 /** 6298 * Starts the view server on the specified port. 6299 * 6300 * @param port The port to listener to. 6301 * 6302 * @return True if the server was successfully started, false otherwise. 6303 * 6304 * @see com.android.server.wm.ViewServer 6305 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 6306 */ 6307 @Override 6308 public boolean startViewServer(int port) { 6309 if (isSystemSecure()) { 6310 return false; 6311 } 6312 6313 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 6314 return false; 6315 } 6316 6317 if (port < 1024) { 6318 return false; 6319 } 6320 6321 if (mViewServer != null) { 6322 if (!mViewServer.isRunning()) { 6323 try { 6324 return mViewServer.start(); 6325 } catch (IOException e) { 6326 Slog.w(TAG, "View server did not start"); 6327 } 6328 } 6329 return false; 6330 } 6331 6332 try { 6333 mViewServer = new ViewServer(this, port); 6334 return mViewServer.start(); 6335 } catch (IOException e) { 6336 Slog.w(TAG, "View server did not start"); 6337 } 6338 return false; 6339 } 6340 6341 private boolean isSystemSecure() { 6342 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 6343 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 6344 } 6345 6346 /** 6347 * Stops the view server if it exists. 6348 * 6349 * @return True if the server stopped, false if it wasn't started or 6350 * couldn't be stopped. 6351 * 6352 * @see com.android.server.wm.ViewServer 6353 */ 6354 @Override 6355 public boolean stopViewServer() { 6356 if (isSystemSecure()) { 6357 return false; 6358 } 6359 6360 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 6361 return false; 6362 } 6363 6364 if (mViewServer != null) { 6365 return mViewServer.stop(); 6366 } 6367 return false; 6368 } 6369 6370 /** 6371 * Indicates whether the view server is running. 6372 * 6373 * @return True if the server is running, false otherwise. 6374 * 6375 * @see com.android.server.wm.ViewServer 6376 */ 6377 @Override 6378 public boolean isViewServerRunning() { 6379 if (isSystemSecure()) { 6380 return false; 6381 } 6382 6383 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 6384 return false; 6385 } 6386 6387 return mViewServer != null && mViewServer.isRunning(); 6388 } 6389 6390 /** 6391 * Lists all availble windows in the system. The listing is written in the 6392 * specified Socket's output stream with the following syntax: 6393 * windowHashCodeInHexadecimal windowName 6394 * Each line of the ouput represents a different window. 6395 * 6396 * @param client The remote client to send the listing to. 6397 * @return False if an error occured, true otherwise. 6398 */ 6399 boolean viewServerListWindows(Socket client) { 6400 if (isSystemSecure()) { 6401 return false; 6402 } 6403 6404 boolean result = true; 6405 6406 WindowList windows = new WindowList(); 6407 synchronized (mWindowMap) { 6408 //noinspection unchecked 6409 final int numDisplays = mDisplayContents.size(); 6410 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6411 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 6412 windows.addAll(displayContent.getWindowList()); 6413 } 6414 } 6415 6416 BufferedWriter out = null; 6417 6418 // Any uncaught exception will crash the system process 6419 try { 6420 OutputStream clientStream = client.getOutputStream(); 6421 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6422 6423 final int count = windows.size(); 6424 for (int i = 0; i < count; i++) { 6425 final WindowState w = windows.get(i); 6426 out.write(Integer.toHexString(System.identityHashCode(w))); 6427 out.write(' '); 6428 out.append(w.mAttrs.getTitle()); 6429 out.write('\n'); 6430 } 6431 6432 out.write("DONE.\n"); 6433 out.flush(); 6434 } catch (Exception e) { 6435 result = false; 6436 } finally { 6437 if (out != null) { 6438 try { 6439 out.close(); 6440 } catch (IOException e) { 6441 result = false; 6442 } 6443 } 6444 } 6445 6446 return result; 6447 } 6448 6449 // TODO(multidisplay): Extend to multiple displays. 6450 /** 6451 * Returns the focused window in the following format: 6452 * windowHashCodeInHexadecimal windowName 6453 * 6454 * @param client The remote client to send the listing to. 6455 * @return False if an error occurred, true otherwise. 6456 */ 6457 boolean viewServerGetFocusedWindow(Socket client) { 6458 if (isSystemSecure()) { 6459 return false; 6460 } 6461 6462 boolean result = true; 6463 6464 WindowState focusedWindow = getFocusedWindow(); 6465 6466 BufferedWriter out = null; 6467 6468 // Any uncaught exception will crash the system process 6469 try { 6470 OutputStream clientStream = client.getOutputStream(); 6471 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6472 6473 if(focusedWindow != null) { 6474 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 6475 out.write(' '); 6476 out.append(focusedWindow.mAttrs.getTitle()); 6477 } 6478 out.write('\n'); 6479 out.flush(); 6480 } catch (Exception e) { 6481 result = false; 6482 } finally { 6483 if (out != null) { 6484 try { 6485 out.close(); 6486 } catch (IOException e) { 6487 result = false; 6488 } 6489 } 6490 } 6491 6492 return result; 6493 } 6494 6495 /** 6496 * Sends a command to a target window. The result of the command, if any, will be 6497 * written in the output stream of the specified socket. 6498 * 6499 * The parameters must follow this syntax: 6500 * windowHashcode extra 6501 * 6502 * Where XX is the length in characeters of the windowTitle. 6503 * 6504 * The first parameter is the target window. The window with the specified hashcode 6505 * will be the target. If no target can be found, nothing happens. The extra parameters 6506 * will be delivered to the target window and as parameters to the command itself. 6507 * 6508 * @param client The remote client to sent the result, if any, to. 6509 * @param command The command to execute. 6510 * @param parameters The command parameters. 6511 * 6512 * @return True if the command was successfully delivered, false otherwise. This does 6513 * not indicate whether the command itself was successful. 6514 */ 6515 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 6516 if (isSystemSecure()) { 6517 return false; 6518 } 6519 6520 boolean success = true; 6521 Parcel data = null; 6522 Parcel reply = null; 6523 6524 BufferedWriter out = null; 6525 6526 // Any uncaught exception will crash the system process 6527 try { 6528 // Find the hashcode of the window 6529 int index = parameters.indexOf(' '); 6530 if (index == -1) { 6531 index = parameters.length(); 6532 } 6533 final String code = parameters.substring(0, index); 6534 int hashCode = (int) Long.parseLong(code, 16); 6535 6536 // Extract the command's parameter after the window description 6537 if (index < parameters.length()) { 6538 parameters = parameters.substring(index + 1); 6539 } else { 6540 parameters = ""; 6541 } 6542 6543 final WindowState window = findWindow(hashCode); 6544 if (window == null) { 6545 return false; 6546 } 6547 6548 data = Parcel.obtain(); 6549 data.writeInterfaceToken("android.view.IWindow"); 6550 data.writeString(command); 6551 data.writeString(parameters); 6552 data.writeInt(1); 6553 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 6554 6555 reply = Parcel.obtain(); 6556 6557 final IBinder binder = window.mClient.asBinder(); 6558 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 6559 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 6560 6561 reply.readException(); 6562 6563 if (!client.isOutputShutdown()) { 6564 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 6565 out.write("DONE\n"); 6566 out.flush(); 6567 } 6568 6569 } catch (Exception e) { 6570 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); 6571 success = false; 6572 } finally { 6573 if (data != null) { 6574 data.recycle(); 6575 } 6576 if (reply != null) { 6577 reply.recycle(); 6578 } 6579 if (out != null) { 6580 try { 6581 out.close(); 6582 } catch (IOException e) { 6583 6584 } 6585 } 6586 } 6587 6588 return success; 6589 } 6590 6591 public void addWindowChangeListener(WindowChangeListener listener) { 6592 synchronized(mWindowMap) { 6593 mWindowChangeListeners.add(listener); 6594 } 6595 } 6596 6597 public void removeWindowChangeListener(WindowChangeListener listener) { 6598 synchronized(mWindowMap) { 6599 mWindowChangeListeners.remove(listener); 6600 } 6601 } 6602 6603 private void notifyWindowsChanged() { 6604 WindowChangeListener[] windowChangeListeners; 6605 synchronized(mWindowMap) { 6606 if(mWindowChangeListeners.isEmpty()) { 6607 return; 6608 } 6609 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6610 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6611 } 6612 int N = windowChangeListeners.length; 6613 for(int i = 0; i < N; i++) { 6614 windowChangeListeners[i].windowsChanged(); 6615 } 6616 } 6617 6618 private void notifyFocusChanged() { 6619 WindowChangeListener[] windowChangeListeners; 6620 synchronized(mWindowMap) { 6621 if(mWindowChangeListeners.isEmpty()) { 6622 return; 6623 } 6624 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6625 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6626 } 6627 int N = windowChangeListeners.length; 6628 for(int i = 0; i < N; i++) { 6629 windowChangeListeners[i].focusChanged(); 6630 } 6631 } 6632 6633 private WindowState findWindow(int hashCode) { 6634 if (hashCode == -1) { 6635 // TODO(multidisplay): Extend to multiple displays. 6636 return getFocusedWindow(); 6637 } 6638 6639 synchronized (mWindowMap) { 6640 final int numDisplays = mDisplayContents.size(); 6641 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6642 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 6643 final int numWindows = windows.size(); 6644 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 6645 final WindowState w = windows.get(winNdx); 6646 if (System.identityHashCode(w) == hashCode) { 6647 return w; 6648 } 6649 } 6650 } 6651 } 6652 6653 return null; 6654 } 6655 6656 /* 6657 * Instruct the Activity Manager to fetch the current configuration and broadcast 6658 * that to config-changed listeners if appropriate. 6659 */ 6660 void sendNewConfiguration() { 6661 try { 6662 mActivityManager.updateConfiguration(null); 6663 } catch (RemoteException e) { 6664 } 6665 } 6666 6667 public Configuration computeNewConfiguration() { 6668 synchronized (mWindowMap) { 6669 Configuration config = computeNewConfigurationLocked(); 6670 if (config == null && mWaitingForConfig) { 6671 // Nothing changed but we are waiting for something... stop that! 6672 mWaitingForConfig = false; 6673 mLastFinishedFreezeSource = "new-config"; 6674 performLayoutAndPlaceSurfacesLocked(); 6675 } 6676 return config; 6677 } 6678 } 6679 6680 Configuration computeNewConfigurationLocked() { 6681 Configuration config = new Configuration(); 6682 config.fontScale = 0; 6683 if (!computeScreenConfigurationLocked(config)) { 6684 return null; 6685 } 6686 return config; 6687 } 6688 6689 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) { 6690 // TODO: Multidisplay: for now only use with default display. 6691 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation); 6692 if (width < displayInfo.smallestNominalAppWidth) { 6693 displayInfo.smallestNominalAppWidth = width; 6694 } 6695 if (width > displayInfo.largestNominalAppWidth) { 6696 displayInfo.largestNominalAppWidth = width; 6697 } 6698 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation); 6699 if (height < displayInfo.smallestNominalAppHeight) { 6700 displayInfo.smallestNominalAppHeight = height; 6701 } 6702 if (height > displayInfo.largestNominalAppHeight) { 6703 displayInfo.largestNominalAppHeight = height; 6704 } 6705 } 6706 6707 private int reduceConfigLayout(int curLayout, int rotation, float density, 6708 int dw, int dh) { 6709 // TODO: Multidisplay: for now only use with default display. 6710 // Get the app screen size at this rotation. 6711 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6712 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6713 6714 // Compute the screen layout size class for this rotation. 6715 int longSize = w; 6716 int shortSize = h; 6717 if (longSize < shortSize) { 6718 int tmp = longSize; 6719 longSize = shortSize; 6720 shortSize = tmp; 6721 } 6722 longSize = (int)(longSize/density); 6723 shortSize = (int)(shortSize/density); 6724 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 6725 } 6726 6727 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 6728 int dw, int dh, float density, Configuration outConfig) { 6729 // TODO: Multidisplay: for now only use with default display. 6730 6731 // We need to determine the smallest width that will occur under normal 6732 // operation. To this, start with the base screen size and compute the 6733 // width under the different possible rotations. We need to un-rotate 6734 // the current screen dimensions before doing this. 6735 int unrotDw, unrotDh; 6736 if (rotated) { 6737 unrotDw = dh; 6738 unrotDh = dw; 6739 } else { 6740 unrotDw = dw; 6741 unrotDh = dh; 6742 } 6743 displayInfo.smallestNominalAppWidth = 1<<30; 6744 displayInfo.smallestNominalAppHeight = 1<<30; 6745 displayInfo.largestNominalAppWidth = 0; 6746 displayInfo.largestNominalAppHeight = 0; 6747 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh); 6748 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw); 6749 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh); 6750 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw); 6751 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 6752 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh); 6753 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw); 6754 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); 6755 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); 6756 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 6757 outConfig.screenLayout = sl; 6758 } 6759 6760 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, 6761 int dw, int dh) { 6762 // TODO: Multidisplay: for now only use with default display. 6763 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6764 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6765 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 6766 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 6767 if (curSize == 0 || size < curSize) { 6768 curSize = size; 6769 } 6770 return curSize; 6771 } 6772 6773 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) { 6774 // TODO: Multidisplay: for now only use with default display. 6775 mTmpDisplayMetrics.setTo(dm); 6776 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 6777 final int unrotDw, unrotDh; 6778 if (rotated) { 6779 unrotDw = dh; 6780 unrotDh = dw; 6781 } else { 6782 unrotDw = dw; 6783 unrotDh = dh; 6784 } 6785 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh); 6786 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw); 6787 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh); 6788 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw); 6789 return sw; 6790 } 6791 6792 boolean computeScreenConfigurationLocked(Configuration config) { 6793 if (!mDisplayReady) { 6794 return false; 6795 } 6796 6797 // TODO(multidisplay): For now, apply Configuration to main screen only. 6798 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6799 6800 // Use the effective "visual" dimensions based on current rotation 6801 final boolean rotated = (mRotation == Surface.ROTATION_90 6802 || mRotation == Surface.ROTATION_270); 6803 final int realdw = rotated ? 6804 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; 6805 final int realdh = rotated ? 6806 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; 6807 int dw = realdw; 6808 int dh = realdh; 6809 6810 if (mAltOrientation) { 6811 if (realdw > realdh) { 6812 // Turn landscape into portrait. 6813 int maxw = (int)(realdh/1.3f); 6814 if (maxw < realdw) { 6815 dw = maxw; 6816 } 6817 } else { 6818 // Turn portrait into landscape. 6819 int maxh = (int)(realdw/1.3f); 6820 if (maxh < realdh) { 6821 dh = maxh; 6822 } 6823 } 6824 } 6825 6826 if (config != null) { 6827 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : 6828 Configuration.ORIENTATION_LANDSCAPE; 6829 } 6830 6831 // Update application display metrics. 6832 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); 6833 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); 6834 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6835 synchronized(displayContent.mDisplaySizeLock) { 6836 displayInfo.rotation = mRotation; 6837 displayInfo.logicalWidth = dw; 6838 displayInfo.logicalHeight = dh; 6839 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; 6840 displayInfo.appWidth = appWidth; 6841 displayInfo.appHeight = appHeight; 6842 displayInfo.getLogicalMetrics(mRealDisplayMetrics, 6843 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 6844 displayInfo.getAppMetrics(mDisplayMetrics); 6845 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 6846 displayContent.getDisplayId(), displayInfo); 6847 } 6848 if (false) { 6849 Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); 6850 } 6851 6852 final DisplayMetrics dm = mDisplayMetrics; 6853 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, 6854 mCompatDisplayMetrics); 6855 6856 if (config != null) { 6857 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) 6858 / dm.density); 6859 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) 6860 / dm.density); 6861 computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config); 6862 6863 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 6864 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 6865 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); 6866 config.densityDpi = displayContent.mBaseDisplayDensity; 6867 6868 // Update the configuration based on available input devices, lid switch, 6869 // and platform configuration. 6870 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6871 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6872 config.navigation = Configuration.NAVIGATION_NONAV; 6873 6874 int keyboardPresence = 0; 6875 int navigationPresence = 0; 6876 final InputDevice[] devices = mInputManager.getInputDevices(); 6877 final int len = devices.length; 6878 for (int i = 0; i < len; i++) { 6879 InputDevice device = devices[i]; 6880 if (!device.isVirtual()) { 6881 final int sources = device.getSources(); 6882 final int presenceFlag = device.isExternal() ? 6883 WindowManagerPolicy.PRESENCE_EXTERNAL : 6884 WindowManagerPolicy.PRESENCE_INTERNAL; 6885 6886 if (mIsTouchDevice) { 6887 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 6888 InputDevice.SOURCE_TOUCHSCREEN) { 6889 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 6890 } 6891 } else { 6892 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6893 } 6894 6895 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 6896 config.navigation = Configuration.NAVIGATION_TRACKBALL; 6897 navigationPresence |= presenceFlag; 6898 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 6899 && config.navigation == Configuration.NAVIGATION_NONAV) { 6900 config.navigation = Configuration.NAVIGATION_DPAD; 6901 navigationPresence |= presenceFlag; 6902 } 6903 6904 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 6905 config.keyboard = Configuration.KEYBOARD_QWERTY; 6906 keyboardPresence |= presenceFlag; 6907 } 6908 } 6909 } 6910 6911 // Determine whether a hard keyboard is available and enabled. 6912 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 6913 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 6914 mHardKeyboardAvailable = hardKeyboardAvailable; 6915 mHardKeyboardEnabled = hardKeyboardAvailable; 6916 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6917 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6918 } 6919 if (!mHardKeyboardEnabled) { 6920 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6921 } 6922 6923 // Let the policy update hidden states. 6924 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 6925 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 6926 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 6927 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 6928 } 6929 6930 return true; 6931 } 6932 6933 public boolean isHardKeyboardAvailable() { 6934 synchronized (mWindowMap) { 6935 return mHardKeyboardAvailable; 6936 } 6937 } 6938 6939 public boolean isHardKeyboardEnabled() { 6940 synchronized (mWindowMap) { 6941 return mHardKeyboardEnabled; 6942 } 6943 } 6944 6945 public void setHardKeyboardEnabled(boolean enabled) { 6946 synchronized (mWindowMap) { 6947 if (mHardKeyboardEnabled != enabled) { 6948 mHardKeyboardEnabled = enabled; 6949 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6950 } 6951 } 6952 } 6953 6954 public void setOnHardKeyboardStatusChangeListener( 6955 OnHardKeyboardStatusChangeListener listener) { 6956 synchronized (mWindowMap) { 6957 mHardKeyboardStatusChangeListener = listener; 6958 } 6959 } 6960 6961 void notifyHardKeyboardStatusChange() { 6962 final boolean available, enabled; 6963 final OnHardKeyboardStatusChangeListener listener; 6964 synchronized (mWindowMap) { 6965 listener = mHardKeyboardStatusChangeListener; 6966 available = mHardKeyboardAvailable; 6967 enabled = mHardKeyboardEnabled; 6968 } 6969 if (listener != null) { 6970 listener.onHardKeyboardStatusChange(available, enabled); 6971 } 6972 } 6973 6974 // ------------------------------------------------------------- 6975 // Drag and drop 6976 // ------------------------------------------------------------- 6977 6978 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 6979 int flags, int width, int height, Surface outSurface) { 6980 if (DEBUG_DRAG) { 6981 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 6982 + " flags=" + Integer.toHexString(flags) + " win=" + window 6983 + " asbinder=" + window.asBinder()); 6984 } 6985 6986 final int callerPid = Binder.getCallingPid(); 6987 final long origId = Binder.clearCallingIdentity(); 6988 IBinder token = null; 6989 6990 try { 6991 synchronized (mWindowMap) { 6992 try { 6993 if (mDragState == null) { 6994 // TODO(multi-display): support other displays 6995 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6996 final Display display = displayContent.getDisplay(); 6997 SurfaceControl surface = new SurfaceControl(session, "drag surface", 6998 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 6999 surface.setLayerStack(display.getLayerStack()); 7000 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 7001 + surface + ": CREATE"); 7002 outSurface.copyFrom(surface); 7003 final IBinder winBinder = window.asBinder(); 7004 token = new Binder(); 7005 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 7006 token = mDragState.mToken = new Binder(); 7007 7008 // 5 second timeout for this window to actually begin the drag 7009 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 7010 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 7011 mH.sendMessageDelayed(msg, 5000); 7012 } else { 7013 Slog.w(TAG, "Drag already in progress"); 7014 } 7015 } catch (OutOfResourcesException e) { 7016 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 7017 if (mDragState != null) { 7018 mDragState.reset(); 7019 mDragState = null; 7020 } 7021 } 7022 } 7023 } finally { 7024 Binder.restoreCallingIdentity(origId); 7025 } 7026 7027 return token; 7028 } 7029 7030 // ------------------------------------------------------------- 7031 // Input Events and Focus Management 7032 // ------------------------------------------------------------- 7033 7034 final InputMonitor mInputMonitor = new InputMonitor(this); 7035 private boolean mEventDispatchingEnabled; 7036 7037 @Override 7038 public void pauseKeyDispatching(IBinder _token) { 7039 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7040 "pauseKeyDispatching()")) { 7041 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7042 } 7043 7044 synchronized (mWindowMap) { 7045 WindowToken token = mTokenMap.get(_token); 7046 if (token != null) { 7047 mInputMonitor.pauseDispatchingLw(token); 7048 } 7049 } 7050 } 7051 7052 @Override 7053 public void resumeKeyDispatching(IBinder _token) { 7054 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7055 "resumeKeyDispatching()")) { 7056 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7057 } 7058 7059 synchronized (mWindowMap) { 7060 WindowToken token = mTokenMap.get(_token); 7061 if (token != null) { 7062 mInputMonitor.resumeDispatchingLw(token); 7063 } 7064 } 7065 } 7066 7067 @Override 7068 public void setEventDispatching(boolean enabled) { 7069 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7070 "setEventDispatching()")) { 7071 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7072 } 7073 7074 synchronized (mWindowMap) { 7075 mEventDispatchingEnabled = enabled; 7076 if (mDisplayEnabled) { 7077 mInputMonitor.setEventDispatchingLw(enabled); 7078 } 7079 } 7080 } 7081 7082 private WindowState getFocusedWindow() { 7083 synchronized (mWindowMap) { 7084 return getFocusedWindowLocked(); 7085 } 7086 } 7087 7088 private WindowState getFocusedWindowLocked() { 7089 return mCurrentFocus; 7090 } 7091 7092 public boolean detectSafeMode() { 7093 if (!mInputMonitor.waitForInputDevicesReady( 7094 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 7095 Slog.w(TAG, "Devices still not ready after waiting " 7096 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 7097 + " milliseconds before attempting to detect safe mode."); 7098 } 7099 7100 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7101 KeyEvent.KEYCODE_MENU); 7102 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 7103 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 7104 KeyEvent.KEYCODE_DPAD_CENTER); 7105 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 7106 InputManagerService.BTN_MOUSE); 7107 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7108 KeyEvent.KEYCODE_VOLUME_DOWN); 7109 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 7110 || volumeDownState > 0; 7111 try { 7112 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 7113 mSafeMode = true; 7114 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 7115 } 7116 } catch (IllegalArgumentException e) { 7117 } 7118 if (mSafeMode) { 7119 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 7120 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 7121 } else { 7122 Log.i(TAG, "SAFE MODE not enabled"); 7123 } 7124 mPolicy.setSafeMode(mSafeMode); 7125 return mSafeMode; 7126 } 7127 7128 public void displayReady() { 7129 displayReady(Display.DEFAULT_DISPLAY); 7130 7131 synchronized(mWindowMap) { 7132 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7133 readForcedDisplaySizeAndDensityLocked(displayContent); 7134 mDisplayReady = true; 7135 } 7136 7137 try { 7138 mActivityManager.updateConfiguration(null); 7139 } catch (RemoteException e) { 7140 } 7141 7142 synchronized(mWindowMap) { 7143 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 7144 PackageManager.FEATURE_TOUCHSCREEN); 7145 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 7146 } 7147 7148 try { 7149 mActivityManager.updateConfiguration(null); 7150 } catch (RemoteException e) { 7151 } 7152 } 7153 7154 private void displayReady(int displayId) { 7155 synchronized(mWindowMap) { 7156 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7157 if (displayContent != null) { 7158 mAnimator.addDisplayLocked(displayId); 7159 synchronized(displayContent.mDisplaySizeLock) { 7160 // Bootstrap the default logical display from the display manager. 7161 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7162 DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId); 7163 if (newDisplayInfo != null) { 7164 displayInfo.copyFrom(newDisplayInfo); 7165 } 7166 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; 7167 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; 7168 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; 7169 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; 7170 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; 7171 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; 7172 displayContent.mBaseDisplayRect.set(0, 0, 7173 displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight); 7174 } 7175 } 7176 } 7177 } 7178 7179 public void systemReady() { 7180 mPolicy.systemReady(); 7181 } 7182 7183 // ------------------------------------------------------------- 7184 // Async Handler 7185 // ------------------------------------------------------------- 7186 7187 final class H extends Handler { 7188 public static final int REPORT_FOCUS_CHANGE = 2; 7189 public static final int REPORT_LOSING_FOCUS = 3; 7190 public static final int DO_TRAVERSAL = 4; 7191 public static final int ADD_STARTING = 5; 7192 public static final int REMOVE_STARTING = 6; 7193 public static final int FINISHED_STARTING = 7; 7194 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 7195 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 7196 public static final int WINDOW_FREEZE_TIMEOUT = 11; 7197 7198 public static final int APP_TRANSITION_TIMEOUT = 13; 7199 public static final int PERSIST_ANIMATION_SCALE = 14; 7200 public static final int FORCE_GC = 15; 7201 public static final int ENABLE_SCREEN = 16; 7202 public static final int APP_FREEZE_TIMEOUT = 17; 7203 public static final int SEND_NEW_CONFIGURATION = 18; 7204 public static final int REPORT_WINDOWS_CHANGE = 19; 7205 public static final int DRAG_START_TIMEOUT = 20; 7206 public static final int DRAG_END_TIMEOUT = 21; 7207 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 7208 public static final int BOOT_TIMEOUT = 23; 7209 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 7210 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 7211 public static final int DO_ANIMATION_CALLBACK = 26; 7212 7213 public static final int DO_DISPLAY_ADDED = 27; 7214 public static final int DO_DISPLAY_REMOVED = 28; 7215 public static final int DO_DISPLAY_CHANGED = 29; 7216 7217 public static final int CLIENT_FREEZE_TIMEOUT = 30; 7218 public static final int TAP_OUTSIDE_STACK = 31; 7219 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 7220 7221 public static final int SHOW_DISPLAY_MASK = 33; 7222 public static final int ALL_WINDOWS_DRAWN = 34; 7223 7224 public static final int NEW_ANIMATOR_SCALE = 35; 7225 7226 @Override 7227 public void handleMessage(Message msg) { 7228 if (DEBUG_WINDOW_TRACE) { 7229 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 7230 } 7231 switch (msg.what) { 7232 case REPORT_FOCUS_CHANGE: { 7233 WindowState lastFocus; 7234 WindowState newFocus; 7235 7236 synchronized(mWindowMap) { 7237 lastFocus = mLastFocus; 7238 newFocus = mCurrentFocus; 7239 if (lastFocus == newFocus) { 7240 // Focus is not changing, so nothing to do. 7241 return; 7242 } 7243 mLastFocus = newFocus; 7244 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus + 7245 " to " + newFocus); 7246 if (newFocus != null && lastFocus != null 7247 && !newFocus.isDisplayedLw()) { 7248 //Slog.i(TAG, "Delaying loss of focus..."); 7249 mLosingFocus.add(lastFocus); 7250 lastFocus = null; 7251 } 7252 } 7253 7254 //System.out.println("Changing focus from " + lastFocus 7255 // + " to " + newFocus); 7256 if (newFocus != null) { 7257 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus); 7258 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 7259 notifyFocusChanged(); 7260 } 7261 7262 if (lastFocus != null) { 7263 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus); 7264 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 7265 } 7266 } break; 7267 7268 case REPORT_LOSING_FOCUS: { 7269 ArrayList<WindowState> losers; 7270 7271 synchronized(mWindowMap) { 7272 losers = mLosingFocus; 7273 mLosingFocus = new ArrayList<WindowState>(); 7274 } 7275 7276 final int N = losers.size(); 7277 for (int i=0; i<N; i++) { 7278 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " + 7279 losers.get(i)); 7280 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 7281 } 7282 } break; 7283 7284 case DO_TRAVERSAL: { 7285 synchronized(mWindowMap) { 7286 mTraversalScheduled = false; 7287 performLayoutAndPlaceSurfacesLocked(); 7288 } 7289 } break; 7290 7291 case ADD_STARTING: { 7292 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7293 final StartingData sd = wtoken.startingData; 7294 7295 if (sd == null) { 7296 // Animation has been canceled... do nothing. 7297 return; 7298 } 7299 7300 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 7301 + wtoken + ": pkg=" + sd.pkg); 7302 7303 View view = null; 7304 try { 7305 view = mPolicy.addStartingWindow( 7306 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 7307 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags); 7308 } catch (Exception e) { 7309 Slog.w(TAG, "Exception when adding starting window", e); 7310 } 7311 7312 if (view != null) { 7313 boolean abort = false; 7314 7315 synchronized(mWindowMap) { 7316 if (wtoken.removed || wtoken.startingData == null) { 7317 // If the window was successfully added, then 7318 // we need to remove it. 7319 if (wtoken.startingWindow != null) { 7320 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7321 "Aborted starting " + wtoken 7322 + ": removed=" + wtoken.removed 7323 + " startingData=" + wtoken.startingData); 7324 wtoken.startingWindow = null; 7325 wtoken.startingData = null; 7326 abort = true; 7327 } 7328 } else { 7329 wtoken.startingView = view; 7330 } 7331 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7332 "Added starting " + wtoken 7333 + ": startingWindow=" 7334 + wtoken.startingWindow + " startingView=" 7335 + wtoken.startingView); 7336 } 7337 7338 if (abort) { 7339 try { 7340 mPolicy.removeStartingWindow(wtoken.token, view); 7341 } catch (Exception e) { 7342 Slog.w(TAG, "Exception when removing starting window", e); 7343 } 7344 } 7345 } 7346 } break; 7347 7348 case REMOVE_STARTING: { 7349 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7350 IBinder token = null; 7351 View view = null; 7352 synchronized (mWindowMap) { 7353 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7354 + wtoken + ": startingWindow=" 7355 + wtoken.startingWindow + " startingView=" 7356 + wtoken.startingView); 7357 if (wtoken.startingWindow != null) { 7358 view = wtoken.startingView; 7359 token = wtoken.token; 7360 wtoken.startingData = null; 7361 wtoken.startingView = null; 7362 wtoken.startingWindow = null; 7363 wtoken.startingDisplayed = false; 7364 } 7365 } 7366 if (view != null) { 7367 try { 7368 mPolicy.removeStartingWindow(token, view); 7369 } catch (Exception e) { 7370 Slog.w(TAG, "Exception when removing starting window", e); 7371 } 7372 } 7373 } break; 7374 7375 case FINISHED_STARTING: { 7376 IBinder token = null; 7377 View view = null; 7378 while (true) { 7379 synchronized (mWindowMap) { 7380 final int N = mFinishedStarting.size(); 7381 if (N <= 0) { 7382 break; 7383 } 7384 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7385 7386 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7387 "Finished starting " + wtoken 7388 + ": startingWindow=" + wtoken.startingWindow 7389 + " startingView=" + wtoken.startingView); 7390 7391 if (wtoken.startingWindow == null) { 7392 continue; 7393 } 7394 7395 view = wtoken.startingView; 7396 token = wtoken.token; 7397 wtoken.startingData = null; 7398 wtoken.startingView = null; 7399 wtoken.startingWindow = null; 7400 wtoken.startingDisplayed = false; 7401 } 7402 7403 try { 7404 mPolicy.removeStartingWindow(token, view); 7405 } catch (Exception e) { 7406 Slog.w(TAG, "Exception when removing starting window", e); 7407 } 7408 } 7409 } break; 7410 7411 case REPORT_APPLICATION_TOKEN_DRAWN: { 7412 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7413 7414 try { 7415 if (DEBUG_VISIBILITY) Slog.v( 7416 TAG, "Reporting drawn in " + wtoken); 7417 wtoken.appToken.windowsDrawn(); 7418 } catch (RemoteException ex) { 7419 } 7420 } break; 7421 7422 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7423 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7424 7425 boolean nowVisible = msg.arg1 != 0; 7426 boolean nowGone = msg.arg2 != 0; 7427 7428 try { 7429 if (DEBUG_VISIBILITY) Slog.v( 7430 TAG, "Reporting visible in " + wtoken 7431 + " visible=" + nowVisible 7432 + " gone=" + nowGone); 7433 if (nowVisible) { 7434 wtoken.appToken.windowsVisible(); 7435 } else { 7436 wtoken.appToken.windowsGone(); 7437 } 7438 } catch (RemoteException ex) { 7439 } 7440 } break; 7441 7442 case WINDOW_FREEZE_TIMEOUT: { 7443 // TODO(multidisplay): Can non-default displays rotate? 7444 synchronized (mWindowMap) { 7445 Slog.w(TAG, "Window freeze timeout expired."); 7446 final WindowList windows = getDefaultWindowListLocked(); 7447 int i = windows.size(); 7448 while (i > 0) { 7449 i--; 7450 WindowState w = windows.get(i); 7451 if (w.mOrientationChanging) { 7452 w.mOrientationChanging = false; 7453 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 7454 - mDisplayFreezeTime); 7455 Slog.w(TAG, "Force clearing orientation change: " + w); 7456 } 7457 } 7458 performLayoutAndPlaceSurfacesLocked(); 7459 } 7460 break; 7461 } 7462 7463 case APP_TRANSITION_TIMEOUT: { 7464 synchronized (mWindowMap) { 7465 if (mAppTransition.isTransitionSet()) { 7466 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT"); 7467 mAppTransition.setTimeout(); 7468 performLayoutAndPlaceSurfacesLocked(); 7469 } 7470 } 7471 break; 7472 } 7473 7474 case PERSIST_ANIMATION_SCALE: { 7475 Settings.Global.putFloat(mContext.getContentResolver(), 7476 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 7477 Settings.Global.putFloat(mContext.getContentResolver(), 7478 Settings.Global.TRANSITION_ANIMATION_SCALE, 7479 mTransitionAnimationScaleSetting); 7480 Settings.Global.putFloat(mContext.getContentResolver(), 7481 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting); 7482 break; 7483 } 7484 7485 case FORCE_GC: { 7486 synchronized (mWindowMap) { 7487 // Since we're holding both mWindowMap and mAnimator we don't need to 7488 // hold mAnimator.mLayoutToAnim. 7489 if (mAnimator.mAnimating || mAnimationScheduled) { 7490 // If we are animating, don't do the gc now but 7491 // delay a bit so we don't interrupt the animation. 7492 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 7493 return; 7494 } 7495 // If we are currently rotating the display, it will 7496 // schedule a new message when done. 7497 if (mDisplayFrozen) { 7498 return; 7499 } 7500 } 7501 Runtime.getRuntime().gc(); 7502 break; 7503 } 7504 7505 case ENABLE_SCREEN: { 7506 performEnableScreen(); 7507 break; 7508 } 7509 7510 case APP_FREEZE_TIMEOUT: { 7511 synchronized (mWindowMap) { 7512 Slog.w(TAG, "App freeze timeout expired."); 7513 final int numStacks = mStackIdToStack.size(); 7514 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 7515 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 7516 final ArrayList<Task> tasks = stack.getTasks(); 7517 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 7518 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 7519 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 7520 AppWindowToken tok = tokens.get(tokenNdx); 7521 if (tok.mAppAnimator.freezingScreen) { 7522 Slog.w(TAG, "Force clearing freeze: " + tok); 7523 unsetAppFreezingScreenLocked(tok, true, true); 7524 } 7525 } 7526 } 7527 } 7528 } 7529 break; 7530 } 7531 7532 case CLIENT_FREEZE_TIMEOUT: { 7533 synchronized (mWindowMap) { 7534 if (mClientFreezingScreen) { 7535 mClientFreezingScreen = false; 7536 mLastFinishedFreezeSource = "client-timeout"; 7537 stopFreezingDisplayLocked(); 7538 } 7539 } 7540 break; 7541 } 7542 7543 case SEND_NEW_CONFIGURATION: { 7544 removeMessages(SEND_NEW_CONFIGURATION); 7545 sendNewConfiguration(); 7546 break; 7547 } 7548 7549 case REPORT_WINDOWS_CHANGE: { 7550 if (mWindowsChanged) { 7551 synchronized (mWindowMap) { 7552 mWindowsChanged = false; 7553 } 7554 notifyWindowsChanged(); 7555 } 7556 break; 7557 } 7558 7559 case DRAG_START_TIMEOUT: { 7560 IBinder win = (IBinder)msg.obj; 7561 if (DEBUG_DRAG) { 7562 Slog.w(TAG, "Timeout starting drag by win " + win); 7563 } 7564 synchronized (mWindowMap) { 7565 // !!! TODO: ANR the app that has failed to start the drag in time 7566 if (mDragState != null) { 7567 mDragState.unregister(); 7568 mInputMonitor.updateInputWindowsLw(true /*force*/); 7569 mDragState.reset(); 7570 mDragState = null; 7571 } 7572 } 7573 break; 7574 } 7575 7576 case DRAG_END_TIMEOUT: { 7577 IBinder win = (IBinder)msg.obj; 7578 if (DEBUG_DRAG) { 7579 Slog.w(TAG, "Timeout ending drag to win " + win); 7580 } 7581 synchronized (mWindowMap) { 7582 // !!! TODO: ANR the drag-receiving app 7583 if (mDragState != null) { 7584 mDragState.mDragResult = false; 7585 mDragState.endDragLw(); 7586 } 7587 } 7588 break; 7589 } 7590 7591 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7592 notifyHardKeyboardStatusChange(); 7593 break; 7594 } 7595 7596 case BOOT_TIMEOUT: { 7597 performBootTimeout(); 7598 break; 7599 } 7600 7601 case WAITING_FOR_DRAWN_TIMEOUT: { 7602 IRemoteCallback callback = null; 7603 synchronized (mWindowMap) { 7604 Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn); 7605 mWaitingForDrawn.clear(); 7606 callback = mWaitingForDrawnCallback; 7607 mWaitingForDrawnCallback = null; 7608 } 7609 if (callback != null) { 7610 try { 7611 callback.sendResult(null); 7612 } catch (RemoteException e) { 7613 } 7614 } 7615 break; 7616 } 7617 7618 case SHOW_STRICT_MODE_VIOLATION: { 7619 showStrictModeViolation(msg.arg1, msg.arg2); 7620 break; 7621 } 7622 7623 case SHOW_DISPLAY_MASK: { 7624 showCircularMask(); 7625 break; 7626 } 7627 7628 case DO_ANIMATION_CALLBACK: { 7629 try { 7630 ((IRemoteCallback)msg.obj).sendResult(null); 7631 } catch (RemoteException e) { 7632 } 7633 break; 7634 } 7635 7636 case DO_DISPLAY_ADDED: 7637 handleDisplayAdded(msg.arg1); 7638 break; 7639 7640 case DO_DISPLAY_REMOVED: 7641 synchronized (mWindowMap) { 7642 handleDisplayRemovedLocked(msg.arg1); 7643 } 7644 break; 7645 7646 case DO_DISPLAY_CHANGED: 7647 synchronized (mWindowMap) { 7648 handleDisplayChangedLocked(msg.arg1); 7649 } 7650 break; 7651 7652 case TAP_OUTSIDE_STACK: { 7653 int stackId; 7654 synchronized (mWindowMap) { 7655 stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2); 7656 } 7657 if (stackId >= 0) { 7658 try { 7659 mActivityManager.setFocusedStack(stackId); 7660 } catch (RemoteException e) { 7661 } 7662 } 7663 } 7664 break; 7665 case NOTIFY_ACTIVITY_DRAWN: 7666 try { 7667 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 7668 } catch (RemoteException e) { 7669 } 7670 break; 7671 case ALL_WINDOWS_DRAWN: { 7672 IRemoteCallback callback; 7673 synchronized (mWindowMap) { 7674 callback = mWaitingForDrawnCallback; 7675 mWaitingForDrawnCallback = null; 7676 } 7677 if (callback != null) { 7678 try { 7679 callback.sendResult(null); 7680 } catch (RemoteException e) { 7681 } 7682 } 7683 } 7684 case NEW_ANIMATOR_SCALE: { 7685 float scale = getCurrentAnimatorScale(); 7686 ValueAnimator.setDurationScale(scale); 7687 Session session = (Session)msg.obj; 7688 if (session != null) { 7689 try { 7690 session.mCallback.onAnimatorScaleChanged(scale); 7691 } catch (RemoteException e) { 7692 } 7693 } else { 7694 ArrayList<IWindowSessionCallback> callbacks 7695 = new ArrayList<IWindowSessionCallback>(); 7696 synchronized (mWindowMap) { 7697 for (int i=0; i<mSessions.size(); i++) { 7698 callbacks.add(mSessions.valueAt(i).mCallback); 7699 } 7700 7701 } 7702 for (int i=0; i<callbacks.size(); i++) { 7703 try { 7704 callbacks.get(i).onAnimatorScaleChanged(scale); 7705 } catch (RemoteException e) { 7706 } 7707 } 7708 } 7709 } 7710 break; 7711 } 7712 if (DEBUG_WINDOW_TRACE) { 7713 Slog.v(TAG, "handleMessage: exit"); 7714 } 7715 } 7716 } 7717 7718 // ------------------------------------------------------------- 7719 // IWindowManager API 7720 // ------------------------------------------------------------- 7721 7722 @Override 7723 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, 7724 IInputContext inputContext) { 7725 if (client == null) throw new IllegalArgumentException("null client"); 7726 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7727 Session session = new Session(this, callback, client, inputContext); 7728 return session; 7729 } 7730 7731 @Override 7732 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7733 synchronized (mWindowMap) { 7734 // The focus for the client is the window immediately below 7735 // where we would place the input method window. 7736 int idx = findDesiredInputMethodWindowIndexLocked(false); 7737 if (idx > 0) { 7738 // TODO(multidisplay): IMEs are only supported on the default display. 7739 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 7740 if (DEBUG_INPUT_METHOD) { 7741 Slog.i(TAG, "Desired input method target: " + imFocus); 7742 Slog.i(TAG, "Current focus: " + mCurrentFocus); 7743 Slog.i(TAG, "Last focus: " + mLastFocus); 7744 } 7745 if (imFocus != null) { 7746 // This may be a starting window, in which case we still want 7747 // to count it as okay. 7748 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7749 && imFocus.mAppToken != null) { 7750 // The client has definitely started, so it really should 7751 // have a window in this app token. Let's look for it. 7752 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7753 WindowState w = imFocus.mAppToken.windows.get(i); 7754 if (w != imFocus) { 7755 Log.i(TAG, "Switching to real app window: " + w); 7756 imFocus = w; 7757 break; 7758 } 7759 } 7760 } 7761 if (DEBUG_INPUT_METHOD) { 7762 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7763 if (imFocus.mSession.mClient != null) { 7764 Slog.i(TAG, "IM target client binder: " 7765 + imFocus.mSession.mClient.asBinder()); 7766 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 7767 } 7768 } 7769 if (imFocus.mSession.mClient != null && 7770 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7771 return true; 7772 } 7773 } 7774 } 7775 7776 // Okay, how about this... what is the current focus? 7777 // It seems in some cases we may not have moved the IM 7778 // target window, such as when it was in a pop-up window, 7779 // so let's also look at the current focus. (An example: 7780 // go to Gmail, start searching so the keyboard goes up, 7781 // press home. Sometimes the IME won't go down.) 7782 // Would be nice to fix this more correctly, but it's 7783 // way at the end of a release, and this should be good enough. 7784 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 7785 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7786 return true; 7787 } 7788 } 7789 return false; 7790 } 7791 7792 @Override 7793 public void getInitialDisplaySize(int displayId, Point size) { 7794 synchronized (mWindowMap) { 7795 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7796 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7797 synchronized(displayContent.mDisplaySizeLock) { 7798 size.x = displayContent.mInitialDisplayWidth; 7799 size.y = displayContent.mInitialDisplayHeight; 7800 } 7801 } 7802 } 7803 } 7804 7805 @Override 7806 public void getBaseDisplaySize(int displayId, Point size) { 7807 synchronized (mWindowMap) { 7808 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7809 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7810 synchronized(displayContent.mDisplaySizeLock) { 7811 size.x = displayContent.mBaseDisplayWidth; 7812 size.y = displayContent.mBaseDisplayHeight; 7813 } 7814 } 7815 } 7816 } 7817 7818 @Override 7819 public void setForcedDisplaySize(int displayId, int width, int height) { 7820 if (mContext.checkCallingOrSelfPermission( 7821 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7822 PackageManager.PERMISSION_GRANTED) { 7823 throw new SecurityException("Must hold permission " + 7824 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7825 } 7826 if (displayId != Display.DEFAULT_DISPLAY) { 7827 throw new IllegalArgumentException("Can only set the default display"); 7828 } 7829 final long ident = Binder.clearCallingIdentity(); 7830 try { 7831 synchronized(mWindowMap) { 7832 // Set some sort of reasonable bounds on the size of the display that we 7833 // will try to emulate. 7834 final int MIN_WIDTH = 200; 7835 final int MIN_HEIGHT = 200; 7836 final int MAX_SCALE = 2; 7837 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7838 if (displayContent != null) { 7839 width = Math.min(Math.max(width, MIN_WIDTH), 7840 displayContent.mInitialDisplayWidth * MAX_SCALE); 7841 height = Math.min(Math.max(height, MIN_HEIGHT), 7842 displayContent.mInitialDisplayHeight * MAX_SCALE); 7843 setForcedDisplaySizeLocked(displayContent, width, height); 7844 Settings.Global.putString(mContext.getContentResolver(), 7845 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 7846 } 7847 } 7848 } finally { 7849 Binder.restoreCallingIdentity(ident); 7850 } 7851 } 7852 7853 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 7854 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 7855 Settings.Global.DISPLAY_SIZE_FORCED); 7856 if (sizeStr == null || sizeStr.length() == 0) { 7857 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 7858 } 7859 if (sizeStr != null && sizeStr.length() > 0) { 7860 final int pos = sizeStr.indexOf(','); 7861 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 7862 int width, height; 7863 try { 7864 width = Integer.parseInt(sizeStr.substring(0, pos)); 7865 height = Integer.parseInt(sizeStr.substring(pos+1)); 7866 synchronized(displayContent.mDisplaySizeLock) { 7867 if (displayContent.mBaseDisplayWidth != width 7868 || displayContent.mBaseDisplayHeight != height) { 7869 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 7870 displayContent.mBaseDisplayWidth = width; 7871 displayContent.mBaseDisplayHeight = height; 7872 } 7873 } 7874 } catch (NumberFormatException ex) { 7875 } 7876 } 7877 } 7878 String densityStr = Settings.Global.getString(mContext.getContentResolver(), 7879 Settings.Global.DISPLAY_DENSITY_FORCED); 7880 if (densityStr == null || densityStr.length() == 0) { 7881 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 7882 } 7883 if (densityStr != null && densityStr.length() > 0) { 7884 int density; 7885 try { 7886 density = Integer.parseInt(densityStr); 7887 synchronized(displayContent.mDisplaySizeLock) { 7888 if (displayContent.mBaseDisplayDensity != density) { 7889 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 7890 displayContent.mBaseDisplayDensity = density; 7891 } 7892 } 7893 } catch (NumberFormatException ex) { 7894 } 7895 } 7896 } 7897 7898 // displayContent must not be null 7899 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 7900 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7901 7902 synchronized(displayContent.mDisplaySizeLock) { 7903 displayContent.mBaseDisplayWidth = width; 7904 displayContent.mBaseDisplayHeight = height; 7905 } 7906 reconfigureDisplayLocked(displayContent); 7907 } 7908 7909 @Override 7910 public void clearForcedDisplaySize(int displayId) { 7911 if (mContext.checkCallingOrSelfPermission( 7912 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7913 PackageManager.PERMISSION_GRANTED) { 7914 throw new SecurityException("Must hold permission " + 7915 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7916 } 7917 if (displayId != Display.DEFAULT_DISPLAY) { 7918 throw new IllegalArgumentException("Can only set the default display"); 7919 } 7920 final long ident = Binder.clearCallingIdentity(); 7921 try { 7922 synchronized(mWindowMap) { 7923 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7924 if (displayContent != null) { 7925 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 7926 displayContent.mInitialDisplayHeight); 7927 Settings.Global.putString(mContext.getContentResolver(), 7928 Settings.Global.DISPLAY_SIZE_FORCED, ""); 7929 } 7930 } 7931 } finally { 7932 Binder.restoreCallingIdentity(ident); 7933 } 7934 } 7935 7936 @Override 7937 public int getInitialDisplayDensity(int displayId) { 7938 synchronized (mWindowMap) { 7939 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7940 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7941 synchronized(displayContent.mDisplaySizeLock) { 7942 return displayContent.mInitialDisplayDensity; 7943 } 7944 } 7945 } 7946 return -1; 7947 } 7948 7949 @Override 7950 public int getBaseDisplayDensity(int displayId) { 7951 synchronized (mWindowMap) { 7952 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7953 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7954 synchronized(displayContent.mDisplaySizeLock) { 7955 return displayContent.mBaseDisplayDensity; 7956 } 7957 } 7958 } 7959 return -1; 7960 } 7961 7962 @Override 7963 public void setForcedDisplayDensity(int displayId, int density) { 7964 if (mContext.checkCallingOrSelfPermission( 7965 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7966 PackageManager.PERMISSION_GRANTED) { 7967 throw new SecurityException("Must hold permission " + 7968 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7969 } 7970 if (displayId != Display.DEFAULT_DISPLAY) { 7971 throw new IllegalArgumentException("Can only set the default display"); 7972 } 7973 final long ident = Binder.clearCallingIdentity(); 7974 try { 7975 synchronized(mWindowMap) { 7976 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7977 if (displayContent != null) { 7978 setForcedDisplayDensityLocked(displayContent, density); 7979 Settings.Global.putString(mContext.getContentResolver(), 7980 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 7981 } 7982 } 7983 } finally { 7984 Binder.restoreCallingIdentity(ident); 7985 } 7986 } 7987 7988 // displayContent must not be null 7989 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 7990 Slog.i(TAG, "Using new display density: " + density); 7991 7992 synchronized(displayContent.mDisplaySizeLock) { 7993 displayContent.mBaseDisplayDensity = density; 7994 } 7995 reconfigureDisplayLocked(displayContent); 7996 } 7997 7998 @Override 7999 public void clearForcedDisplayDensity(int displayId) { 8000 if (mContext.checkCallingOrSelfPermission( 8001 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8002 PackageManager.PERMISSION_GRANTED) { 8003 throw new SecurityException("Must hold permission " + 8004 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8005 } 8006 if (displayId != Display.DEFAULT_DISPLAY) { 8007 throw new IllegalArgumentException("Can only set the default display"); 8008 } 8009 final long ident = Binder.clearCallingIdentity(); 8010 try { 8011 synchronized(mWindowMap) { 8012 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8013 if (displayContent != null) { 8014 setForcedDisplayDensityLocked(displayContent, 8015 displayContent.mInitialDisplayDensity); 8016 Settings.Global.putString(mContext.getContentResolver(), 8017 Settings.Global.DISPLAY_DENSITY_FORCED, ""); 8018 } 8019 } 8020 } finally { 8021 Binder.restoreCallingIdentity(ident); 8022 } 8023 } 8024 8025 // displayContent must not be null 8026 private void reconfigureDisplayLocked(DisplayContent displayContent) { 8027 // TODO: Multidisplay: for now only use with default display. 8028 configureDisplayPolicyLocked(displayContent); 8029 displayContent.layoutNeeded = true; 8030 8031 boolean configChanged = updateOrientationFromAppTokensLocked(false); 8032 mTempConfiguration.setToDefaults(); 8033 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 8034 if (computeScreenConfigurationLocked(mTempConfiguration)) { 8035 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 8036 configChanged = true; 8037 } 8038 } 8039 8040 if (configChanged) { 8041 mWaitingForConfig = true; 8042 startFreezingDisplayLocked(false, 0, 0); 8043 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8044 } 8045 8046 performLayoutAndPlaceSurfacesLocked(); 8047 } 8048 8049 private void configureDisplayPolicyLocked(DisplayContent displayContent) { 8050 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 8051 displayContent.mBaseDisplayWidth, 8052 displayContent.mBaseDisplayHeight, 8053 displayContent.mBaseDisplayDensity); 8054 8055 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8056 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 8057 displayInfo.overscanLeft, displayInfo.overscanTop, 8058 displayInfo.overscanRight, displayInfo.overscanBottom); 8059 } 8060 8061 @Override 8062 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 8063 if (mContext.checkCallingOrSelfPermission( 8064 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8065 PackageManager.PERMISSION_GRANTED) { 8066 throw new SecurityException("Must hold permission " + 8067 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8068 } 8069 final long ident = Binder.clearCallingIdentity(); 8070 try { 8071 synchronized(mWindowMap) { 8072 DisplayContent displayContent = getDisplayContentLocked(displayId); 8073 if (displayContent != null) { 8074 setOverscanLocked(displayContent, left, top, right, bottom); 8075 } 8076 } 8077 } finally { 8078 Binder.restoreCallingIdentity(ident); 8079 } 8080 } 8081 8082 private void setOverscanLocked(DisplayContent displayContent, 8083 int left, int top, int right, int bottom) { 8084 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8085 synchronized (displayContent.mDisplaySizeLock) { 8086 displayInfo.overscanLeft = left; 8087 displayInfo.overscanTop = top; 8088 displayInfo.overscanRight = right; 8089 displayInfo.overscanBottom = bottom; 8090 } 8091 8092 mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom); 8093 mDisplaySettings.writeSettingsLocked(); 8094 8095 reconfigureDisplayLocked(displayContent); 8096 } 8097 8098 // ------------------------------------------------------------- 8099 // Internals 8100 // ------------------------------------------------------------- 8101 8102 final WindowState windowForClientLocked(Session session, IWindow client, 8103 boolean throwOnError) { 8104 return windowForClientLocked(session, client.asBinder(), throwOnError); 8105 } 8106 8107 final WindowState windowForClientLocked(Session session, IBinder client, 8108 boolean throwOnError) { 8109 WindowState win = mWindowMap.get(client); 8110 if (localLOGV) Slog.v( 8111 TAG, "Looking up client " + client + ": " + win); 8112 if (win == null) { 8113 RuntimeException ex = new IllegalArgumentException( 8114 "Requested window " + client + " does not exist"); 8115 if (throwOnError) { 8116 throw ex; 8117 } 8118 Slog.w(TAG, "Failed looking up window", ex); 8119 return null; 8120 } 8121 if (session != null && win.mSession != session) { 8122 RuntimeException ex = new IllegalArgumentException( 8123 "Requested window " + client + " is in session " + 8124 win.mSession + ", not " + session); 8125 if (throwOnError) { 8126 throw ex; 8127 } 8128 Slog.w(TAG, "Failed looking up window", ex); 8129 return null; 8130 } 8131 8132 return win; 8133 } 8134 8135 final void rebuildAppWindowListLocked() { 8136 rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); 8137 } 8138 8139 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 8140 final WindowList windows = displayContent.getWindowList(); 8141 int NW = windows.size(); 8142 int i; 8143 int lastBelow = -1; 8144 int numRemoved = 0; 8145 8146 if (mRebuildTmp.length < NW) { 8147 mRebuildTmp = new WindowState[NW+10]; 8148 } 8149 8150 // First remove all existing app windows. 8151 i=0; 8152 while (i < NW) { 8153 WindowState w = windows.get(i); 8154 if (w.mAppToken != null) { 8155 WindowState win = windows.remove(i); 8156 win.mRebuilding = true; 8157 mRebuildTmp[numRemoved] = win; 8158 mWindowsChanged = true; 8159 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win); 8160 NW--; 8161 numRemoved++; 8162 continue; 8163 } else if (lastBelow == i-1) { 8164 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8165 lastBelow = i; 8166 } 8167 } 8168 i++; 8169 } 8170 8171 // Keep whatever windows were below the app windows still below, 8172 // by skipping them. 8173 lastBelow++; 8174 i = lastBelow; 8175 8176 // First add all of the exiting app tokens... these are no longer 8177 // in the main app list, but still have windows shown. We put them 8178 // in the back because now that the animation is over we no longer 8179 // will care about them. 8180 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 8181 final int numStacks = stacks.size(); 8182 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8183 AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens; 8184 int NT = exitingAppTokens.size(); 8185 for (int j = 0; j < NT; j++) { 8186 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 8187 } 8188 } 8189 8190 // And add in the still active app tokens in Z order. 8191 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8192 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8193 final int numTasks = tasks.size(); 8194 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 8195 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8196 final int numTokens = tokens.size(); 8197 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 8198 final AppWindowToken wtoken = tokens.get(tokenNdx); 8199 if (wtoken.mDeferRemoval) { 8200 continue; 8201 } 8202 i = reAddAppWindowsLocked(displayContent, i, wtoken); 8203 } 8204 } 8205 } 8206 8207 i -= lastBelow; 8208 if (i != numRemoved) { 8209 Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " + 8210 numRemoved + " windows but added " + i, 8211 new RuntimeException("here").fillInStackTrace()); 8212 for (i=0; i<numRemoved; i++) { 8213 WindowState ws = mRebuildTmp[i]; 8214 if (ws.mRebuilding) { 8215 StringWriter sw = new StringWriter(); 8216 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 8217 ws.dump(pw, "", true); 8218 pw.flush(); 8219 Slog.w(TAG, "This window was lost: " + ws); 8220 Slog.w(TAG, sw.toString()); 8221 ws.mWinAnimator.destroySurfaceLocked(); 8222 } 8223 } 8224 Slog.w(TAG, "Current app token list:"); 8225 dumpAppTokensLocked(); 8226 Slog.w(TAG, "Final window list:"); 8227 dumpWindowsLocked(); 8228 } 8229 } 8230 8231 private final void assignLayersLocked(WindowList windows) { 8232 int N = windows.size(); 8233 int curBaseLayer = 0; 8234 int curLayer = 0; 8235 int i; 8236 8237 if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows, 8238 new RuntimeException("here").fillInStackTrace()); 8239 8240 boolean anyLayerChanged = false; 8241 8242 for (i=0; i<N; i++) { 8243 final WindowState w = windows.get(i); 8244 final WindowStateAnimator winAnimator = w.mWinAnimator; 8245 boolean layerChanged = false; 8246 int oldLayer = w.mLayer; 8247 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 8248 || (i > 0 && w.mIsWallpaper)) { 8249 curLayer += WINDOW_LAYER_MULTIPLIER; 8250 w.mLayer = curLayer; 8251 } else { 8252 curBaseLayer = curLayer = w.mBaseLayer; 8253 w.mLayer = curLayer; 8254 } 8255 if (w.mLayer != oldLayer) { 8256 layerChanged = true; 8257 anyLayerChanged = true; 8258 } 8259 final AppWindowToken wtoken = w.mAppToken; 8260 oldLayer = winAnimator.mAnimLayer; 8261 if (w.mTargetAppToken != null) { 8262 winAnimator.mAnimLayer = 8263 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 8264 } else if (wtoken != null) { 8265 winAnimator.mAnimLayer = 8266 w.mLayer + wtoken.mAppAnimator.animLayerAdjustment; 8267 } else { 8268 winAnimator.mAnimLayer = w.mLayer; 8269 } 8270 if (w.mIsImWindow) { 8271 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 8272 } else if (w.mIsWallpaper) { 8273 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 8274 } 8275 if (winAnimator.mAnimLayer != oldLayer) { 8276 layerChanged = true; 8277 anyLayerChanged = true; 8278 } 8279 if (layerChanged && w.getStack().isDimming(winAnimator)) { 8280 // Force an animation pass just to update the mDimLayer layer. 8281 scheduleAnimationLocked(); 8282 } 8283 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 8284 + "mBase=" + w.mBaseLayer 8285 + " mLayer=" + w.mLayer 8286 + (wtoken == null ? 8287 "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment) 8288 + " =mAnimLayer=" + winAnimator.mAnimLayer); 8289 //System.out.println( 8290 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 8291 } 8292 8293 //TODO (multidisplay): Magnification is supported only for the default display. 8294 if (mAccessibilityController != null && anyLayerChanged 8295 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) { 8296 mAccessibilityController.onWindowLayersChangedLocked(); 8297 } 8298 } 8299 8300 private final void performLayoutAndPlaceSurfacesLocked() { 8301 int loopCount = 6; 8302 do { 8303 mTraversalScheduled = false; 8304 performLayoutAndPlaceSurfacesLockedLoop(); 8305 mH.removeMessages(H.DO_TRAVERSAL); 8306 loopCount--; 8307 } while (mTraversalScheduled && loopCount > 0); 8308 mInnerFields.mWallpaperActionPending = false; 8309 } 8310 8311 private boolean mInLayout = false; 8312 private final void performLayoutAndPlaceSurfacesLockedLoop() { 8313 if (mInLayout) { 8314 if (DEBUG) { 8315 throw new RuntimeException("Recursive call!"); 8316 } 8317 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 8318 + Debug.getCallers(3)); 8319 return; 8320 } 8321 8322 if (mWaitingForConfig) { 8323 // Our configuration has changed (most likely rotation), but we 8324 // don't yet have the complete configuration to report to 8325 // applications. Don't do any window layout until we have it. 8326 return; 8327 } 8328 8329 if (!mDisplayReady) { 8330 // Not yet initialized, nothing to do. 8331 return; 8332 } 8333 8334 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 8335 mInLayout = true; 8336 boolean recoveringMemory = false; 8337 8338 try { 8339 if (mForceRemoves != null) { 8340 recoveringMemory = true; 8341 // Wait a little bit for things to settle down, and off we go. 8342 for (int i=0; i<mForceRemoves.size(); i++) { 8343 WindowState ws = mForceRemoves.get(i); 8344 Slog.i(TAG, "Force removing: " + ws); 8345 removeWindowInnerLocked(ws.mSession, ws); 8346 } 8347 mForceRemoves = null; 8348 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 8349 Object tmp = new Object(); 8350 synchronized (tmp) { 8351 try { 8352 tmp.wait(250); 8353 } catch (InterruptedException e) { 8354 } 8355 } 8356 } 8357 } catch (RuntimeException e) { 8358 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 8359 } 8360 8361 try { 8362 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 8363 8364 mInLayout = false; 8365 8366 if (needsLayout()) { 8367 if (++mLayoutRepeatCount < 6) { 8368 requestTraversalLocked(); 8369 } else { 8370 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 8371 mLayoutRepeatCount = 0; 8372 } 8373 } else { 8374 mLayoutRepeatCount = 0; 8375 } 8376 8377 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 8378 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 8379 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE); 8380 } 8381 } catch (RuntimeException e) { 8382 mInLayout = false; 8383 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 8384 } 8385 8386 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 8387 } 8388 8389 private final void performLayoutLockedInner(final DisplayContent displayContent, 8390 boolean initial, boolean updateInputWindows) { 8391 if (!displayContent.layoutNeeded) { 8392 return; 8393 } 8394 displayContent.layoutNeeded = false; 8395 WindowList windows = displayContent.getWindowList(); 8396 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 8397 8398 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8399 final int dw = displayInfo.logicalWidth; 8400 final int dh = displayInfo.logicalHeight; 8401 8402 final int NFW = mFakeWindows.size(); 8403 for (int i=0; i<NFW; i++) { 8404 mFakeWindows.get(i).layout(dw, dh); 8405 } 8406 8407 final int N = windows.size(); 8408 int i; 8409 8410 if (DEBUG_LAYOUT) { 8411 Slog.v(TAG, "-------------------------------------"); 8412 Slog.v(TAG, "performLayout: needed=" 8413 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 8414 } 8415 8416 WindowStateAnimator universeBackground = null; 8417 8418 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); 8419 if (isDefaultDisplay) { 8420 // Not needed on non-default displays. 8421 mSystemDecorLayer = mPolicy.getSystemDecorLayerLw(); 8422 mScreenRect.set(0, 0, dw, dh); 8423 } 8424 8425 mPolicy.getContentRectLw(mTmpContentRect); 8426 displayContent.resize(mTmpContentRect); 8427 8428 int seq = mLayoutSeq+1; 8429 if (seq < 0) seq = 0; 8430 mLayoutSeq = seq; 8431 8432 boolean behindDream = false; 8433 8434 // First perform layout of any root windows (not attached 8435 // to another window). 8436 int topAttached = -1; 8437 for (i = N-1; i >= 0; i--) { 8438 final WindowState win = windows.get(i); 8439 8440 // Don't do layout of a window if it is not visible, or 8441 // soon won't be visible, to avoid wasting time and funky 8442 // changes while a window is animating away. 8443 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) 8444 || win.isGoneForLayoutLw(); 8445 8446 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 8447 Slog.v(TAG, "1ST PASS " + win 8448 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 8449 + " mLayoutAttached=" + win.mLayoutAttached 8450 + " screen changed=" + win.isConfigChanged()); 8451 final AppWindowToken atoken = win.mAppToken; 8452 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 8453 + win.mViewVisibility + " mRelayoutCalled=" 8454 + win.mRelayoutCalled + " hidden=" 8455 + win.mRootToken.hidden + " hiddenRequested=" 8456 + (atoken != null && atoken.hiddenRequested) 8457 + " mAttachedHidden=" + win.mAttachedHidden); 8458 else Slog.v(TAG, " VIS: mViewVisibility=" 8459 + win.mViewVisibility + " mRelayoutCalled=" 8460 + win.mRelayoutCalled + " hidden=" 8461 + win.mRootToken.hidden + " hiddenRequested=" 8462 + (atoken != null && atoken.hiddenRequested) 8463 + " mAttachedHidden=" + win.mAttachedHidden); 8464 } 8465 8466 // If this view is GONE, then skip it -- keep the current 8467 // frame, and let the caller know so they can ignore it 8468 // if they want. (We do the normal layout for INVISIBLE 8469 // windows, since that means "perform layout as normal, 8470 // just don't display"). 8471 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 8472 || ((win.isConfigChanged() || win.setInsetsChanged()) && 8473 ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || 8474 win.mAppToken != null && win.mAppToken.layoutConfigChanges)) 8475 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8476 if (!win.mLayoutAttached) { 8477 if (initial) { 8478 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8479 win.mContentChanged = false; 8480 } 8481 if (win.mAttrs.type == TYPE_DREAM) { 8482 // Don't layout windows behind a dream, so that if it 8483 // does stuff like hide the status bar we won't get a 8484 // bad transition when it goes away. 8485 behindDream = true; 8486 } 8487 win.mLayoutNeeded = false; 8488 win.prelayout(); 8489 mPolicy.layoutWindowLw(win, win.mAttrs, null); 8490 win.mLayoutSeq = seq; 8491 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8492 + win.mFrame + " mContainingFrame=" 8493 + win.mContainingFrame + " mDisplayFrame=" 8494 + win.mDisplayFrame); 8495 } else { 8496 if (topAttached < 0) topAttached = i; 8497 } 8498 } 8499 if (win.mViewVisibility == View.VISIBLE 8500 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 8501 && universeBackground == null) { 8502 universeBackground = win.mWinAnimator; 8503 } 8504 } 8505 8506 if (mAnimator.mUniverseBackground != universeBackground) { 8507 mFocusMayChange = true; 8508 mAnimator.mUniverseBackground = universeBackground; 8509 } 8510 8511 boolean attachedBehindDream = false; 8512 8513 // Now perform layout of attached windows, which usually 8514 // depend on the position of the window they are attached to. 8515 // XXX does not deal with windows that are attached to windows 8516 // that are themselves attached. 8517 for (i = topAttached; i >= 0; i--) { 8518 final WindowState win = windows.get(i); 8519 8520 if (win.mLayoutAttached) { 8521 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 8522 + " mHaveFrame=" + win.mHaveFrame 8523 + " mViewVisibility=" + win.mViewVisibility 8524 + " mRelayoutCalled=" + win.mRelayoutCalled); 8525 // If this view is GONE, then skip it -- keep the current 8526 // frame, and let the caller know so they can ignore it 8527 // if they want. (We do the normal layout for INVISIBLE 8528 // windows, since that means "perform layout as normal, 8529 // just don't display"). 8530 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) { 8531 continue; 8532 } 8533 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8534 || !win.mHaveFrame || win.mLayoutNeeded) { 8535 if (initial) { 8536 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8537 win.mContentChanged = false; 8538 } 8539 win.mLayoutNeeded = false; 8540 win.prelayout(); 8541 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 8542 win.mLayoutSeq = seq; 8543 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8544 + win.mFrame + " mContainingFrame=" 8545 + win.mContainingFrame + " mDisplayFrame=" 8546 + win.mDisplayFrame); 8547 } 8548 } else if (win.mAttrs.type == TYPE_DREAM) { 8549 // Don't layout windows behind a dream, so that if it 8550 // does stuff like hide the status bar we won't get a 8551 // bad transition when it goes away. 8552 attachedBehindDream = behindDream; 8553 } 8554 } 8555 8556 // Window frames may have changed. Tell the input dispatcher about it. 8557 mInputMonitor.setUpdateInputWindowsNeededLw(); 8558 if (updateInputWindows) { 8559 mInputMonitor.updateInputWindowsLw(false /*force*/); 8560 } 8561 8562 mPolicy.finishLayoutLw(); 8563 } 8564 8565 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8566 // If the screen is currently frozen or off, then keep 8567 // it frozen/off until this window draws at its new 8568 // orientation. 8569 if (!okToDisplay()) { 8570 if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w); 8571 w.mOrientationChanging = true; 8572 w.mLastFreezeDuration = 0; 8573 mInnerFields.mOrientationChangeComplete = false; 8574 if (!mWindowsFreezingScreen) { 8575 mWindowsFreezingScreen = true; 8576 // XXX should probably keep timeout from 8577 // when we first froze the display. 8578 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8579 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 8580 WINDOW_FREEZE_TIMEOUT_DURATION); 8581 } 8582 } 8583 } 8584 8585 /** 8586 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8587 * @param windows List of windows on default display. 8588 * @return bitmap indicating if another pass through layout must be made. 8589 */ 8590 public int handleAppTransitionReadyLocked(WindowList windows) { 8591 int changes = 0; 8592 int i; 8593 int NN = mOpeningApps.size(); 8594 boolean goodToGo = true; 8595 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8596 "Checking " + NN + " opening apps (frozen=" 8597 + mDisplayFrozen + " timeout=" 8598 + mAppTransition.isTimeout() + ")..."); 8599 if (!mDisplayFrozen && !mAppTransition.isTimeout()) { 8600 // If the display isn't frozen, wait to do anything until 8601 // all of the apps are ready. Otherwise just go because 8602 // we'll unfreeze the display when everyone is ready. 8603 for (i=0; i<NN && goodToGo; i++) { 8604 AppWindowToken wtoken = mOpeningApps.get(i); 8605 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8606 "Check opening app=" + wtoken + ": allDrawn=" 8607 + wtoken.allDrawn + " startingDisplayed=" 8608 + wtoken.startingDisplayed + " startingMoved=" 8609 + wtoken.startingMoved); 8610 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8611 && !wtoken.startingMoved) { 8612 goodToGo = false; 8613 } 8614 } 8615 } 8616 if (goodToGo) { 8617 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8618 int transit = mAppTransition.getAppTransition(); 8619 if (mSkipAppTransitionAnimation) { 8620 transit = AppTransition.TRANSIT_UNSET; 8621 } 8622 mAppTransition.goodToGo(); 8623 mStartingIconInTransition = false; 8624 mSkipAppTransitionAnimation = false; 8625 8626 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8627 8628 rebuildAppWindowListLocked(); 8629 8630 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8631 WindowState oldWallpaper = 8632 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8633 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8634 ? null : mWallpaperTarget; 8635 8636 mInnerFields.mWallpaperMayChange = false; 8637 8638 // The top-most window will supply the layout params, 8639 // and we will determine it below. 8640 LayoutParams animLp = null; 8641 int bestAnimLayer = -1; 8642 boolean fullscreenAnim = false; 8643 boolean voiceInteraction = false; 8644 8645 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8646 "New wallpaper target=" + mWallpaperTarget 8647 + ", oldWallpaper=" + oldWallpaper 8648 + ", lower target=" + mLowerWallpaperTarget 8649 + ", upper target=" + mUpperWallpaperTarget); 8650 8651 boolean openingAppHasWallpaper = false; 8652 boolean closingAppHasWallpaper = false; 8653 final AppWindowToken lowerWallpaperAppToken; 8654 final AppWindowToken upperWallpaperAppToken; 8655 if (mLowerWallpaperTarget == null) { 8656 lowerWallpaperAppToken = upperWallpaperAppToken = null; 8657 } else { 8658 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken; 8659 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken; 8660 } 8661 8662 // Do a first pass through the tokens for two 8663 // things: 8664 // (1) Determine if both the closing and opening 8665 // app token sets are wallpaper targets, in which 8666 // case special animations are needed 8667 // (since the wallpaper needs to stay static 8668 // behind them). 8669 // (2) Find the layout params of the top-most 8670 // application window in the tokens, which is 8671 // what will control the animation theme. 8672 final int NC = mClosingApps.size(); 8673 NN = NC + mOpeningApps.size(); 8674 for (i=0; i<NN; i++) { 8675 final AppWindowToken wtoken; 8676 if (i < NC) { 8677 wtoken = mClosingApps.get(i); 8678 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8679 closingAppHasWallpaper = true; 8680 } 8681 } else { 8682 wtoken = mOpeningApps.get(i - NC); 8683 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8684 openingAppHasWallpaper = true; 8685 } 8686 } 8687 8688 voiceInteraction |= wtoken.voiceInteraction; 8689 8690 if (wtoken.appFullscreen) { 8691 WindowState ws = wtoken.findMainWindow(); 8692 if (ws != null) { 8693 animLp = ws.mAttrs; 8694 bestAnimLayer = ws.mLayer; 8695 fullscreenAnim = true; 8696 } 8697 } else if (!fullscreenAnim) { 8698 WindowState ws = wtoken.findMainWindow(); 8699 if (ws != null) { 8700 if (ws.mLayer > bestAnimLayer) { 8701 animLp = ws.mAttrs; 8702 bestAnimLayer = ws.mLayer; 8703 } 8704 } 8705 } 8706 } 8707 8708 mAnimateWallpaperWithTarget = false; 8709 if (closingAppHasWallpaper && openingAppHasWallpaper) { 8710 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!"); 8711 switch (transit) { 8712 case AppTransition.TRANSIT_ACTIVITY_OPEN: 8713 case AppTransition.TRANSIT_TASK_OPEN: 8714 case AppTransition.TRANSIT_TASK_TO_FRONT: 8715 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN; 8716 break; 8717 case AppTransition.TRANSIT_ACTIVITY_CLOSE: 8718 case AppTransition.TRANSIT_TASK_CLOSE: 8719 case AppTransition.TRANSIT_TASK_TO_BACK: 8720 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; 8721 break; 8722 } 8723 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); 8724 } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty() 8725 && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 8726 // We are transitioning from an activity with 8727 // a wallpaper to one without. 8728 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; 8729 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8730 "New transit away from wallpaper: " + transit); 8731 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) { 8732 // We are transitioning from an activity without 8733 // a wallpaper to now showing the wallpaper 8734 transit = AppTransition.TRANSIT_WALLPAPER_OPEN; 8735 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8736 "New transit into wallpaper: " + transit); 8737 } else { 8738 mAnimateWallpaperWithTarget = true; 8739 } 8740 8741 // If all closing windows are obscured, then there is 8742 // no need to do an animation. This is the case, for 8743 // example, when this transition is being done behind 8744 // the lock screen. 8745 if (!mPolicy.allowAppAnimationsLw()) { 8746 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8747 "Animations disallowed by keyguard or dream."); 8748 animLp = null; 8749 } 8750 8751 AppWindowToken topOpeningApp = null; 8752 int topOpeningLayer = 0; 8753 8754 NN = mOpeningApps.size(); 8755 for (i=0; i<NN; i++) { 8756 AppWindowToken wtoken = mOpeningApps.get(i); 8757 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 8758 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 8759 appAnimator.clearThumbnail(); 8760 wtoken.inPendingTransaction = false; 8761 appAnimator.animation = null; 8762 setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction); 8763 wtoken.updateReportedVisibilityLocked(); 8764 wtoken.waitingToShow = false; 8765 8766 appAnimator.mAllAppWinAnimators.clear(); 8767 final int N = wtoken.allAppWindows.size(); 8768 for (int j = 0; j < N; j++) { 8769 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 8770 } 8771 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 8772 8773 if (animLp != null) { 8774 int layer = -1; 8775 for (int j=0; j<wtoken.windows.size(); j++) { 8776 WindowState win = wtoken.windows.get(j); 8777 if (win.mWinAnimator.mAnimLayer > layer) { 8778 layer = win.mWinAnimator.mAnimLayer; 8779 } 8780 } 8781 if (topOpeningApp == null || layer > topOpeningLayer) { 8782 topOpeningApp = wtoken; 8783 topOpeningLayer = layer; 8784 } 8785 } 8786 } 8787 NN = mClosingApps.size(); 8788 for (i=0; i<NN; i++) { 8789 AppWindowToken wtoken = mClosingApps.get(i); 8790 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken); 8791 wtoken.mAppAnimator.clearThumbnail(); 8792 wtoken.inPendingTransaction = false; 8793 wtoken.mAppAnimator.animation = null; 8794 setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction); 8795 wtoken.updateReportedVisibilityLocked(); 8796 wtoken.waitingToHide = false; 8797 // Force the allDrawn flag, because we want to start 8798 // this guy's animations regardless of whether it's 8799 // gotten drawn. 8800 wtoken.allDrawn = true; 8801 wtoken.deferClearAllDrawn = false; 8802 } 8803 8804 boolean useAlternateThumbnailAnimation = true; 8805 AppWindowAnimator appAnimator = 8806 topOpeningApp == null ? null : topOpeningApp.mAppAnimator; 8807 Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail(); 8808 if (!useAlternateThumbnailAnimation && nextAppTransitionThumbnail != null 8809 && appAnimator != null && appAnimator.animation != null) { 8810 // This thumbnail animation is very special, we need to have 8811 // an extra surface with the thumbnail included with the animation. 8812 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(), 8813 nextAppTransitionThumbnail.getHeight()); 8814 try { 8815 // TODO(multi-display): support other displays 8816 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8817 final Display display = displayContent.getDisplay(); 8818 SurfaceControl surfaceControl = new SurfaceControl(mFxSession, 8819 "thumbnail anim", 8820 dirty.width(), dirty.height(), 8821 PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 8822 surfaceControl.setLayerStack(display.getLayerStack()); 8823 appAnimator.thumbnail = surfaceControl; 8824 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE"); 8825 Surface drawSurface = new Surface(); 8826 drawSurface.copyFrom(surfaceControl); 8827 Canvas c = drawSurface.lockCanvas(dirty); 8828 c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null); 8829 drawSurface.unlockCanvasAndPost(c); 8830 drawSurface.release(); 8831 appAnimator.thumbnailLayer = topOpeningLayer; 8832 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 8833 Animation anim = mAppTransition.createThumbnailScaleAnimationLocked( 8834 displayInfo.appWidth, displayInfo.appHeight, transit); 8835 appAnimator.thumbnailAnimation = anim; 8836 anim.restrictDuration(MAX_ANIMATION_DURATION); 8837 anim.scaleCurrentDuration(getTransitionAnimationScaleLocked()); 8838 Point p = new Point(); 8839 mAppTransition.getStartingPoint(p); 8840 appAnimator.thumbnailX = p.x; 8841 appAnimator.thumbnailY = p.y; 8842 } catch (OutOfResourcesException e) { 8843 Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width() 8844 + " h=" + dirty.height(), e); 8845 appAnimator.clearThumbnail(); 8846 } 8847 } 8848 8849 mAppTransition.postAnimationCallback(); 8850 mAppTransition.clear(); 8851 8852 mOpeningApps.clear(); 8853 mClosingApps.clear(); 8854 8855 // This has changed the visibility of windows, so perform 8856 // a new layout to get them all up-to-date. 8857 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT 8858 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 8859 getDefaultDisplayContentLocked().layoutNeeded = true; 8860 8861 // TODO(multidisplay): IMEs are only supported on the default display. 8862 if (windows == getDefaultWindowListLocked() 8863 && !moveInputMethodWindowsIfNeededLocked(true)) { 8864 assignLayersLocked(windows); 8865 } 8866 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/); 8867 mFocusMayChange = false; 8868 } 8869 8870 return changes; 8871 } 8872 8873 /** 8874 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8875 * @return bitmap indicating if another pass through layout must be made. 8876 */ 8877 private int handleAnimatingStoppedAndTransitionLocked() { 8878 int changes = 0; 8879 8880 mAppTransition.setIdle(); 8881 // Restore window app tokens to the ActivityManager views 8882 ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks(); 8883 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 8884 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8885 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 8886 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8887 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 8888 tokens.get(tokenNdx).sendingToBottom = false; 8889 } 8890 } 8891 } 8892 rebuildAppWindowListLocked(); 8893 8894 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8895 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 8896 "Wallpaper layer changed: assigning layers + relayout"); 8897 moveInputMethodWindowsIfNeededLocked(true); 8898 mInnerFields.mWallpaperMayChange = true; 8899 // Since the window list has been rebuilt, focus might 8900 // have to be recomputed since the actual order of windows 8901 // might have changed again. 8902 mFocusMayChange = true; 8903 8904 return changes; 8905 } 8906 8907 private void updateResizingWindows(final WindowState w) { 8908 final WindowStateAnimator winAnimator = w.mWinAnimator; 8909 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { 8910 w.setInsetsChanged(); 8911 boolean configChanged = w.isConfigChanged(); 8912 if (DEBUG_CONFIGURATION && configChanged) { 8913 Slog.v(TAG, "Win " + w + " config changed: " 8914 + mCurConfiguration); 8915 } 8916 if (localLOGV) Slog.v(TAG, "Resizing " + w 8917 + ": configChanged=" + configChanged 8918 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8919 w.mLastFrame.set(w.mFrame); 8920 if (w.mContentInsetsChanged 8921 || w.mVisibleInsetsChanged 8922 || winAnimator.mSurfaceResized 8923 || configChanged) { 8924 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8925 Slog.v(TAG, "Resize reasons for w=" + w + ": " 8926 + " contentInsetsChanged=" + w.mContentInsetsChanged 8927 + " " + w.mContentInsets.toShortString() 8928 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8929 + " " + w.mVisibleInsets.toShortString() 8930 + " surfaceResized=" + winAnimator.mSurfaceResized 8931 + " configChanged=" + configChanged); 8932 } 8933 8934 w.mLastOverscanInsets.set(w.mOverscanInsets); 8935 w.mLastContentInsets.set(w.mContentInsets); 8936 w.mLastVisibleInsets.set(w.mVisibleInsets); 8937 makeWindowFreezingScreenIfNeededLocked(w); 8938 // If the orientation is changing, then we need to 8939 // hold off on unfreezing the display until this 8940 // window has been redrawn; to do that, we need 8941 // to go through the process of getting informed 8942 // by the application when it has finished drawing. 8943 if (w.mOrientationChanging) { 8944 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 8945 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 8946 + w + ", surface " + winAnimator.mSurfaceControl); 8947 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 8948 if (w.mAppToken != null) { 8949 w.mAppToken.allDrawn = false; 8950 w.mAppToken.deferClearAllDrawn = false; 8951 } 8952 } 8953 if (!mResizingWindows.contains(w)) { 8954 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8955 "Resizing window " + w + " to " + winAnimator.mSurfaceW 8956 + "x" + winAnimator.mSurfaceH); 8957 mResizingWindows.add(w); 8958 } 8959 } else if (w.mOrientationChanging) { 8960 if (w.isDrawnLw()) { 8961 if (DEBUG_ORIENTATION) Slog.v(TAG, 8962 "Orientation not waiting for draw in " 8963 + w + ", surface " + winAnimator.mSurfaceControl); 8964 w.mOrientationChanging = false; 8965 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 8966 - mDisplayFreezeTime); 8967 } 8968 } 8969 } 8970 } 8971 8972 /** 8973 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8974 * 8975 * @param w WindowState this method is applied to. 8976 * @param currentTime The time which animations use for calculating transitions. 8977 * @param innerDw Width of app window. 8978 * @param innerDh Height of app window. 8979 */ 8980 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 8981 final int innerDw, final int innerDh) { 8982 final WindowManager.LayoutParams attrs = w.mAttrs; 8983 final int attrFlags = attrs.flags; 8984 final boolean canBeSeen = w.isDisplayedLw(); 8985 final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8986 8987 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8988 // This window completely covers everything behind it, 8989 // so we want to leave all of them as undimmed (for 8990 // performance reasons). 8991 mInnerFields.mObscured = true; 8992 } 8993 8994 if (w.mHasSurface) { 8995 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8996 mInnerFields.mHoldScreen = w.mSession; 8997 } 8998 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 8999 && mInnerFields.mScreenBrightness < 0) { 9000 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 9001 } 9002 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 9003 && mInnerFields.mButtonBrightness < 0) { 9004 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 9005 } 9006 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0 9007 && mInnerFields.mUserActivityTimeout < 0) { 9008 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout; 9009 } 9010 9011 final int type = attrs.type; 9012 if (canBeSeen 9013 && (type == TYPE_SYSTEM_DIALOG 9014 || type == TYPE_RECENTS_OVERLAY 9015 || type == TYPE_SYSTEM_ERROR 9016 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) { 9017 mInnerFields.mSyswin = true; 9018 } 9019 9020 if (canBeSeen) { 9021 // This function assumes that the contents of the default display are 9022 // processed first before secondary displays. 9023 final DisplayContent displayContent = w.getDisplayContent(); 9024 if (displayContent != null && displayContent.isDefaultDisplay) { 9025 // While a dream or keyguard is showing, obscure ordinary application 9026 // content on secondary displays (by forcibly enabling mirroring unless 9027 // there is other content we want to show) but still allow opaque 9028 // keyguard dialogs to be shown. 9029 if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 9030 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true; 9031 } 9032 mInnerFields.mDisplayHasContent = true; 9033 } else if (displayContent != null && 9034 (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays 9035 || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) { 9036 // Allow full screen keyguard presentation dialogs to be seen. 9037 mInnerFields.mDisplayHasContent = true; 9038 } 9039 } 9040 } 9041 } 9042 9043 private void handleFlagDimBehind(WindowState w) { 9044 final WindowManager.LayoutParams attrs = w.mAttrs; 9045 if ((attrs.flags & FLAG_DIM_BEHIND) != 0 9046 && w.isDisplayedLw() 9047 && !w.mExiting) { 9048 final WindowStateAnimator winAnimator = w.mWinAnimator; 9049 final TaskStack stack = w.getStack(); 9050 stack.setDimmingTag(); 9051 if (!stack.isDimming(winAnimator)) { 9052 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming."); 9053 stack.startDimmingIfNeeded(winAnimator); 9054 } 9055 } 9056 } 9057 9058 private void updateAllDrawnLocked(DisplayContent displayContent) { 9059 // See if any windows have been drawn, so they (and others 9060 // associated with them) can now be shown. 9061 ArrayList<TaskStack> stacks = displayContent.getStacks(); 9062 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 9063 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9064 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9065 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9066 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9067 final AppWindowToken wtoken = tokens.get(tokenNdx); 9068 if (!wtoken.allDrawn) { 9069 int numInteresting = wtoken.numInterestingWindows; 9070 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 9071 if (DEBUG_VISIBILITY) Slog.v(TAG, 9072 "allDrawn: " + wtoken 9073 + " interesting=" + numInteresting 9074 + " drawn=" + wtoken.numDrawnWindows); 9075 wtoken.allDrawn = true; 9076 mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget(); 9077 } 9078 } 9079 } 9080 } 9081 } 9082 } 9083 9084 // "Something has changed! Let's make it correct now." 9085 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 9086 if (DEBUG_WINDOW_TRACE) { 9087 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 9088 + Debug.getCallers(3)); 9089 } 9090 9091 final long currentTime = SystemClock.uptimeMillis(); 9092 9093 int i; 9094 9095 if (mFocusMayChange) { 9096 mFocusMayChange = false; 9097 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 9098 false /*updateInputWindows*/); 9099 } 9100 9101 // Initialize state of exiting tokens. 9102 final int numDisplays = mDisplayContents.size(); 9103 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9104 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9105 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) { 9106 displayContent.mExitingTokens.get(i).hasVisible = false; 9107 } 9108 } 9109 9110 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9111 // Initialize state of exiting applications. 9112 final AppTokenList exitingAppTokens = 9113 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9114 for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9115 exitingAppTokens.get(tokenNdx).hasVisible = false; 9116 } 9117 } 9118 9119 mInnerFields.mHoldScreen = null; 9120 mInnerFields.mScreenBrightness = -1; 9121 mInnerFields.mButtonBrightness = -1; 9122 mInnerFields.mUserActivityTimeout = -1; 9123 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false; 9124 9125 mTransactionSequence++; 9126 9127 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked(); 9128 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 9129 final int defaultDw = defaultInfo.logicalWidth; 9130 final int defaultDh = defaultInfo.logicalHeight; 9131 9132 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9133 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 9134 SurfaceControl.openTransaction(); 9135 try { 9136 9137 if (mWatermark != null) { 9138 mWatermark.positionSurface(defaultDw, defaultDh); 9139 } 9140 if (mStrictModeFlash != null) { 9141 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 9142 } 9143 if (mCircularDisplayMask != null) { 9144 mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation); 9145 } 9146 9147 boolean focusDisplayed = false; 9148 9149 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9150 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9151 boolean updateAllDrawn = false; 9152 WindowList windows = displayContent.getWindowList(); 9153 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9154 final int displayId = displayContent.getDisplayId(); 9155 final int dw = displayInfo.logicalWidth; 9156 final int dh = displayInfo.logicalHeight; 9157 final int innerDw = displayInfo.appWidth; 9158 final int innerDh = displayInfo.appHeight; 9159 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 9160 9161 // Reset for each display. 9162 mInnerFields.mDisplayHasContent = false; 9163 9164 int repeats = 0; 9165 do { 9166 repeats++; 9167 if (repeats > 6) { 9168 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 9169 displayContent.layoutNeeded = false; 9170 break; 9171 } 9172 9173 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 9174 displayContent.pendingLayoutChanges); 9175 9176 if ((displayContent.pendingLayoutChanges & 9177 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 && 9178 (adjustWallpaperWindowsLocked() & 9179 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 9180 assignLayersLocked(windows); 9181 displayContent.layoutNeeded = true; 9182 } 9183 9184 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 9185 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 9186 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 9187 if (updateOrientationFromAppTokensLocked(true)) { 9188 displayContent.layoutNeeded = true; 9189 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9190 } 9191 } 9192 9193 if ((displayContent.pendingLayoutChanges 9194 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9195 displayContent.layoutNeeded = true; 9196 } 9197 9198 // FIRST LOOP: Perform a layout, if needed. 9199 if (repeats < 4) { 9200 performLayoutLockedInner(displayContent, repeats == 1, 9201 false /*updateInputWindows*/); 9202 } else { 9203 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 9204 } 9205 9206 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 9207 // it is animating. 9208 displayContent.pendingLayoutChanges = 0; 9209 9210 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 9211 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 9212 9213 if (isDefaultDisplay) { 9214 mPolicy.beginPostLayoutPolicyLw(dw, dh); 9215 for (i = windows.size() - 1; i >= 0; i--) { 9216 WindowState w = windows.get(i); 9217 if (w.mHasSurface) { 9218 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); 9219 } 9220 } 9221 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 9222 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 9223 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges); 9224 } 9225 } while (displayContent.pendingLayoutChanges != 0); 9226 9227 mInnerFields.mObscured = false; 9228 mInnerFields.mSyswin = false; 9229 displayContent.resetDimming(); 9230 9231 // Only used if default window 9232 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 9233 9234 final int N = windows.size(); 9235 for (i=N-1; i>=0; i--) { 9236 WindowState w = windows.get(i); 9237 final TaskStack stack = w.getStack(); 9238 if (stack == null) { 9239 continue; 9240 } 9241 9242 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 9243 9244 // Update effect. 9245 w.mObscured = mInnerFields.mObscured; 9246 if (!mInnerFields.mObscured) { 9247 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 9248 } 9249 9250 if (!stack.testDimmingTag()) { 9251 handleFlagDimBehind(w); 9252 } 9253 9254 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 9255 && w.isVisibleLw()) { 9256 // This is the wallpaper target and its obscured state 9257 // changed... make sure the current wallaper's visibility 9258 // has been updated accordingly. 9259 updateWallpaperVisibilityLocked(); 9260 } 9261 9262 final WindowStateAnimator winAnimator = w.mWinAnimator; 9263 9264 // If the window has moved due to its containing 9265 // content frame changing, then we'd like to animate 9266 // it. 9267 if (w.mHasSurface && w.shouldAnimateMove()) { 9268 // Frame has moved, containing content frame 9269 // has also moved, and we're not currently animating... 9270 // let's do something. 9271 Animation a = AnimationUtils.loadAnimation(mContext, 9272 com.android.internal.R.anim.window_move_from_decor); 9273 winAnimator.setAnimation(a); 9274 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 9275 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 9276 try { 9277 w.mClient.moved(w.mFrame.left, w.mFrame.top); 9278 } catch (RemoteException e) { 9279 } 9280 } 9281 9282 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 9283 w.mContentChanged = false; 9284 9285 // Moved from updateWindowsAndWallpaperLocked(). 9286 if (w.mHasSurface) { 9287 // Take care of the window being ready to display. 9288 final boolean committed = 9289 winAnimator.commitFinishDrawingLocked(currentTime); 9290 if (isDefaultDisplay && committed) { 9291 if (w.mAttrs.type == TYPE_DREAM) { 9292 // HACK: When a dream is shown, it may at that 9293 // point hide the lock screen. So we need to 9294 // redo the layout to let the phone window manager 9295 // make this happen. 9296 displayContent.pendingLayoutChanges |= 9297 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9298 if (DEBUG_LAYOUT_REPEATS) { 9299 debugLayoutRepeats( 9300 "dream and commitFinishDrawingLocked true", 9301 displayContent.pendingLayoutChanges); 9302 } 9303 } 9304 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 9305 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 9306 "First draw done in potential wallpaper target " + w); 9307 mInnerFields.mWallpaperMayChange = true; 9308 displayContent.pendingLayoutChanges |= 9309 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9310 if (DEBUG_LAYOUT_REPEATS) { 9311 debugLayoutRepeats( 9312 "wallpaper and commitFinishDrawingLocked true", 9313 displayContent.pendingLayoutChanges); 9314 } 9315 } 9316 } 9317 9318 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 9319 9320 final AppWindowToken atoken = w.mAppToken; 9321 if (DEBUG_STARTING_WINDOW && atoken != null 9322 && w == atoken.startingWindow) { 9323 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 9324 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 9325 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 9326 } 9327 if (atoken != null 9328 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 9329 if (atoken.lastTransactionSequence != mTransactionSequence) { 9330 atoken.lastTransactionSequence = mTransactionSequence; 9331 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 9332 atoken.startingDisplayed = false; 9333 } 9334 if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 9335 && !w.mExiting && !w.mDestroying) { 9336 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 9337 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 9338 + ", isAnimating=" + winAnimator.isAnimating()); 9339 if (!w.isDrawnLw()) { 9340 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl 9341 + " pv=" + w.mPolicyVisibility 9342 + " mDrawState=" + winAnimator.mDrawState 9343 + " ah=" + w.mAttachedHidden 9344 + " th=" + atoken.hiddenRequested 9345 + " a=" + winAnimator.mAnimating); 9346 } 9347 } 9348 if (w != atoken.startingWindow) { 9349 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 9350 atoken.numInterestingWindows++; 9351 if (w.isDrawnLw()) { 9352 atoken.numDrawnWindows++; 9353 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 9354 "tokenMayBeDrawn: " + atoken 9355 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 9356 + " mAppFreezing=" + w.mAppFreezing); 9357 updateAllDrawn = true; 9358 } 9359 } 9360 } else if (w.isDrawnLw()) { 9361 atoken.startingDisplayed = true; 9362 } 9363 } 9364 } 9365 } 9366 9367 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 9368 && w.isDisplayedLw()) { 9369 focusDisplayed = true; 9370 } 9371 9372 updateResizingWindows(w); 9373 } 9374 9375 mDisplayManagerInternal.setDisplayHasContent(displayId, 9376 mInnerFields.mDisplayHasContent, 9377 true /* inTraversal, must call performTraversalInTrans... below */); 9378 9379 getDisplayContentLocked(displayId).stopDimmingIfNeeded(); 9380 9381 if (updateAllDrawn) { 9382 updateAllDrawnLocked(displayContent); 9383 } 9384 } 9385 9386 if (focusDisplayed) { 9387 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 9388 } 9389 9390 // Give the display manager a chance to adjust properties 9391 // like display rotation if it needs to. 9392 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 9393 9394 } catch (RuntimeException e) { 9395 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 9396 } finally { 9397 SurfaceControl.closeTransaction(); 9398 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9399 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 9400 } 9401 9402 final WindowList defaultWindows = defaultDisplay.getWindowList(); 9403 9404 // If we are ready to perform an app transition, check through 9405 // all of the app tokens to be shown and see if they are ready 9406 // to go. 9407 if (mAppTransition.isReady()) { 9408 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 9409 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 9410 defaultDisplay.pendingLayoutChanges); 9411 } 9412 9413 if (!mAnimator.mAnimating && mAppTransition.isRunning()) { 9414 // We have finished the animation of an app transition. To do 9415 // this, we have delayed a lot of operations like showing and 9416 // hiding apps, moving apps in Z-order, etc. The app token list 9417 // reflects the correct Z-order, but the window list may now 9418 // be out of sync with it. So here we will just rebuild the 9419 // entire app window list. Fun! 9420 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 9421 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 9422 defaultDisplay.pendingLayoutChanges); 9423 } 9424 9425 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 9426 && !mAppTransition.isReady()) { 9427 // At this point, there was a window with a wallpaper that 9428 // was force hiding other windows behind it, but now it 9429 // is going away. This may be simple -- just animate 9430 // away the wallpaper and its window -- or it may be 9431 // hard -- the wallpaper now needs to be shown behind 9432 // something that was hidden. 9433 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9434 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 9435 defaultDisplay.pendingLayoutChanges); 9436 } 9437 mInnerFields.mWallpaperForceHidingChanged = false; 9438 9439 if (mInnerFields.mWallpaperMayChange) { 9440 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting"); 9441 defaultDisplay.pendingLayoutChanges |= 9442 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9443 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange", 9444 defaultDisplay.pendingLayoutChanges); 9445 } 9446 9447 if (mFocusMayChange) { 9448 mFocusMayChange = false; 9449 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 9450 false /*updateInputWindows*/)) { 9451 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 9452 } 9453 } 9454 9455 if (needsLayout()) { 9456 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9457 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 9458 defaultDisplay.pendingLayoutChanges); 9459 } 9460 9461 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 9462 WindowState win = mResizingWindows.get(i); 9463 if (win.mAppFreezing) { 9464 // Don't remove this window until rotation has completed. 9465 continue; 9466 } 9467 win.reportResized(); 9468 mResizingWindows.remove(i); 9469 } 9470 9471 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 9472 "With display frozen, orientationChangeComplete=" 9473 + mInnerFields.mOrientationChangeComplete); 9474 if (mInnerFields.mOrientationChangeComplete) { 9475 if (mWindowsFreezingScreen) { 9476 mWindowsFreezingScreen = false; 9477 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource; 9478 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9479 } 9480 stopFreezingDisplayLocked(); 9481 } 9482 9483 // Destroy the surface of any windows that are no longer visible. 9484 boolean wallpaperDestroyed = false; 9485 i = mDestroySurface.size(); 9486 if (i > 0) { 9487 do { 9488 i--; 9489 WindowState win = mDestroySurface.get(i); 9490 win.mDestroying = false; 9491 if (mInputMethodWindow == win) { 9492 mInputMethodWindow = null; 9493 } 9494 if (win == mWallpaperTarget) { 9495 wallpaperDestroyed = true; 9496 } 9497 win.mWinAnimator.destroySurfaceLocked(); 9498 } while (i > 0); 9499 mDestroySurface.clear(); 9500 } 9501 9502 // Time to remove any exiting tokens? 9503 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9504 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9505 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens; 9506 for (i = exitingTokens.size() - 1; i >= 0; i--) { 9507 WindowToken token = exitingTokens.get(i); 9508 if (!token.hasVisible) { 9509 exitingTokens.remove(i); 9510 if (token.windowType == TYPE_WALLPAPER) { 9511 mWallpaperTokens.remove(token); 9512 } 9513 } 9514 } 9515 } 9516 9517 // Time to remove any exiting applications? 9518 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9519 // Initialize state of exiting applications. 9520 final AppTokenList exitingAppTokens = 9521 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9522 for (i = exitingAppTokens.size() - 1; i >= 0; i--) { 9523 AppWindowToken token = exitingAppTokens.get(i); 9524 if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) { 9525 // Make sure there is no animation running on this token, 9526 // so any windows associated with it will be removed as 9527 // soon as their animations are complete 9528 token.mAppAnimator.clearAnimation(); 9529 token.mAppAnimator.animating = false; 9530 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 9531 "performLayout: App token exiting now removed" + token); 9532 removeAppFromTaskLocked(token); 9533 exitingAppTokens.remove(i); 9534 } 9535 } 9536 } 9537 9538 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 9539 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 9540 try { 9541 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 9542 } catch (RemoteException e) { 9543 } 9544 } 9545 mRelayoutWhileAnimating.clear(); 9546 } 9547 9548 if (wallpaperDestroyed) { 9549 defaultDisplay.pendingLayoutChanges |= 9550 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9551 defaultDisplay.layoutNeeded = true; 9552 } 9553 9554 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9555 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9556 if (displayContent.pendingLayoutChanges != 0) { 9557 displayContent.layoutNeeded = true; 9558 } 9559 } 9560 9561 // Finally update all input windows now that the window changes have stabilized. 9562 mInputMonitor.updateInputWindowsLw(true /*force*/); 9563 9564 setHoldScreenLocked(mInnerFields.mHoldScreen); 9565 if (!mDisplayFrozen) { 9566 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 9567 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1); 9568 } else { 9569 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager( 9570 toBrightnessOverride(mInnerFields.mScreenBrightness)); 9571 } 9572 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 9573 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1); 9574 } else { 9575 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager( 9576 toBrightnessOverride(mInnerFields.mButtonBrightness)); 9577 } 9578 mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager( 9579 mInnerFields.mUserActivityTimeout); 9580 } 9581 9582 if (mTurnOnScreen) { 9583 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 9584 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 9585 mTurnOnScreen = false; 9586 } 9587 9588 if (mInnerFields.mUpdateRotation) { 9589 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9590 if (updateRotationUncheckedLocked(false)) { 9591 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9592 } else { 9593 mInnerFields.mUpdateRotation = false; 9594 } 9595 } 9596 9597 if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded 9598 && !mInnerFields.mUpdateRotation) { 9599 checkDrawnWindowsLocked(); 9600 } 9601 9602 final int N = mPendingRemove.size(); 9603 if (N > 0) { 9604 if (mPendingRemoveTmp.length < N) { 9605 mPendingRemoveTmp = new WindowState[N+10]; 9606 } 9607 mPendingRemove.toArray(mPendingRemoveTmp); 9608 mPendingRemove.clear(); 9609 DisplayContentList displayList = new DisplayContentList(); 9610 for (i = 0; i < N; i++) { 9611 WindowState w = mPendingRemoveTmp[i]; 9612 removeWindowInnerLocked(w.mSession, w); 9613 final DisplayContent displayContent = w.getDisplayContent(); 9614 if (displayContent != null && !displayList.contains(displayContent)) { 9615 displayList.add(displayContent); 9616 } 9617 } 9618 9619 for (DisplayContent displayContent : displayList) { 9620 assignLayersLocked(displayContent.getWindowList()); 9621 displayContent.layoutNeeded = true; 9622 } 9623 } 9624 9625 // Remove all deferred displays stacks, tasks, and activities. 9626 for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) { 9627 mDisplayContents.valueAt(displayNdx).checkForDeferredActions(); 9628 } 9629 9630 setFocusedStackFrame(); 9631 9632 // Check to see if we are now in a state where the screen should 9633 // be enabled, because the window obscured flags have changed. 9634 enableScreenIfNeededLocked(); 9635 9636 scheduleAnimationLocked(); 9637 9638 if (DEBUG_WINDOW_TRACE) { 9639 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" 9640 + mAnimator.mAnimating); 9641 } 9642 } 9643 9644 private int toBrightnessOverride(float value) { 9645 return (int)(value * PowerManager.BRIGHTNESS_ON); 9646 } 9647 9648 void checkDrawnWindowsLocked() { 9649 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { 9650 return; 9651 } 9652 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { 9653 WindowState win = mWaitingForDrawn.get(j); 9654 if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win + 9655 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() + 9656 " mHasSurface=" + win.mHasSurface + 9657 " drawState=" + win.mWinAnimator.mDrawState); 9658 if (win.mRemoved || !win.mHasSurface) { 9659 // Window has been removed; no draw will now happen, so stop waiting. 9660 if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win); 9661 mWaitingForDrawn.remove(win); 9662 } else if (win.hasDrawnLw()) { 9663 // Window is now drawn (and shown). 9664 if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win); 9665 mWaitingForDrawn.remove(win); 9666 } 9667 } 9668 if (mWaitingForDrawn.isEmpty()) { 9669 if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!"); 9670 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 9671 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); 9672 } 9673 } 9674 9675 void setHoldScreenLocked(final Session newHoldScreen) { 9676 final boolean hold = newHoldScreen != null; 9677 9678 if (hold && mHoldingScreenOn != newHoldScreen) { 9679 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 9680 } 9681 mHoldingScreenOn = newHoldScreen; 9682 9683 final boolean state = mHoldingScreenWakeLock.isHeld(); 9684 if (hold != state) { 9685 if (hold) { 9686 mHoldingScreenWakeLock.acquire(); 9687 mPolicy.keepScreenOnStartedLw(); 9688 } else { 9689 mPolicy.keepScreenOnStoppedLw(); 9690 mHoldingScreenWakeLock.release(); 9691 } 9692 } 9693 } 9694 9695 void requestTraversal() { 9696 synchronized (mWindowMap) { 9697 requestTraversalLocked(); 9698 } 9699 } 9700 9701 void requestTraversalLocked() { 9702 if (!mTraversalScheduled) { 9703 mTraversalScheduled = true; 9704 mH.sendEmptyMessage(H.DO_TRAVERSAL); 9705 } 9706 } 9707 9708 /** Note that Locked in this case is on mLayoutToAnim */ 9709 void scheduleAnimationLocked() { 9710 if (!mAnimationScheduled) { 9711 mAnimationScheduled = true; 9712 mChoreographer.postCallback( 9713 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 9714 } 9715 } 9716 9717 private boolean needsLayout() { 9718 final int numDisplays = mDisplayContents.size(); 9719 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9720 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9721 if (displayContent.layoutNeeded) { 9722 return true; 9723 } 9724 } 9725 return false; 9726 } 9727 9728 boolean copyAnimToLayoutParamsLocked() { 9729 boolean doRequest = false; 9730 9731 final int bulkUpdateParams = mAnimator.mBulkUpdateParams; 9732 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 9733 mInnerFields.mUpdateRotation = true; 9734 doRequest = true; 9735 } 9736 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 9737 mInnerFields.mWallpaperMayChange = true; 9738 doRequest = true; 9739 } 9740 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 9741 mInnerFields.mWallpaperForceHidingChanged = true; 9742 doRequest = true; 9743 } 9744 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 9745 mInnerFields.mOrientationChangeComplete = false; 9746 } else { 9747 mInnerFields.mOrientationChangeComplete = true; 9748 mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource; 9749 if (mWindowsFreezingScreen) { 9750 doRequest = true; 9751 } 9752 } 9753 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 9754 mTurnOnScreen = true; 9755 } 9756 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) { 9757 mInnerFields.mWallpaperActionPending = true; 9758 } 9759 9760 return doRequest; 9761 } 9762 9763 /** If a window that has an animation specifying a colored background and the current wallpaper 9764 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 9765 * suddenly disappear. */ 9766 int adjustAnimationBackground(WindowStateAnimator winAnimator) { 9767 WindowList windows = winAnimator.mWin.getWindowList(); 9768 for (int i = windows.size() - 1; i >= 0; --i) { 9769 WindowState testWin = windows.get(i); 9770 if (testWin.mIsWallpaper && testWin.isVisibleNow()) { 9771 return testWin.mWinAnimator.mAnimLayer; 9772 } 9773 } 9774 return winAnimator.mAnimLayer; 9775 } 9776 9777 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9778 boolean secure) { 9779 final SurfaceControl surface = winAnimator.mSurfaceControl; 9780 boolean leakedSurface = false; 9781 boolean killedApps = false; 9782 9783 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9784 winAnimator.mSession.mPid, operation); 9785 9786 if (mForceRemoves == null) { 9787 mForceRemoves = new ArrayList<WindowState>(); 9788 } 9789 9790 long callingIdentity = Binder.clearCallingIdentity(); 9791 try { 9792 // There was some problem... first, do a sanity check of the 9793 // window list to make sure we haven't left any dangling surfaces 9794 // around. 9795 9796 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 9797 final int numDisplays = mDisplayContents.size(); 9798 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9799 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9800 final int numWindows = windows.size(); 9801 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9802 final WindowState ws = windows.get(winNdx); 9803 WindowStateAnimator wsa = ws.mWinAnimator; 9804 if (wsa.mSurfaceControl != null) { 9805 if (!mSessions.contains(wsa.mSession)) { 9806 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 9807 + ws + " surface=" + wsa.mSurfaceControl 9808 + " token=" + ws.mToken 9809 + " pid=" + ws.mSession.mPid 9810 + " uid=" + ws.mSession.mUid); 9811 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9812 wsa.mSurfaceControl.destroy(); 9813 wsa.mSurfaceShown = false; 9814 wsa.mSurfaceControl = null; 9815 ws.mHasSurface = false; 9816 mForceRemoves.add(ws); 9817 leakedSurface = true; 9818 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9819 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 9820 + ws + " surface=" + wsa.mSurfaceControl 9821 + " token=" + ws.mAppToken); 9822 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9823 wsa.mSurfaceControl.destroy(); 9824 wsa.mSurfaceShown = false; 9825 wsa.mSurfaceControl = null; 9826 ws.mHasSurface = false; 9827 leakedSurface = true; 9828 } 9829 } 9830 } 9831 } 9832 9833 if (!leakedSurface) { 9834 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 9835 SparseIntArray pidCandidates = new SparseIntArray(); 9836 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9837 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9838 final int numWindows = windows.size(); 9839 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9840 final WindowState ws = windows.get(winNdx); 9841 if (mForceRemoves.contains(ws)) { 9842 continue; 9843 } 9844 WindowStateAnimator wsa = ws.mWinAnimator; 9845 if (wsa.mSurfaceControl != null) { 9846 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9847 } 9848 } 9849 if (pidCandidates.size() > 0) { 9850 int[] pids = new int[pidCandidates.size()]; 9851 for (int i=0; i<pids.length; i++) { 9852 pids[i] = pidCandidates.keyAt(i); 9853 } 9854 try { 9855 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9856 killedApps = true; 9857 } 9858 } catch (RemoteException e) { 9859 } 9860 } 9861 } 9862 } 9863 9864 if (leakedSurface || killedApps) { 9865 // We managed to reclaim some memory, so get rid of the trouble 9866 // surface and ask the app to request another one. 9867 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 9868 if (surface != null) { 9869 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9870 "RECOVER DESTROY", null); 9871 surface.destroy(); 9872 winAnimator.mSurfaceShown = false; 9873 winAnimator.mSurfaceControl = null; 9874 winAnimator.mWin.mHasSurface = false; 9875 scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken); 9876 } 9877 9878 try { 9879 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9880 } catch (RemoteException e) { 9881 } 9882 } 9883 } finally { 9884 Binder.restoreCallingIdentity(callingIdentity); 9885 } 9886 9887 return leakedSurface || killedApps; 9888 } 9889 9890 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9891 WindowState newFocus = computeFocusedWindowLocked(); 9892 if (mCurrentFocus != newFocus) { 9893 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9894 // This check makes sure that we don't already have the focus 9895 // change message pending. 9896 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9897 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9898 // TODO(multidisplay): Focused windows on default display only. 9899 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9900 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked( 9901 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 9902 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES); 9903 if (imWindowChanged) { 9904 displayContent.layoutNeeded = true; 9905 newFocus = computeFocusedWindowLocked(); 9906 } 9907 9908 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " + 9909 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 9910 final WindowState oldFocus = mCurrentFocus; 9911 mCurrentFocus = newFocus; 9912 mLosingFocus.remove(newFocus); 9913 9914 if (mAccessibilityController != null) { 9915 mAccessibilityController.onWindowFocusChangedLocked(); 9916 } 9917 9918 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9919 9920 if (imWindowChanged && oldFocus != mInputMethodWindow) { 9921 // Focus of the input method window changed. Perform layout if needed. 9922 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9923 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9924 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9925 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9926 // Client will do the layout, but we need to assign layers 9927 // for handleNewWindowLocked() below. 9928 assignLayersLocked(displayContent.getWindowList()); 9929 } 9930 } 9931 9932 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9933 // The change in focus caused us to need to do a layout. Okay. 9934 displayContent.layoutNeeded = true; 9935 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9936 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9937 } 9938 } 9939 9940 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9941 // If we defer assigning layers, then the caller is responsible for 9942 // doing this part. 9943 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 9944 } 9945 9946 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9947 return true; 9948 } 9949 return false; 9950 } 9951 9952 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 9953 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9954 } 9955 9956 private WindowState computeFocusedWindowLocked() { 9957 if (mAnimator.mUniverseBackground != null 9958 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 9959 return mAnimator.mUniverseBackground.mWin; 9960 } 9961 9962 final int displayCount = mDisplayContents.size(); 9963 for (int i = 0; i < displayCount; i++) { 9964 final DisplayContent displayContent = mDisplayContents.valueAt(i); 9965 WindowState win = findFocusedWindowLocked(displayContent); 9966 if (win != null) { 9967 return win; 9968 } 9969 } 9970 return null; 9971 } 9972 9973 private WindowState findFocusedWindowLocked(DisplayContent displayContent) { 9974 final WindowList windows = displayContent.getWindowList(); 9975 for (int i = windows.size() - 1; i >= 0; i--) { 9976 final WindowState win = windows.get(i); 9977 9978 if (localLOGV || DEBUG_FOCUS) Slog.v( 9979 TAG, "Looking for focus: " + i 9980 + " = " + win 9981 + ", flags=" + win.mAttrs.flags 9982 + ", canReceive=" + win.canReceiveKeys()); 9983 9984 AppWindowToken wtoken = win.mAppToken; 9985 9986 // If this window's application has been removed, just skip it. 9987 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 9988 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because " 9989 + (wtoken.removed ? "removed" : "sendingToBottom")); 9990 continue; 9991 } 9992 9993 if (!win.canReceiveKeys()) { 9994 continue; 9995 } 9996 9997 // Descend through all of the app tokens and find the first that either matches 9998 // win.mAppToken (return win) or mFocusedApp (return null). 9999 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && 10000 mFocusedApp != null) { 10001 ArrayList<Task> tasks = displayContent.getTasks(); 10002 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 10003 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 10004 int tokenNdx = tokens.size() - 1; 10005 for ( ; tokenNdx >= 0; --tokenNdx) { 10006 final AppWindowToken token = tokens.get(tokenNdx); 10007 if (wtoken == token) { 10008 break; 10009 } 10010 if (mFocusedApp == token) { 10011 // Whoops, we are below the focused app... no focus for you! 10012 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG, 10013 "findFocusedWindow: Reached focused app=" + mFocusedApp); 10014 return null; 10015 } 10016 } 10017 if (tokenNdx >= 0) { 10018 // Early exit from loop, must have found the matching token. 10019 break; 10020 } 10021 } 10022 } 10023 10024 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i + 10025 " = " + win); 10026 return win; 10027 } 10028 10029 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows."); 10030 return null; 10031 } 10032 10033 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 10034 if (mDisplayFrozen) { 10035 return; 10036 } 10037 10038 if (!mDisplayReady || !mPolicy.isScreenOnFully()) { 10039 // No need to freeze the screen before the system is ready or if 10040 // the screen is off. 10041 return; 10042 } 10043 10044 mScreenFrozenLock.acquire(); 10045 10046 mDisplayFrozen = true; 10047 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 10048 mLastFinishedFreezeSource = null; 10049 10050 mInputMonitor.freezeInputDispatchingLw(); 10051 10052 // Clear the last input window -- that is just used for 10053 // clean transitions between IMEs, and if we are freezing 10054 // the screen then the whole world is changing behind the scenes. 10055 mPolicy.setLastInputMethodWindowLw(null, null); 10056 10057 if (mAppTransition.isTransitionSet()) { 10058 mAppTransition.freeze(); 10059 } 10060 10061 if (PROFILE_ORIENTATION) { 10062 File file = new File("/data/system/frozen"); 10063 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 10064 } 10065 10066 if (CUSTOM_SCREEN_ROTATION) { 10067 mExitAnimId = exitAnim; 10068 mEnterAnimId = enterAnim; 10069 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10070 final int displayId = displayContent.getDisplayId(); 10071 ScreenRotationAnimation screenRotationAnimation = 10072 mAnimator.getScreenRotationAnimationLocked(displayId); 10073 if (screenRotationAnimation != null) { 10074 screenRotationAnimation.kill(); 10075 } 10076 10077 // Check whether the current screen contains any secure content. 10078 boolean isSecure = false; 10079 final WindowList windows = getDefaultWindowListLocked(); 10080 final int N = windows.size(); 10081 for (int i = 0; i < N; i++) { 10082 WindowState ws = windows.get(i); 10083 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) { 10084 isSecure = true; 10085 break; 10086 } 10087 } 10088 10089 // TODO(multidisplay): rotation on main screen only. 10090 displayContent.updateDisplayInfo(); 10091 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 10092 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure); 10093 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10094 } 10095 } 10096 10097 private void stopFreezingDisplayLocked() { 10098 if (!mDisplayFrozen) { 10099 return; 10100 } 10101 10102 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen 10103 || mClientFreezingScreen) { 10104 if (DEBUG_ORIENTATION) Slog.d(TAG, 10105 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 10106 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 10107 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 10108 + ", mClientFreezingScreen=" + mClientFreezingScreen); 10109 return; 10110 } 10111 10112 mDisplayFrozen = false; 10113 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 10114 StringBuilder sb = new StringBuilder(128); 10115 sb.append("Screen frozen for "); 10116 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 10117 if (mLastFinishedFreezeSource != null) { 10118 sb.append(" due to "); 10119 sb.append(mLastFinishedFreezeSource); 10120 } 10121 Slog.i(TAG, sb.toString()); 10122 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 10123 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 10124 if (PROFILE_ORIENTATION) { 10125 Debug.stopMethodTracing(); 10126 } 10127 10128 boolean updateRotation = false; 10129 10130 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10131 final int displayId = displayContent.getDisplayId(); 10132 ScreenRotationAnimation screenRotationAnimation = 10133 mAnimator.getScreenRotationAnimationLocked(displayId); 10134 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 10135 && screenRotationAnimation.hasScreenshot()) { 10136 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 10137 // TODO(multidisplay): rotation on main screen only. 10138 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10139 // Get rotation animation again, with new top window 10140 boolean isDimming = displayContent.isDimming(); 10141 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 10142 mExitAnimId = mEnterAnimId = 0; 10143 } 10144 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 10145 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, 10146 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 10147 scheduleAnimationLocked(); 10148 } else { 10149 screenRotationAnimation.kill(); 10150 screenRotationAnimation = null; 10151 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10152 updateRotation = true; 10153 } 10154 } else { 10155 if (screenRotationAnimation != null) { 10156 screenRotationAnimation.kill(); 10157 screenRotationAnimation = null; 10158 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10159 } 10160 updateRotation = true; 10161 } 10162 10163 mInputMonitor.thawInputDispatchingLw(); 10164 10165 boolean configChanged; 10166 10167 // While the display is frozen we don't re-compute the orientation 10168 // to avoid inconsistent states. However, something interesting 10169 // could have actually changed during that time so re-evaluate it 10170 // now to catch that. 10171 configChanged = updateOrientationFromAppTokensLocked(false); 10172 10173 // A little kludge: a lot could have happened while the 10174 // display was frozen, so now that we are coming back we 10175 // do a gc so that any remote references the system 10176 // processes holds on others can be released if they are 10177 // no longer needed. 10178 mH.removeMessages(H.FORCE_GC); 10179 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 10180 10181 mScreenFrozenLock.release(); 10182 10183 if (updateRotation) { 10184 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 10185 configChanged |= updateRotationUncheckedLocked(false); 10186 } 10187 10188 if (configChanged) { 10189 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10190 } 10191 } 10192 10193 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 10194 DisplayMetrics dm) { 10195 if (index < tokens.length) { 10196 String str = tokens[index]; 10197 if (str != null && str.length() > 0) { 10198 try { 10199 int val = Integer.parseInt(str); 10200 return val; 10201 } catch (Exception e) { 10202 } 10203 } 10204 } 10205 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 10206 return defDps; 10207 } 10208 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 10209 return val; 10210 } 10211 10212 void createWatermarkInTransaction() { 10213 if (mWatermark != null) { 10214 return; 10215 } 10216 10217 File file = new File("/system/etc/setup.conf"); 10218 FileInputStream in = null; 10219 DataInputStream ind = null; 10220 try { 10221 in = new FileInputStream(file); 10222 ind = new DataInputStream(in); 10223 String line = ind.readLine(); 10224 if (line != null) { 10225 String[] toks = line.split("%"); 10226 if (toks != null && toks.length > 0) { 10227 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 10228 mRealDisplayMetrics, mFxSession, toks); 10229 } 10230 } 10231 } catch (FileNotFoundException e) { 10232 } catch (IOException e) { 10233 } finally { 10234 if (ind != null) { 10235 try { 10236 ind.close(); 10237 } catch (IOException e) { 10238 } 10239 } else if (in != null) { 10240 try { 10241 in.close(); 10242 } catch (IOException e) { 10243 } 10244 } 10245 } 10246 } 10247 10248 @Override 10249 public void statusBarVisibilityChanged(int visibility) { 10250 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10251 != PackageManager.PERMISSION_GRANTED) { 10252 throw new SecurityException("Caller does not hold permission " 10253 + android.Manifest.permission.STATUS_BAR); 10254 } 10255 10256 synchronized (mWindowMap) { 10257 mLastStatusBarVisibility = visibility; 10258 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 10259 updateStatusBarVisibilityLocked(visibility); 10260 } 10261 } 10262 10263 // TOOD(multidisplay): StatusBar on multiple screens? 10264 void updateStatusBarVisibilityLocked(int visibility) { 10265 mInputManager.setSystemUiVisibility(visibility); 10266 final WindowList windows = getDefaultWindowListLocked(); 10267 final int N = windows.size(); 10268 for (int i = 0; i < N; i++) { 10269 WindowState ws = windows.get(i); 10270 try { 10271 int curValue = ws.mSystemUiVisibility; 10272 int diff = curValue ^ visibility; 10273 // We are only interested in differences of one of the 10274 // clearable flags... 10275 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 10276 // ...if it has actually been cleared. 10277 diff &= ~visibility; 10278 int newValue = (curValue&~diff) | (visibility&diff); 10279 if (newValue != curValue) { 10280 ws.mSeq++; 10281 ws.mSystemUiVisibility = newValue; 10282 } 10283 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 10284 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 10285 visibility, newValue, diff); 10286 } 10287 } catch (RemoteException e) { 10288 // so sorry 10289 } 10290 } 10291 } 10292 10293 @Override 10294 public void reevaluateStatusBarVisibility() { 10295 synchronized (mWindowMap) { 10296 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 10297 updateStatusBarVisibilityLocked(visibility); 10298 performLayoutAndPlaceSurfacesLocked(); 10299 } 10300 } 10301 10302 @Override 10303 public FakeWindow addFakeWindow(Looper looper, 10304 InputEventReceiver.Factory inputEventReceiverFactory, 10305 String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags, 10306 boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) { 10307 synchronized (mWindowMap) { 10308 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 10309 name, windowType, 10310 layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys, 10311 hasFocus, touchFullscreen); 10312 int i=0; 10313 while (i<mFakeWindows.size()) { 10314 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 10315 break; 10316 } 10317 } 10318 mFakeWindows.add(i, fw); 10319 mInputMonitor.updateInputWindowsLw(true); 10320 return fw; 10321 } 10322 } 10323 10324 boolean removeFakeWindowLocked(FakeWindow window) { 10325 synchronized (mWindowMap) { 10326 if (mFakeWindows.remove(window)) { 10327 mInputMonitor.updateInputWindowsLw(true); 10328 return true; 10329 } 10330 return false; 10331 } 10332 } 10333 10334 // It is assumed that this method is called only by InputMethodManagerService. 10335 public void saveLastInputMethodWindowForTransition() { 10336 synchronized (mWindowMap) { 10337 // TODO(multidisplay): Pass in the displayID. 10338 DisplayContent displayContent = getDefaultDisplayContentLocked(); 10339 if (mInputMethodWindow != null) { 10340 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 10341 } 10342 } 10343 } 10344 10345 public int getInputMethodWindowVisibleHeight() { 10346 synchronized (mWindowMap) { 10347 return mPolicy.getInputMethodWindowVisibleHeightLw(); 10348 } 10349 } 10350 10351 @Override 10352 public boolean hasNavigationBar() { 10353 return mPolicy.hasNavigationBar(); 10354 } 10355 10356 @Override 10357 public void lockNow(Bundle options) { 10358 mPolicy.lockNow(options); 10359 } 10360 10361 @Override 10362 public boolean isSafeModeEnabled() { 10363 return mSafeMode; 10364 } 10365 10366 @Override 10367 public boolean clearWindowContentFrameStats(IBinder token) { 10368 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10369 "clearWindowContentFrameStats()")) { 10370 throw new SecurityException("Requires FRAME_STATS permission"); 10371 } 10372 synchronized (mWindowMap) { 10373 WindowState windowState = mWindowMap.get(token); 10374 if (windowState == null) { 10375 return false; 10376 } 10377 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10378 if (surfaceControl == null) { 10379 return false; 10380 } 10381 return surfaceControl.clearContentFrameStats(); 10382 } 10383 } 10384 10385 @Override 10386 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) { 10387 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10388 "getWindowContentFrameStats()")) { 10389 throw new SecurityException("Requires FRAME_STATS permission"); 10390 } 10391 synchronized (mWindowMap) { 10392 WindowState windowState = mWindowMap.get(token); 10393 if (windowState == null) { 10394 return null; 10395 } 10396 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10397 if (surfaceControl == null) { 10398 return null; 10399 } 10400 if (mTempWindowRenderStats == null) { 10401 mTempWindowRenderStats = new WindowContentFrameStats(); 10402 } 10403 WindowContentFrameStats stats = mTempWindowRenderStats; 10404 if (!surfaceControl.getContentFrameStats(stats)) { 10405 return null; 10406 } 10407 return stats; 10408 } 10409 } 10410 10411 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10412 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 10413 mPolicy.dump(" ", pw, args); 10414 } 10415 10416 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10417 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 10418 mAnimator.dumpLocked(pw, " ", dumpAll); 10419 } 10420 10421 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 10422 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 10423 if (mTokenMap.size() > 0) { 10424 pw.println(" All tokens:"); 10425 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10426 while (it.hasNext()) { 10427 WindowToken token = it.next(); 10428 pw.print(" "); pw.print(token); 10429 if (dumpAll) { 10430 pw.println(':'); 10431 token.dump(pw, " "); 10432 } else { 10433 pw.println(); 10434 } 10435 } 10436 } 10437 if (mWallpaperTokens.size() > 0) { 10438 pw.println(); 10439 pw.println(" Wallpaper tokens:"); 10440 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 10441 WindowToken token = mWallpaperTokens.get(i); 10442 pw.print(" Wallpaper #"); pw.print(i); 10443 pw.print(' '); pw.print(token); 10444 if (dumpAll) { 10445 pw.println(':'); 10446 token.dump(pw, " "); 10447 } else { 10448 pw.println(); 10449 } 10450 } 10451 } 10452 if (mFinishedStarting.size() > 0) { 10453 pw.println(); 10454 pw.println(" Finishing start of application tokens:"); 10455 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10456 WindowToken token = mFinishedStarting.get(i); 10457 pw.print(" Finished Starting #"); pw.print(i); 10458 pw.print(' '); pw.print(token); 10459 if (dumpAll) { 10460 pw.println(':'); 10461 token.dump(pw, " "); 10462 } else { 10463 pw.println(); 10464 } 10465 } 10466 } 10467 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 10468 pw.println(); 10469 if (mOpeningApps.size() > 0) { 10470 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10471 } 10472 if (mClosingApps.size() > 0) { 10473 pw.print(" mClosingApps="); pw.println(mClosingApps); 10474 } 10475 } 10476 } 10477 10478 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 10479 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 10480 for (int i=0; i<mSessions.size(); i++) { 10481 Session s = mSessions.valueAt(i); 10482 pw.print(" Session "); pw.print(s); pw.println(':'); 10483 s.dump(pw, " "); 10484 } 10485 } 10486 10487 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 10488 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 10489 if (mDisplayReady) { 10490 final int numDisplays = mDisplayContents.size(); 10491 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10492 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10493 displayContent.dump(" ", pw); 10494 } 10495 } else { 10496 pw.println(" NO DISPLAY"); 10497 } 10498 } 10499 10500 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 10501 ArrayList<WindowState> windows) { 10502 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 10503 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 10504 } 10505 10506 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 10507 ArrayList<WindowState> windows) { 10508 final int numDisplays = mDisplayContents.size(); 10509 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10510 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); 10511 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10512 final WindowState w = windowList.get(winNdx); 10513 if (windows == null || windows.contains(w)) { 10514 pw.print(" Window #"); pw.print(winNdx); pw.print(' '); 10515 pw.print(w); pw.println(":"); 10516 w.dump(pw, " ", dumpAll || windows != null); 10517 } 10518 } 10519 } 10520 if (mInputMethodDialogs.size() > 0) { 10521 pw.println(); 10522 pw.println(" Input method dialogs:"); 10523 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 10524 WindowState w = mInputMethodDialogs.get(i); 10525 if (windows == null || windows.contains(w)) { 10526 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 10527 } 10528 } 10529 } 10530 if (mPendingRemove.size() > 0) { 10531 pw.println(); 10532 pw.println(" Remove pending for:"); 10533 for (int i=mPendingRemove.size()-1; i>=0; i--) { 10534 WindowState w = mPendingRemove.get(i); 10535 if (windows == null || windows.contains(w)) { 10536 pw.print(" Remove #"); pw.print(i); pw.print(' '); 10537 pw.print(w); 10538 if (dumpAll) { 10539 pw.println(":"); 10540 w.dump(pw, " ", true); 10541 } else { 10542 pw.println(); 10543 } 10544 } 10545 } 10546 } 10547 if (mForceRemoves != null && mForceRemoves.size() > 0) { 10548 pw.println(); 10549 pw.println(" Windows force removing:"); 10550 for (int i=mForceRemoves.size()-1; i>=0; i--) { 10551 WindowState w = mForceRemoves.get(i); 10552 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10553 pw.print(w); 10554 if (dumpAll) { 10555 pw.println(":"); 10556 w.dump(pw, " ", true); 10557 } else { 10558 pw.println(); 10559 } 10560 } 10561 } 10562 if (mDestroySurface.size() > 0) { 10563 pw.println(); 10564 pw.println(" Windows waiting to destroy their surface:"); 10565 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10566 WindowState w = mDestroySurface.get(i); 10567 if (windows == null || windows.contains(w)) { 10568 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10569 pw.print(w); 10570 if (dumpAll) { 10571 pw.println(":"); 10572 w.dump(pw, " ", true); 10573 } else { 10574 pw.println(); 10575 } 10576 } 10577 } 10578 } 10579 if (mLosingFocus.size() > 0) { 10580 pw.println(); 10581 pw.println(" Windows losing focus:"); 10582 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10583 WindowState w = mLosingFocus.get(i); 10584 if (windows == null || windows.contains(w)) { 10585 pw.print(" Losing #"); pw.print(i); pw.print(' '); 10586 pw.print(w); 10587 if (dumpAll) { 10588 pw.println(":"); 10589 w.dump(pw, " ", true); 10590 } else { 10591 pw.println(); 10592 } 10593 } 10594 } 10595 } 10596 if (mResizingWindows.size() > 0) { 10597 pw.println(); 10598 pw.println(" Windows waiting to resize:"); 10599 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10600 WindowState w = mResizingWindows.get(i); 10601 if (windows == null || windows.contains(w)) { 10602 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 10603 pw.print(w); 10604 if (dumpAll) { 10605 pw.println(":"); 10606 w.dump(pw, " ", true); 10607 } else { 10608 pw.println(); 10609 } 10610 } 10611 } 10612 } 10613 if (mWaitingForDrawn.size() > 0) { 10614 pw.println(); 10615 pw.println(" Clients waiting for these windows to be drawn:"); 10616 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10617 WindowState win = mWaitingForDrawn.get(i); 10618 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); 10619 } 10620 } 10621 pw.println(); 10622 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10623 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10624 if (mLastFocus != mCurrentFocus) { 10625 pw.print(" mLastFocus="); pw.println(mLastFocus); 10626 } 10627 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10628 if (mInputMethodTarget != null) { 10629 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10630 } 10631 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10632 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10633 pw.print(" mLastDisplayFreezeDuration="); 10634 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 10635 if ( mLastFinishedFreezeSource != null) { 10636 pw.print(" due to "); 10637 pw.print(mLastFinishedFreezeSource); 10638 } 10639 pw.println(); 10640 if (dumpAll) { 10641 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 10642 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 10643 if (mLastStatusBarVisibility != 0) { 10644 pw.print(" mLastStatusBarVisibility=0x"); 10645 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 10646 } 10647 if (mInputMethodWindow != null) { 10648 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10649 } 10650 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 10651 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) { 10652 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 10653 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 10654 } 10655 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 10656 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 10657 if (mInputMethodAnimLayerAdjustment != 0 || 10658 mWallpaperAnimLayerAdjustment != 0) { 10659 pw.print(" mInputMethodAnimLayerAdjustment="); 10660 pw.print(mInputMethodAnimLayerAdjustment); 10661 pw.print(" mWallpaperAnimLayerAdjustment="); 10662 pw.println(mWallpaperAnimLayerAdjustment); 10663 } 10664 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10665 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10666 if (needsLayout()) { 10667 pw.print(" layoutNeeded on displays="); 10668 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10669 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10670 if (displayContent.layoutNeeded) { 10671 pw.print(displayContent.getDisplayId()); 10672 } 10673 } 10674 pw.println(); 10675 } 10676 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 10677 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10678 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 10679 pw.print(" client="); pw.print(mClientFreezingScreen); 10680 pw.print(" apps="); pw.print(mAppsFreezingScreen); 10681 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 10682 pw.print(" mRotation="); pw.print(mRotation); 10683 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 10684 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 10685 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 10686 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 10687 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled); 10688 pw.print(" window="); pw.print(mWindowAnimationScaleSetting); 10689 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); 10690 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); 10691 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); 10692 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 10693 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 10694 pw.println(" mLayoutToAnim:"); 10695 mAppTransition.dump(pw); 10696 } 10697 } 10698 10699 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10700 int opti, boolean dumpAll) { 10701 WindowList windows = new WindowList(); 10702 if ("visible".equals(name)) { 10703 synchronized(mWindowMap) { 10704 final int numDisplays = mDisplayContents.size(); 10705 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10706 final WindowList windowList = 10707 mDisplayContents.valueAt(displayNdx).getWindowList(); 10708 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10709 final WindowState w = windowList.get(winNdx); 10710 if (w.mWinAnimator.mSurfaceShown) { 10711 windows.add(w); 10712 } 10713 } 10714 } 10715 } 10716 } else { 10717 int objectId = 0; 10718 // See if this is an object ID. 10719 try { 10720 objectId = Integer.parseInt(name, 16); 10721 name = null; 10722 } catch (RuntimeException e) { 10723 } 10724 synchronized(mWindowMap) { 10725 final int numDisplays = mDisplayContents.size(); 10726 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10727 final WindowList windowList = 10728 mDisplayContents.valueAt(displayNdx).getWindowList(); 10729 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10730 final WindowState w = windowList.get(winNdx); 10731 if (name != null) { 10732 if (w.mAttrs.getTitle().toString().contains(name)) { 10733 windows.add(w); 10734 } 10735 } else if (System.identityHashCode(w) == objectId) { 10736 windows.add(w); 10737 } 10738 } 10739 } 10740 } 10741 } 10742 10743 if (windows.size() <= 0) { 10744 return false; 10745 } 10746 10747 synchronized(mWindowMap) { 10748 dumpWindowsLocked(pw, dumpAll, windows); 10749 } 10750 return true; 10751 } 10752 10753 void dumpLastANRLocked(PrintWriter pw) { 10754 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10755 if (mLastANRState == null) { 10756 pw.println(" <no ANR has occurred since boot>"); 10757 } else { 10758 pw.println(mLastANRState); 10759 } 10760 } 10761 10762 /** 10763 * Saves information about the state of the window manager at 10764 * the time an ANR occurred before anything else in the system changes 10765 * in response. 10766 * 10767 * @param appWindowToken The application that ANR'd, may be null. 10768 * @param windowState The window that ANR'd, may be null. 10769 * @param reason The reason for the ANR, may be null. 10770 */ 10771 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, 10772 String reason) { 10773 StringWriter sw = new StringWriter(); 10774 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 10775 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10776 if (appWindowToken != null) { 10777 pw.println(" Application at fault: " + appWindowToken.stringName); 10778 } 10779 if (windowState != null) { 10780 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10781 } 10782 if (reason != null) { 10783 pw.println(" Reason: " + reason); 10784 } 10785 pw.println(); 10786 dumpWindowsNoHeaderLocked(pw, true, null); 10787 pw.close(); 10788 mLastANRState = sw.toString(); 10789 } 10790 10791 @Override 10792 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10793 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10794 != PackageManager.PERMISSION_GRANTED) { 10795 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10796 + Binder.getCallingPid() 10797 + ", uid=" + Binder.getCallingUid()); 10798 return; 10799 } 10800 10801 boolean dumpAll = false; 10802 10803 int opti = 0; 10804 while (opti < args.length) { 10805 String opt = args[opti]; 10806 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10807 break; 10808 } 10809 opti++; 10810 if ("-a".equals(opt)) { 10811 dumpAll = true; 10812 } else if ("-h".equals(opt)) { 10813 pw.println("Window manager dump options:"); 10814 pw.println(" [-a] [-h] [cmd] ..."); 10815 pw.println(" cmd may be one of:"); 10816 pw.println(" l[astanr]: last ANR information"); 10817 pw.println(" p[policy]: policy state"); 10818 pw.println(" a[animator]: animator state"); 10819 pw.println(" s[essions]: active sessions"); 10820 pw.println(" d[isplays]: active display contents"); 10821 pw.println(" t[okens]: token list"); 10822 pw.println(" w[indows]: window list"); 10823 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10824 pw.println(" be a partial substring in a window name, a"); 10825 pw.println(" Window hex object identifier, or"); 10826 pw.println(" \"all\" for all windows, or"); 10827 pw.println(" \"visible\" for the visible windows."); 10828 pw.println(" -a: include all available server state."); 10829 return; 10830 } else { 10831 pw.println("Unknown argument: " + opt + "; use -h for help"); 10832 } 10833 } 10834 10835 // Is the caller requesting to dump a particular piece of data? 10836 if (opti < args.length) { 10837 String cmd = args[opti]; 10838 opti++; 10839 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10840 synchronized(mWindowMap) { 10841 dumpLastANRLocked(pw); 10842 } 10843 return; 10844 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10845 synchronized(mWindowMap) { 10846 dumpPolicyLocked(pw, args, true); 10847 } 10848 return; 10849 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 10850 synchronized(mWindowMap) { 10851 dumpAnimatorLocked(pw, args, true); 10852 } 10853 return; 10854 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10855 synchronized(mWindowMap) { 10856 dumpSessionsLocked(pw, true); 10857 } 10858 return; 10859 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 10860 synchronized(mWindowMap) { 10861 dumpDisplayContentsLocked(pw, true); 10862 } 10863 return; 10864 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10865 synchronized(mWindowMap) { 10866 dumpTokensLocked(pw, true); 10867 } 10868 return; 10869 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10870 synchronized(mWindowMap) { 10871 dumpWindowsLocked(pw, true, null); 10872 } 10873 return; 10874 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10875 synchronized(mWindowMap) { 10876 dumpWindowsLocked(pw, true, null); 10877 } 10878 return; 10879 } else { 10880 // Dumping a single name? 10881 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10882 pw.println("Bad window command, or no windows match: " + cmd); 10883 pw.println("Use -h for help."); 10884 } 10885 return; 10886 } 10887 } 10888 10889 synchronized(mWindowMap) { 10890 pw.println(); 10891 if (dumpAll) { 10892 pw.println("-------------------------------------------------------------------------------"); 10893 } 10894 dumpLastANRLocked(pw); 10895 pw.println(); 10896 if (dumpAll) { 10897 pw.println("-------------------------------------------------------------------------------"); 10898 } 10899 dumpPolicyLocked(pw, args, dumpAll); 10900 pw.println(); 10901 if (dumpAll) { 10902 pw.println("-------------------------------------------------------------------------------"); 10903 } 10904 dumpAnimatorLocked(pw, args, dumpAll); 10905 pw.println(); 10906 if (dumpAll) { 10907 pw.println("-------------------------------------------------------------------------------"); 10908 } 10909 dumpSessionsLocked(pw, dumpAll); 10910 pw.println(); 10911 if (dumpAll) { 10912 pw.println("-------------------------------------------------------------------------------"); 10913 } 10914 dumpDisplayContentsLocked(pw, dumpAll); 10915 pw.println(); 10916 if (dumpAll) { 10917 pw.println("-------------------------------------------------------------------------------"); 10918 } 10919 dumpTokensLocked(pw, dumpAll); 10920 pw.println(); 10921 if (dumpAll) { 10922 pw.println("-------------------------------------------------------------------------------"); 10923 } 10924 dumpWindowsLocked(pw, dumpAll, null); 10925 } 10926 } 10927 10928 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10929 @Override 10930 public void monitor() { 10931 synchronized (mWindowMap) { } 10932 } 10933 10934 public interface OnHardKeyboardStatusChangeListener { 10935 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 10936 } 10937 10938 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 10939 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 10940 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 10941 Integer.toHexString(pendingLayoutChanges)); 10942 } 10943 } 10944 10945 private DisplayContent newDisplayContentLocked(final Display display) { 10946 DisplayContent displayContent = new DisplayContent(display, this); 10947 final int displayId = display.getDisplayId(); 10948 if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display); 10949 mDisplayContents.put(displayId, displayContent); 10950 10951 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10952 final Rect rect = new Rect(); 10953 mDisplaySettings.getOverscanLocked(displayInfo.name, rect); 10954 synchronized (displayContent.mDisplaySizeLock) { 10955 displayInfo.overscanLeft = rect.left; 10956 displayInfo.overscanTop = rect.top; 10957 displayInfo.overscanRight = rect.right; 10958 displayInfo.overscanBottom = rect.bottom; 10959 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 10960 displayId, displayInfo); 10961 } 10962 configureDisplayPolicyLocked(displayContent); 10963 10964 // TODO: Create an input channel for each display with touch capability. 10965 if (displayId == Display.DEFAULT_DISPLAY) { 10966 displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent); 10967 registerPointerEventListener(displayContent.mTapDetector); 10968 } 10969 10970 return displayContent; 10971 } 10972 10973 public void createDisplayContentLocked(final Display display) { 10974 if (display == null) { 10975 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 10976 } 10977 getDisplayContentLocked(display.getDisplayId()); 10978 } 10979 10980 /** 10981 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 10982 * there is a Display for the displayId. 10983 * @param displayId The display the caller is interested in. 10984 * @return The DisplayContent associated with displayId or null if there is no Display for it. 10985 */ 10986 public DisplayContent getDisplayContentLocked(final int displayId) { 10987 DisplayContent displayContent = mDisplayContents.get(displayId); 10988 if (displayContent == null) { 10989 final Display display = mDisplayManager.getDisplay(displayId); 10990 if (display != null) { 10991 displayContent = newDisplayContentLocked(display); 10992 } 10993 } 10994 return displayContent; 10995 } 10996 10997 // There is an inherent assumption that this will never return null. 10998 public DisplayContent getDefaultDisplayContentLocked() { 10999 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 11000 } 11001 11002 public WindowList getDefaultWindowListLocked() { 11003 return getDefaultDisplayContentLocked().getWindowList(); 11004 } 11005 11006 public DisplayInfo getDefaultDisplayInfoLocked() { 11007 return getDefaultDisplayContentLocked().getDisplayInfo(); 11008 } 11009 11010 /** 11011 * Return the list of WindowStates associated on the passed display. 11012 * @param display The screen to return windows from. 11013 * @return The list of WindowStates on the screen, or null if the there is no screen. 11014 */ 11015 public WindowList getWindowListLocked(final Display display) { 11016 return getWindowListLocked(display.getDisplayId()); 11017 } 11018 11019 /** 11020 * Return the list of WindowStates associated on the passed display. 11021 * @param displayId The screen to return windows from. 11022 * @return The list of WindowStates on the screen, or null if the there is no screen. 11023 */ 11024 public WindowList getWindowListLocked(final int displayId) { 11025 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11026 return displayContent != null ? displayContent.getWindowList() : null; 11027 } 11028 11029 public void onDisplayAdded(int displayId) { 11030 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 11031 } 11032 11033 public void handleDisplayAdded(int displayId) { 11034 synchronized (mWindowMap) { 11035 final Display display = mDisplayManager.getDisplay(displayId); 11036 if (display != null) { 11037 createDisplayContentLocked(display); 11038 displayReady(displayId); 11039 } 11040 } 11041 } 11042 11043 public void onDisplayRemoved(int displayId) { 11044 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 11045 } 11046 11047 private void handleDisplayRemovedLocked(int displayId) { 11048 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11049 if (displayContent != null) { 11050 if (displayContent.isAnimating()) { 11051 displayContent.mDeferredRemoval = true; 11052 return; 11053 } 11054 if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent); 11055 mDisplayContents.delete(displayId); 11056 displayContent.close(); 11057 if (displayId == Display.DEFAULT_DISPLAY) { 11058 unregisterPointerEventListener(displayContent.mTapDetector); 11059 } 11060 } 11061 mAnimator.removeDisplayLocked(displayId); 11062 } 11063 11064 public void onDisplayChanged(int displayId) { 11065 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 11066 } 11067 11068 private void handleDisplayChangedLocked(int displayId) { 11069 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11070 if (displayContent != null) { 11071 displayContent.updateDisplayInfo(); 11072 } 11073 } 11074 11075 @Override 11076 public Object getWindowManagerLock() { 11077 return mWindowMap; 11078 } 11079 11080 private final class LocalService extends WindowManagerInternal { 11081 @Override 11082 public void requestTraversalFromDisplayManager() { 11083 requestTraversal(); 11084 } 11085 11086 @Override 11087 public void setMagnificationSpec(MagnificationSpec spec) { 11088 synchronized (mWindowMap) { 11089 if (mAccessibilityController != null) { 11090 mAccessibilityController.setMagnificationSpecLocked(spec); 11091 } else { 11092 throw new IllegalStateException("Magnification callbacks not set!"); 11093 } 11094 } 11095 if (Binder.getCallingPid() != android.os.Process.myPid()) { 11096 spec.recycle(); 11097 } 11098 } 11099 11100 @Override 11101 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { 11102 synchronized (mWindowMap) { 11103 WindowState windowState = mWindowMap.get(windowToken); 11104 if (windowState == null) { 11105 return null; 11106 } 11107 MagnificationSpec spec = null; 11108 if (mAccessibilityController != null) { 11109 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState); 11110 } 11111 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) { 11112 return null; 11113 } 11114 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec); 11115 spec.scale *= windowState.mGlobalScale; 11116 return spec; 11117 } 11118 } 11119 11120 @Override 11121 public void setMagnificationCallbacks(MagnificationCallbacks callbacks) { 11122 synchronized (mWindowMap) { 11123 if (mAccessibilityController == null) { 11124 mAccessibilityController = new AccessibilityController( 11125 WindowManagerService.this); 11126 } 11127 mAccessibilityController.setMagnificationCallbacksLocked(callbacks); 11128 if (!mAccessibilityController.hasCallbacksLocked()) { 11129 mAccessibilityController = null; 11130 } 11131 } 11132 } 11133 11134 @Override 11135 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) { 11136 synchronized (mWindowMap) { 11137 if (mAccessibilityController == null) { 11138 mAccessibilityController = new AccessibilityController( 11139 WindowManagerService.this); 11140 } 11141 mAccessibilityController.setWindowsForAccessibilityCallback(callback); 11142 if (!mAccessibilityController.hasCallbacksLocked()) { 11143 mAccessibilityController = null; 11144 } 11145 } 11146 } 11147 11148 @Override 11149 public void setInputFilter(IInputFilter filter) { 11150 mInputManager.setInputFilter(filter); 11151 } 11152 11153 @Override 11154 public IBinder getFocusedWindowToken() { 11155 synchronized (mWindowMap) { 11156 WindowState windowState = getFocusedWindowLocked(); 11157 if (windowState != null) { 11158 return windowState.mClient.asBinder(); 11159 } 11160 return null; 11161 } 11162 } 11163 11164 @Override 11165 public boolean isKeyguardLocked() { 11166 return isKeyguardLocked(); 11167 } 11168 11169 @Override 11170 public void getWindowFrame(IBinder token, Rect outBounds) { 11171 synchronized (mWindowMap) { 11172 WindowState windowState = mWindowMap.get(token); 11173 if (windowState != null) { 11174 outBounds.set(windowState.mFrame); 11175 } else { 11176 outBounds.setEmpty(); 11177 } 11178 } 11179 } 11180 11181 public void waitForAllWindowsDrawn(IRemoteCallback callback, long timeout) { 11182 synchronized (mWindowMap) { 11183 mWaitingForDrawnCallback = callback; 11184 final WindowList windows = getDefaultWindowListLocked(); 11185 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 11186 final WindowState win = windows.get(winNdx); 11187 if (win.mHasSurface) { 11188 win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 11189 // Force add to mResizingWindows. 11190 win.mLastContentInsets.set(-1, -1, -1, -1); 11191 mWaitingForDrawn.add(win); 11192 } 11193 } 11194 requestTraversalLocked(); 11195 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 11196 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); 11197 } 11198 checkDrawnWindowsLocked(); 11199 } 11200 } 11201} 11202