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