WindowManagerService.java revision abe0aa78caf81b24af0b45700801fc1f867cfa0e
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.drawBitmap(rawss, matrix, null); 5494 canvas.setBitmap(null); 5495 5496 if (true || DEBUG_SCREENSHOT) { 5497 // TEST IF IT's ALL BLACK 5498 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 5499 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 5500 boolean allBlack = true; 5501 for (int i = 0; i < buffer.length; i++) { 5502 if (buffer[i] != Color.BLACK) { 5503 allBlack = false; 5504 break; 5505 } 5506 } 5507 if (allBlack) { 5508 Slog.i(TAG, "Screenshot " + appWin + " was all black! mSurfaceLayer=" + 5509 (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") + 5510 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 5511 } 5512 } 5513 5514 rawss.recycle(); 5515 return bm; 5516 } 5517 5518 /** 5519 * Freeze rotation changes. (Enable "rotation lock".) 5520 * Persists across reboots. 5521 * @param rotation The desired rotation to freeze to, or -1 to use the 5522 * current rotation. 5523 */ 5524 @Override 5525 public void freezeRotation(int rotation) { 5526 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5527 "freezeRotation()")) { 5528 throw new SecurityException("Requires SET_ORIENTATION permission"); 5529 } 5530 if (rotation < -1 || rotation > Surface.ROTATION_270) { 5531 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 5532 + "rotation constant."); 5533 } 5534 5535 if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); 5536 5537 long origId = Binder.clearCallingIdentity(); 5538 try { 5539 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, 5540 rotation == -1 ? mRotation : rotation); 5541 } finally { 5542 Binder.restoreCallingIdentity(origId); 5543 } 5544 5545 updateRotationUnchecked(false, false); 5546 } 5547 5548 /** 5549 * Thaw rotation changes. (Disable "rotation lock".) 5550 * Persists across reboots. 5551 */ 5552 @Override 5553 public void thawRotation() { 5554 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5555 "thawRotation()")) { 5556 throw new SecurityException("Requires SET_ORIENTATION permission"); 5557 } 5558 5559 if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); 5560 5561 long origId = Binder.clearCallingIdentity(); 5562 try { 5563 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 5564 777); // rot not used 5565 } finally { 5566 Binder.restoreCallingIdentity(origId); 5567 } 5568 5569 updateRotationUnchecked(false, false); 5570 } 5571 5572 /** 5573 * Recalculate the current rotation. 5574 * 5575 * Called by the window manager policy whenever the state of the system changes 5576 * such that the current rotation might need to be updated, such as when the 5577 * device is docked or rotated into a new posture. 5578 */ 5579 @Override 5580 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 5581 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 5582 } 5583 5584 /** 5585 * Temporarily pauses rotation changes until resumed. 5586 * 5587 * This can be used to prevent rotation changes from occurring while the user is 5588 * performing certain operations, such as drag and drop. 5589 * 5590 * This call nests and must be matched by an equal number of calls to 5591 * {@link #resumeRotationLocked}. 5592 */ 5593 void pauseRotationLocked() { 5594 mDeferredRotationPauseCount += 1; 5595 } 5596 5597 /** 5598 * Resumes normal rotation changes after being paused. 5599 */ 5600 void resumeRotationLocked() { 5601 if (mDeferredRotationPauseCount > 0) { 5602 mDeferredRotationPauseCount -= 1; 5603 if (mDeferredRotationPauseCount == 0) { 5604 boolean changed = updateRotationUncheckedLocked(false); 5605 if (changed) { 5606 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 5607 } 5608 } 5609 } 5610 } 5611 5612 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 5613 if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" 5614 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); 5615 5616 long origId = Binder.clearCallingIdentity(); 5617 boolean changed; 5618 synchronized(mWindowMap) { 5619 changed = updateRotationUncheckedLocked(false); 5620 if (!changed || forceRelayout) { 5621 getDefaultDisplayContentLocked().layoutNeeded = true; 5622 performLayoutAndPlaceSurfacesLocked(); 5623 } 5624 } 5625 5626 if (changed || alwaysSendConfiguration) { 5627 sendNewConfiguration(); 5628 } 5629 5630 Binder.restoreCallingIdentity(origId); 5631 } 5632 5633 // TODO(multidisplay): Rotate any display? 5634 /** 5635 * Updates the current rotation. 5636 * 5637 * Returns true if the rotation has been changed. In this case YOU 5638 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. 5639 */ 5640 public boolean updateRotationUncheckedLocked(boolean inTransaction) { 5641 if (mDeferredRotationPauseCount > 0) { 5642 // Rotation updates have been paused temporarily. Defer the update until 5643 // updates have been resumed. 5644 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused."); 5645 return false; 5646 } 5647 5648 ScreenRotationAnimation screenRotationAnimation = 5649 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 5650 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 5651 // Rotation updates cannot be performed while the previous rotation change 5652 // animation is still in progress. Skip this update. We will try updating 5653 // again after the animation is finished and the display is unfrozen. 5654 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress."); 5655 return false; 5656 } 5657 5658 if (!mDisplayEnabled) { 5659 // No point choosing a rotation if the display is not enabled. 5660 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled."); 5661 return false; 5662 } 5663 5664 // TODO: Implement forced rotation changes. 5665 // Set mAltOrientation to indicate that the application is receiving 5666 // an orientation that has different metrics than it expected. 5667 // eg. Portrait instead of Landscape. 5668 5669 int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation); 5670 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 5671 mForcedAppOrientation, rotation); 5672 5673 if (DEBUG_ORIENTATION) { 5674 Slog.v(TAG, "Application requested orientation " 5675 + mForcedAppOrientation + ", got rotation " + rotation 5676 + " which has " + (altOrientation ? "incompatible" : "compatible") 5677 + " metrics"); 5678 } 5679 5680 if (mRotation == rotation && mAltOrientation == altOrientation) { 5681 // No change. 5682 return false; 5683 } 5684 5685 if (DEBUG_ORIENTATION) { 5686 Slog.v(TAG, 5687 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") 5688 + " from " + mRotation + (mAltOrientation ? " (alt)" : "") 5689 + ", forceApp=" + mForcedAppOrientation); 5690 } 5691 5692 mRotation = rotation; 5693 mAltOrientation = altOrientation; 5694 mPolicy.setRotationLw(mRotation); 5695 5696 mWindowsFreezingScreen = true; 5697 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 5698 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION); 5699 mWaitingForConfig = true; 5700 getDefaultDisplayContentLocked().layoutNeeded = true; 5701 final int[] anim = new int[2]; 5702 if (mAnimator.isDimmingLocked(Display.DEFAULT_DISPLAY)) { 5703 anim[0] = anim[1] = 0; 5704 } else { 5705 mPolicy.selectRotationAnimationLw(anim); 5706 } 5707 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]); 5708 // startFreezingDisplayLocked can reset the ScreenRotationAnimation. 5709 screenRotationAnimation = 5710 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 5711 5712 // We need to update our screen size information to match the new 5713 // rotation. Note that this is redundant with the later call to 5714 // sendNewConfiguration() that must be called after this function 5715 // returns... however we need to do the screen size part of that 5716 // before then so we have the correct size to use when initializing 5717 // the rotation animation for the new rotation. 5718 computeScreenConfigurationLocked(null); 5719 5720 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 5721 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 5722 if (!inTransaction) { 5723 if (SHOW_TRANSACTIONS) { 5724 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked"); 5725 } 5726 SurfaceControl.openTransaction(); 5727 } 5728 try { 5729 // NOTE: We disable the rotation in the emulator because 5730 // it doesn't support hardware OpenGL emulation yet. 5731 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 5732 && screenRotationAnimation.hasScreenshot()) { 5733 if (screenRotationAnimation.setRotationInTransaction( 5734 rotation, mFxSession, 5735 MAX_ANIMATION_DURATION, mTransitionAnimationScale, 5736 displayInfo.logicalWidth, displayInfo.logicalHeight)) { 5737 scheduleAnimationLocked(); 5738 } 5739 } 5740 5741 mDisplayManagerService.performTraversalInTransactionFromWindowManager(); 5742 } finally { 5743 if (!inTransaction) { 5744 SurfaceControl.closeTransaction(); 5745 if (SHOW_LIGHT_TRANSACTIONS) { 5746 Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked"); 5747 } 5748 } 5749 } 5750 5751 final WindowList windows = displayContent.getWindowList(); 5752 for (int i = windows.size() - 1; i >= 0; i--) { 5753 WindowState w = windows.get(i); 5754 if (w.mHasSurface) { 5755 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w); 5756 w.mOrientationChanging = true; 5757 mInnerFields.mOrientationChangeComplete = false; 5758 } 5759 w.mLastFreezeDuration = 0; 5760 } 5761 5762 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 5763 try { 5764 mRotationWatchers.get(i).onRotationChanged(rotation); 5765 } catch (RemoteException e) { 5766 } 5767 } 5768 5769 //TODO (multidisplay): Magnification is supported only for the default display. 5770 if (mDisplayMagnifier != null 5771 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 5772 mDisplayMagnifier.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation); 5773 } 5774 5775 return true; 5776 } 5777 5778 @Override 5779 public int getRotation() { 5780 return mRotation; 5781 } 5782 5783 @Override 5784 public boolean isRotationFrozen() { 5785 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED; 5786 } 5787 5788 @Override 5789 public int watchRotation(IRotationWatcher watcher) { 5790 final IBinder watcherBinder = watcher.asBinder(); 5791 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 5792 @Override 5793 public void binderDied() { 5794 synchronized (mWindowMap) { 5795 for (int i=0; i<mRotationWatchers.size(); i++) { 5796 if (watcherBinder == mRotationWatchers.get(i).asBinder()) { 5797 IRotationWatcher removed = mRotationWatchers.remove(i); 5798 if (removed != null) { 5799 removed.asBinder().unlinkToDeath(this, 0); 5800 } 5801 i--; 5802 } 5803 } 5804 } 5805 } 5806 }; 5807 5808 synchronized (mWindowMap) { 5809 try { 5810 watcher.asBinder().linkToDeath(dr, 0); 5811 mRotationWatchers.add(watcher); 5812 } catch (RemoteException e) { 5813 // Client died, no cleanup needed. 5814 } 5815 5816 return mRotation; 5817 } 5818 } 5819 5820 @Override 5821 public void removeRotationWatcher(IRotationWatcher watcher) { 5822 final IBinder watcherBinder = watcher.asBinder(); 5823 synchronized (mWindowMap) { 5824 for (int i=0; i<mRotationWatchers.size(); i++) { 5825 if (watcherBinder == mRotationWatchers.get(i).asBinder()) { 5826 mRotationWatchers.remove(i); 5827 i--; 5828 } 5829 } 5830 } 5831 } 5832 5833 /** 5834 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 5835 * theme attribute) on devices that feature a physical options menu key attempt to position 5836 * their menu panel window along the edge of the screen nearest the physical menu key. 5837 * This lowers the travel distance between invoking the menu panel and selecting 5838 * a menu option. 5839 * 5840 * This method helps control where that menu is placed. Its current implementation makes 5841 * assumptions about the menu key and its relationship to the screen based on whether 5842 * the device's natural orientation is portrait (width < height) or landscape. 5843 * 5844 * The menu key is assumed to be located along the bottom edge of natural-portrait 5845 * devices and along the right edge of natural-landscape devices. If these assumptions 5846 * do not hold for the target device, this method should be changed to reflect that. 5847 * 5848 * @return A {@link Gravity} value for placing the options menu window 5849 */ 5850 @Override 5851 public int getPreferredOptionsPanelGravity() { 5852 synchronized (mWindowMap) { 5853 final int rotation = getRotation(); 5854 5855 // TODO(multidisplay): Assume that such devices physical keys are on the main screen. 5856 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 5857 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) { 5858 // On devices with a natural orientation of portrait 5859 switch (rotation) { 5860 default: 5861 case Surface.ROTATION_0: 5862 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 5863 case Surface.ROTATION_90: 5864 return Gravity.RIGHT | Gravity.BOTTOM; 5865 case Surface.ROTATION_180: 5866 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 5867 case Surface.ROTATION_270: 5868 return Gravity.START | Gravity.BOTTOM; 5869 } 5870 } 5871 5872 // On devices with a natural orientation of landscape 5873 switch (rotation) { 5874 default: 5875 case Surface.ROTATION_0: 5876 return Gravity.RIGHT | Gravity.BOTTOM; 5877 case Surface.ROTATION_90: 5878 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 5879 case Surface.ROTATION_180: 5880 return Gravity.START | Gravity.BOTTOM; 5881 case Surface.ROTATION_270: 5882 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 5883 } 5884 } 5885 } 5886 5887 /** 5888 * Starts the view server on the specified port. 5889 * 5890 * @param port The port to listener to. 5891 * 5892 * @return True if the server was successfully started, false otherwise. 5893 * 5894 * @see com.android.server.wm.ViewServer 5895 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 5896 */ 5897 @Override 5898 public boolean startViewServer(int port) { 5899 if (isSystemSecure()) { 5900 return false; 5901 } 5902 5903 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 5904 return false; 5905 } 5906 5907 if (port < 1024) { 5908 return false; 5909 } 5910 5911 if (mViewServer != null) { 5912 if (!mViewServer.isRunning()) { 5913 try { 5914 return mViewServer.start(); 5915 } catch (IOException e) { 5916 Slog.w(TAG, "View server did not start"); 5917 } 5918 } 5919 return false; 5920 } 5921 5922 try { 5923 mViewServer = new ViewServer(this, port); 5924 return mViewServer.start(); 5925 } catch (IOException e) { 5926 Slog.w(TAG, "View server did not start"); 5927 } 5928 return false; 5929 } 5930 5931 private boolean isSystemSecure() { 5932 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 5933 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 5934 } 5935 5936 /** 5937 * Stops the view server if it exists. 5938 * 5939 * @return True if the server stopped, false if it wasn't started or 5940 * couldn't be stopped. 5941 * 5942 * @see com.android.server.wm.ViewServer 5943 */ 5944 @Override 5945 public boolean stopViewServer() { 5946 if (isSystemSecure()) { 5947 return false; 5948 } 5949 5950 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 5951 return false; 5952 } 5953 5954 if (mViewServer != null) { 5955 return mViewServer.stop(); 5956 } 5957 return false; 5958 } 5959 5960 /** 5961 * Indicates whether the view server is running. 5962 * 5963 * @return True if the server is running, false otherwise. 5964 * 5965 * @see com.android.server.wm.ViewServer 5966 */ 5967 @Override 5968 public boolean isViewServerRunning() { 5969 if (isSystemSecure()) { 5970 return false; 5971 } 5972 5973 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 5974 return false; 5975 } 5976 5977 return mViewServer != null && mViewServer.isRunning(); 5978 } 5979 5980 /** 5981 * Lists all availble windows in the system. The listing is written in the 5982 * specified Socket's output stream with the following syntax: 5983 * windowHashCodeInHexadecimal windowName 5984 * Each line of the ouput represents a different window. 5985 * 5986 * @param client The remote client to send the listing to. 5987 * @return False if an error occured, true otherwise. 5988 */ 5989 boolean viewServerListWindows(Socket client) { 5990 if (isSystemSecure()) { 5991 return false; 5992 } 5993 5994 boolean result = true; 5995 5996 WindowList windows = new WindowList(); 5997 synchronized (mWindowMap) { 5998 //noinspection unchecked 5999 DisplayContentsIterator iterator = new DisplayContentsIterator(); 6000 while(iterator.hasNext()) { 6001 windows.addAll(iterator.next().getWindowList()); 6002 } 6003 } 6004 6005 BufferedWriter out = null; 6006 6007 // Any uncaught exception will crash the system process 6008 try { 6009 OutputStream clientStream = client.getOutputStream(); 6010 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6011 6012 final int count = windows.size(); 6013 for (int i = 0; i < count; i++) { 6014 final WindowState w = windows.get(i); 6015 out.write(Integer.toHexString(System.identityHashCode(w))); 6016 out.write(' '); 6017 out.append(w.mAttrs.getTitle()); 6018 out.write('\n'); 6019 } 6020 6021 out.write("DONE.\n"); 6022 out.flush(); 6023 } catch (Exception e) { 6024 result = false; 6025 } finally { 6026 if (out != null) { 6027 try { 6028 out.close(); 6029 } catch (IOException e) { 6030 result = false; 6031 } 6032 } 6033 } 6034 6035 return result; 6036 } 6037 6038 // TODO(multidisplay): Extend to multiple displays. 6039 /** 6040 * Returns the focused window in the following format: 6041 * windowHashCodeInHexadecimal windowName 6042 * 6043 * @param client The remote client to send the listing to. 6044 * @return False if an error occurred, true otherwise. 6045 */ 6046 boolean viewServerGetFocusedWindow(Socket client) { 6047 if (isSystemSecure()) { 6048 return false; 6049 } 6050 6051 boolean result = true; 6052 6053 WindowState focusedWindow = getFocusedWindow(); 6054 6055 BufferedWriter out = null; 6056 6057 // Any uncaught exception will crash the system process 6058 try { 6059 OutputStream clientStream = client.getOutputStream(); 6060 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6061 6062 if(focusedWindow != null) { 6063 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 6064 out.write(' '); 6065 out.append(focusedWindow.mAttrs.getTitle()); 6066 } 6067 out.write('\n'); 6068 out.flush(); 6069 } catch (Exception e) { 6070 result = false; 6071 } finally { 6072 if (out != null) { 6073 try { 6074 out.close(); 6075 } catch (IOException e) { 6076 result = false; 6077 } 6078 } 6079 } 6080 6081 return result; 6082 } 6083 6084 /** 6085 * Sends a command to a target window. The result of the command, if any, will be 6086 * written in the output stream of the specified socket. 6087 * 6088 * The parameters must follow this syntax: 6089 * windowHashcode extra 6090 * 6091 * Where XX is the length in characeters of the windowTitle. 6092 * 6093 * The first parameter is the target window. The window with the specified hashcode 6094 * will be the target. If no target can be found, nothing happens. The extra parameters 6095 * will be delivered to the target window and as parameters to the command itself. 6096 * 6097 * @param client The remote client to sent the result, if any, to. 6098 * @param command The command to execute. 6099 * @param parameters The command parameters. 6100 * 6101 * @return True if the command was successfully delivered, false otherwise. This does 6102 * not indicate whether the command itself was successful. 6103 */ 6104 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 6105 if (isSystemSecure()) { 6106 return false; 6107 } 6108 6109 boolean success = true; 6110 Parcel data = null; 6111 Parcel reply = null; 6112 6113 BufferedWriter out = null; 6114 6115 // Any uncaught exception will crash the system process 6116 try { 6117 // Find the hashcode of the window 6118 int index = parameters.indexOf(' '); 6119 if (index == -1) { 6120 index = parameters.length(); 6121 } 6122 final String code = parameters.substring(0, index); 6123 int hashCode = (int) Long.parseLong(code, 16); 6124 6125 // Extract the command's parameter after the window description 6126 if (index < parameters.length()) { 6127 parameters = parameters.substring(index + 1); 6128 } else { 6129 parameters = ""; 6130 } 6131 6132 final WindowState window = findWindow(hashCode); 6133 if (window == null) { 6134 return false; 6135 } 6136 6137 data = Parcel.obtain(); 6138 data.writeInterfaceToken("android.view.IWindow"); 6139 data.writeString(command); 6140 data.writeString(parameters); 6141 data.writeInt(1); 6142 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 6143 6144 reply = Parcel.obtain(); 6145 6146 final IBinder binder = window.mClient.asBinder(); 6147 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 6148 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 6149 6150 reply.readException(); 6151 6152 if (!client.isOutputShutdown()) { 6153 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 6154 out.write("DONE\n"); 6155 out.flush(); 6156 } 6157 6158 } catch (Exception e) { 6159 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); 6160 success = false; 6161 } finally { 6162 if (data != null) { 6163 data.recycle(); 6164 } 6165 if (reply != null) { 6166 reply.recycle(); 6167 } 6168 if (out != null) { 6169 try { 6170 out.close(); 6171 } catch (IOException e) { 6172 6173 } 6174 } 6175 } 6176 6177 return success; 6178 } 6179 6180 public void addWindowChangeListener(WindowChangeListener listener) { 6181 synchronized(mWindowMap) { 6182 mWindowChangeListeners.add(listener); 6183 } 6184 } 6185 6186 public void removeWindowChangeListener(WindowChangeListener listener) { 6187 synchronized(mWindowMap) { 6188 mWindowChangeListeners.remove(listener); 6189 } 6190 } 6191 6192 private void notifyWindowsChanged() { 6193 WindowChangeListener[] windowChangeListeners; 6194 synchronized(mWindowMap) { 6195 if(mWindowChangeListeners.isEmpty()) { 6196 return; 6197 } 6198 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6199 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6200 } 6201 int N = windowChangeListeners.length; 6202 for(int i = 0; i < N; i++) { 6203 windowChangeListeners[i].windowsChanged(); 6204 } 6205 } 6206 6207 private void notifyFocusChanged() { 6208 WindowChangeListener[] windowChangeListeners; 6209 synchronized(mWindowMap) { 6210 if(mWindowChangeListeners.isEmpty()) { 6211 return; 6212 } 6213 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6214 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6215 } 6216 int N = windowChangeListeners.length; 6217 for(int i = 0; i < N; i++) { 6218 windowChangeListeners[i].focusChanged(); 6219 } 6220 } 6221 6222 private WindowState findWindow(int hashCode) { 6223 if (hashCode == -1) { 6224 // TODO(multidisplay): Extend to multiple displays. 6225 return getFocusedWindow(); 6226 } 6227 6228 synchronized (mWindowMap) { 6229 final AllWindowsIterator iterator = new AllWindowsIterator(); 6230 while (iterator.hasNext()) { 6231 final WindowState w = iterator.next(); 6232 if (System.identityHashCode(w) == hashCode) { 6233 return w; 6234 } 6235 } 6236 } 6237 6238 return null; 6239 } 6240 6241 /* 6242 * Instruct the Activity Manager to fetch the current configuration and broadcast 6243 * that to config-changed listeners if appropriate. 6244 */ 6245 void sendNewConfiguration() { 6246 try { 6247 mActivityManager.updateConfiguration(null); 6248 } catch (RemoteException e) { 6249 } 6250 } 6251 6252 public Configuration computeNewConfiguration() { 6253 synchronized (mWindowMap) { 6254 Configuration config = computeNewConfigurationLocked(); 6255 if (config == null && mWaitingForConfig) { 6256 // Nothing changed but we are waiting for something... stop that! 6257 mWaitingForConfig = false; 6258 mLastFinishedFreezeSource = "new-config"; 6259 performLayoutAndPlaceSurfacesLocked(); 6260 } 6261 return config; 6262 } 6263 } 6264 6265 Configuration computeNewConfigurationLocked() { 6266 Configuration config = new Configuration(); 6267 config.fontScale = 0; 6268 if (!computeScreenConfigurationLocked(config)) { 6269 return null; 6270 } 6271 return config; 6272 } 6273 6274 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) { 6275 // TODO: Multidisplay: for now only use with default display. 6276 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation); 6277 if (width < displayInfo.smallestNominalAppWidth) { 6278 displayInfo.smallestNominalAppWidth = width; 6279 } 6280 if (width > displayInfo.largestNominalAppWidth) { 6281 displayInfo.largestNominalAppWidth = width; 6282 } 6283 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation); 6284 if (height < displayInfo.smallestNominalAppHeight) { 6285 displayInfo.smallestNominalAppHeight = height; 6286 } 6287 if (height > displayInfo.largestNominalAppHeight) { 6288 displayInfo.largestNominalAppHeight = height; 6289 } 6290 } 6291 6292 private int reduceConfigLayout(int curLayout, int rotation, float density, 6293 int dw, int dh) { 6294 // TODO: Multidisplay: for now only use with default display. 6295 // Get the app screen size at this rotation. 6296 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6297 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6298 6299 // Compute the screen layout size class for this rotation. 6300 int longSize = w; 6301 int shortSize = h; 6302 if (longSize < shortSize) { 6303 int tmp = longSize; 6304 longSize = shortSize; 6305 shortSize = tmp; 6306 } 6307 longSize = (int)(longSize/density); 6308 shortSize = (int)(shortSize/density); 6309 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 6310 } 6311 6312 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 6313 int dw, int dh, float density, Configuration outConfig) { 6314 // TODO: Multidisplay: for now only use with default display. 6315 6316 // We need to determine the smallest width that will occur under normal 6317 // operation. To this, start with the base screen size and compute the 6318 // width under the different possible rotations. We need to un-rotate 6319 // the current screen dimensions before doing this. 6320 int unrotDw, unrotDh; 6321 if (rotated) { 6322 unrotDw = dh; 6323 unrotDh = dw; 6324 } else { 6325 unrotDw = dw; 6326 unrotDh = dh; 6327 } 6328 displayInfo.smallestNominalAppWidth = 1<<30; 6329 displayInfo.smallestNominalAppHeight = 1<<30; 6330 displayInfo.largestNominalAppWidth = 0; 6331 displayInfo.largestNominalAppHeight = 0; 6332 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh); 6333 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw); 6334 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh); 6335 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw); 6336 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 6337 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh); 6338 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw); 6339 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); 6340 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); 6341 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 6342 outConfig.screenLayout = sl; 6343 } 6344 6345 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, 6346 int dw, int dh) { 6347 // TODO: Multidisplay: for now only use with default display. 6348 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6349 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6350 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 6351 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 6352 if (curSize == 0 || size < curSize) { 6353 curSize = size; 6354 } 6355 return curSize; 6356 } 6357 6358 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) { 6359 // TODO: Multidisplay: for now only use with default display. 6360 mTmpDisplayMetrics.setTo(dm); 6361 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 6362 final int unrotDw, unrotDh; 6363 if (rotated) { 6364 unrotDw = dh; 6365 unrotDh = dw; 6366 } else { 6367 unrotDw = dw; 6368 unrotDh = dh; 6369 } 6370 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh); 6371 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw); 6372 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh); 6373 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw); 6374 return sw; 6375 } 6376 6377 boolean computeScreenConfigurationLocked(Configuration config) { 6378 if (!mDisplayReady) { 6379 return false; 6380 } 6381 6382 // TODO(multidisplay): For now, apply Configuration to main screen only. 6383 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6384 6385 // Use the effective "visual" dimensions based on current rotation 6386 final boolean rotated = (mRotation == Surface.ROTATION_90 6387 || mRotation == Surface.ROTATION_270); 6388 final int realdw = rotated ? 6389 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; 6390 final int realdh = rotated ? 6391 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; 6392 int dw = realdw; 6393 int dh = realdh; 6394 6395 if (mAltOrientation) { 6396 if (realdw > realdh) { 6397 // Turn landscape into portrait. 6398 int maxw = (int)(realdh/1.3f); 6399 if (maxw < realdw) { 6400 dw = maxw; 6401 } 6402 } else { 6403 // Turn portrait into landscape. 6404 int maxh = (int)(realdw/1.3f); 6405 if (maxh < realdh) { 6406 dh = maxh; 6407 } 6408 } 6409 } 6410 6411 if (config != null) { 6412 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : 6413 Configuration.ORIENTATION_LANDSCAPE; 6414 } 6415 6416 // Update application display metrics. 6417 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); 6418 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); 6419 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6420 synchronized(displayContent.mDisplaySizeLock) { 6421 displayInfo.rotation = mRotation; 6422 displayInfo.logicalWidth = dw; 6423 displayInfo.logicalHeight = dh; 6424 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; 6425 displayInfo.appWidth = appWidth; 6426 displayInfo.appHeight = appHeight; 6427 displayInfo.getLogicalMetrics(mRealDisplayMetrics, null); 6428 displayInfo.getAppMetrics(mDisplayMetrics, null); 6429 mDisplayManagerService.setDisplayInfoOverrideFromWindowManager( 6430 displayContent.getDisplayId(), displayInfo); 6431 } 6432 if (false) { 6433 Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); 6434 } 6435 6436 final DisplayMetrics dm = mDisplayMetrics; 6437 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, 6438 mCompatDisplayMetrics); 6439 6440 if (config != null) { 6441 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) 6442 / dm.density); 6443 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) 6444 / dm.density); 6445 computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config); 6446 6447 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 6448 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 6449 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); 6450 config.densityDpi = displayContent.mBaseDisplayDensity; 6451 6452 // Update the configuration based on available input devices, lid switch, 6453 // and platform configuration. 6454 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6455 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6456 config.navigation = Configuration.NAVIGATION_NONAV; 6457 6458 int keyboardPresence = 0; 6459 int navigationPresence = 0; 6460 final InputDevice[] devices = mInputManager.getInputDevices(); 6461 final int len = devices.length; 6462 for (int i = 0; i < len; i++) { 6463 InputDevice device = devices[i]; 6464 if (!device.isVirtual()) { 6465 final int sources = device.getSources(); 6466 final int presenceFlag = device.isExternal() ? 6467 WindowManagerPolicy.PRESENCE_EXTERNAL : 6468 WindowManagerPolicy.PRESENCE_INTERNAL; 6469 6470 if (mIsTouchDevice) { 6471 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 6472 InputDevice.SOURCE_TOUCHSCREEN) { 6473 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 6474 } 6475 } else { 6476 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6477 } 6478 6479 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 6480 config.navigation = Configuration.NAVIGATION_TRACKBALL; 6481 navigationPresence |= presenceFlag; 6482 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 6483 && config.navigation == Configuration.NAVIGATION_NONAV) { 6484 config.navigation = Configuration.NAVIGATION_DPAD; 6485 navigationPresence |= presenceFlag; 6486 } 6487 6488 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 6489 config.keyboard = Configuration.KEYBOARD_QWERTY; 6490 keyboardPresence |= presenceFlag; 6491 } 6492 } 6493 } 6494 6495 // Determine whether a hard keyboard is available and enabled. 6496 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 6497 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 6498 mHardKeyboardAvailable = hardKeyboardAvailable; 6499 mHardKeyboardEnabled = hardKeyboardAvailable; 6500 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6501 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6502 } 6503 if (!mHardKeyboardEnabled) { 6504 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6505 } 6506 6507 // Let the policy update hidden states. 6508 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 6509 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 6510 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 6511 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 6512 } 6513 6514 return true; 6515 } 6516 6517 public boolean isHardKeyboardAvailable() { 6518 synchronized (mWindowMap) { 6519 return mHardKeyboardAvailable; 6520 } 6521 } 6522 6523 public boolean isHardKeyboardEnabled() { 6524 synchronized (mWindowMap) { 6525 return mHardKeyboardEnabled; 6526 } 6527 } 6528 6529 public void setHardKeyboardEnabled(boolean enabled) { 6530 synchronized (mWindowMap) { 6531 if (mHardKeyboardEnabled != enabled) { 6532 mHardKeyboardEnabled = enabled; 6533 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6534 } 6535 } 6536 } 6537 6538 public void setOnHardKeyboardStatusChangeListener( 6539 OnHardKeyboardStatusChangeListener listener) { 6540 synchronized (mWindowMap) { 6541 mHardKeyboardStatusChangeListener = listener; 6542 } 6543 } 6544 6545 void notifyHardKeyboardStatusChange() { 6546 final boolean available, enabled; 6547 final OnHardKeyboardStatusChangeListener listener; 6548 synchronized (mWindowMap) { 6549 listener = mHardKeyboardStatusChangeListener; 6550 available = mHardKeyboardAvailable; 6551 enabled = mHardKeyboardEnabled; 6552 } 6553 if (listener != null) { 6554 listener.onHardKeyboardStatusChange(available, enabled); 6555 } 6556 } 6557 6558 // ------------------------------------------------------------- 6559 // Drag and drop 6560 // ------------------------------------------------------------- 6561 6562 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 6563 int flags, int width, int height, Surface outSurface) { 6564 if (DEBUG_DRAG) { 6565 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 6566 + " flags=" + Integer.toHexString(flags) + " win=" + window 6567 + " asbinder=" + window.asBinder()); 6568 } 6569 6570 final int callerPid = Binder.getCallingPid(); 6571 final long origId = Binder.clearCallingIdentity(); 6572 IBinder token = null; 6573 6574 try { 6575 synchronized (mWindowMap) { 6576 try { 6577 if (mDragState == null) { 6578 // TODO(multi-display): support other displays 6579 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6580 final Display display = displayContent.getDisplay(); 6581 SurfaceControl surface = new SurfaceControl(session, "drag surface", 6582 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 6583 surface.setLayerStack(display.getLayerStack()); 6584 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 6585 + surface + ": CREATE"); 6586 outSurface.copyFrom(surface); 6587 final IBinder winBinder = window.asBinder(); 6588 token = new Binder(); 6589 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 6590 token = mDragState.mToken = new Binder(); 6591 6592 // 5 second timeout for this window to actually begin the drag 6593 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 6594 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 6595 mH.sendMessageDelayed(msg, 5000); 6596 } else { 6597 Slog.w(TAG, "Drag already in progress"); 6598 } 6599 } catch (SurfaceControl.OutOfResourcesException e) { 6600 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 6601 if (mDragState != null) { 6602 mDragState.reset(); 6603 mDragState = null; 6604 } 6605 } 6606 } 6607 } finally { 6608 Binder.restoreCallingIdentity(origId); 6609 } 6610 6611 return token; 6612 } 6613 6614 // ------------------------------------------------------------- 6615 // Input Events and Focus Management 6616 // ------------------------------------------------------------- 6617 6618 final InputMonitor mInputMonitor = new InputMonitor(this); 6619 private boolean mEventDispatchingEnabled; 6620 6621 @Override 6622 public void pauseKeyDispatching(IBinder _token) { 6623 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6624 "pauseKeyDispatching()")) { 6625 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6626 } 6627 6628 synchronized (mWindowMap) { 6629 WindowToken token = mTokenMap.get(_token); 6630 if (token != null) { 6631 mInputMonitor.pauseDispatchingLw(token); 6632 } 6633 } 6634 } 6635 6636 @Override 6637 public void resumeKeyDispatching(IBinder _token) { 6638 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6639 "resumeKeyDispatching()")) { 6640 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6641 } 6642 6643 synchronized (mWindowMap) { 6644 WindowToken token = mTokenMap.get(_token); 6645 if (token != null) { 6646 mInputMonitor.resumeDispatchingLw(token); 6647 } 6648 } 6649 } 6650 6651 @Override 6652 public void setEventDispatching(boolean enabled) { 6653 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6654 "setEventDispatching()")) { 6655 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6656 } 6657 6658 synchronized (mWindowMap) { 6659 mEventDispatchingEnabled = enabled; 6660 if (mDisplayEnabled) { 6661 mInputMonitor.setEventDispatchingLw(enabled); 6662 } 6663 sendScreenStatusToClientsLocked(); 6664 } 6665 } 6666 6667 @Override 6668 public IBinder getFocusedWindowToken() { 6669 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 6670 "getFocusedWindowToken()")) { 6671 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission."); 6672 } 6673 synchronized (mWindowMap) { 6674 WindowState windowState = getFocusedWindowLocked(); 6675 if (windowState != null) { 6676 return windowState.mClient.asBinder(); 6677 } 6678 return null; 6679 } 6680 } 6681 6682 private WindowState getFocusedWindow() { 6683 synchronized (mWindowMap) { 6684 return getFocusedWindowLocked(); 6685 } 6686 } 6687 6688 private WindowState getFocusedWindowLocked() { 6689 return mCurrentFocus; 6690 } 6691 6692 public boolean detectSafeMode() { 6693 if (!mInputMonitor.waitForInputDevicesReady( 6694 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 6695 Slog.w(TAG, "Devices still not ready after waiting " 6696 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 6697 + " milliseconds before attempting to detect safe mode."); 6698 } 6699 6700 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 6701 KeyEvent.KEYCODE_MENU); 6702 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 6703 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 6704 KeyEvent.KEYCODE_DPAD_CENTER); 6705 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 6706 InputManagerService.BTN_MOUSE); 6707 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 6708 KeyEvent.KEYCODE_VOLUME_DOWN); 6709 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 6710 || volumeDownState > 0; 6711 try { 6712 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 6713 mSafeMode = true; 6714 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 6715 } 6716 } catch (IllegalArgumentException e) { 6717 } 6718 if (mSafeMode) { 6719 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 6720 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 6721 } else { 6722 Log.i(TAG, "SAFE MODE not enabled"); 6723 } 6724 mPolicy.setSafeMode(mSafeMode); 6725 return mSafeMode; 6726 } 6727 6728 public void displayReady() { 6729 displayReady(Display.DEFAULT_DISPLAY); 6730 6731 synchronized(mWindowMap) { 6732 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6733 readForcedDisplaySizeAndDensityLocked(displayContent); 6734 6735 mDisplayReady = true; 6736 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 6737 PackageManager.FEATURE_TOUCHSCREEN); 6738 6739 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 6740 displayContent.mInitialDisplayWidth, 6741 displayContent.mInitialDisplayHeight, 6742 displayContent.mInitialDisplayDensity); 6743 } 6744 6745 try { 6746 mActivityManager.updateConfiguration(null); 6747 } catch (RemoteException e) { 6748 } 6749 } 6750 6751 private void displayReady(int displayId) { 6752 synchronized(mWindowMap) { 6753 final DisplayContent displayContent = getDisplayContentLocked(displayId); 6754 if (displayContent != null) { 6755 mAnimator.addDisplayLocked(displayId); 6756 synchronized(displayContent.mDisplaySizeLock) { 6757 // Bootstrap the default logical display from the display manager. 6758 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6759 DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId); 6760 if (newDisplayInfo != null) { 6761 displayInfo.copyFrom(newDisplayInfo); 6762 } 6763 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; 6764 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; 6765 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; 6766 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; 6767 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; 6768 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; 6769 } 6770 } 6771 } 6772 } 6773 6774 public void systemReady() { 6775 mPolicy.systemReady(); 6776 } 6777 6778 // TODO(multidisplay): Call isScreenOn for each display. 6779 private void sendScreenStatusToClientsLocked() { 6780 final boolean on = mPowerManager.isScreenOn(); 6781 final AllWindowsIterator iterator = new AllWindowsIterator(); 6782 while (iterator.hasNext()) { 6783 try { 6784 iterator.next().mClient.dispatchScreenState(on); 6785 } catch (RemoteException e) { 6786 // Ignored 6787 } 6788 } 6789 } 6790 6791 // ------------------------------------------------------------- 6792 // Async Handler 6793 // ------------------------------------------------------------- 6794 6795 final class H extends Handler { 6796 public static final int REPORT_FOCUS_CHANGE = 2; 6797 public static final int REPORT_LOSING_FOCUS = 3; 6798 public static final int DO_TRAVERSAL = 4; 6799 public static final int ADD_STARTING = 5; 6800 public static final int REMOVE_STARTING = 6; 6801 public static final int FINISHED_STARTING = 7; 6802 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 6803 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 6804 public static final int WINDOW_FREEZE_TIMEOUT = 11; 6805 6806 public static final int APP_TRANSITION_TIMEOUT = 13; 6807 public static final int PERSIST_ANIMATION_SCALE = 14; 6808 public static final int FORCE_GC = 15; 6809 public static final int ENABLE_SCREEN = 16; 6810 public static final int APP_FREEZE_TIMEOUT = 17; 6811 public static final int SEND_NEW_CONFIGURATION = 18; 6812 public static final int REPORT_WINDOWS_CHANGE = 19; 6813 public static final int DRAG_START_TIMEOUT = 20; 6814 public static final int DRAG_END_TIMEOUT = 21; 6815 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 6816 public static final int BOOT_TIMEOUT = 23; 6817 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 6818 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 6819 public static final int DO_ANIMATION_CALLBACK = 26; 6820 6821 public static final int DO_DISPLAY_ADDED = 27; 6822 public static final int DO_DISPLAY_REMOVED = 28; 6823 public static final int DO_DISPLAY_CHANGED = 29; 6824 6825 public static final int CLIENT_FREEZE_TIMEOUT = 30; 6826 6827 @Override 6828 public void handleMessage(Message msg) { 6829 if (DEBUG_WINDOW_TRACE) { 6830 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 6831 } 6832 switch (msg.what) { 6833 case REPORT_FOCUS_CHANGE: { 6834 WindowState lastFocus; 6835 WindowState newFocus; 6836 6837 synchronized(mWindowMap) { 6838 lastFocus = mLastFocus; 6839 newFocus = mCurrentFocus; 6840 if (lastFocus == newFocus) { 6841 // Focus is not changing, so nothing to do. 6842 return; 6843 } 6844 mLastFocus = newFocus; 6845 //Slog.i(TAG, "Focus moving from " + lastFocus 6846 // + " to " + newFocus); 6847 if (newFocus != null && lastFocus != null 6848 && !newFocus.isDisplayedLw()) { 6849 //Slog.i(TAG, "Delaying loss of focus..."); 6850 mLosingFocus.add(lastFocus); 6851 lastFocus = null; 6852 } 6853 } 6854 6855 if (lastFocus != newFocus) { 6856 //System.out.println("Changing focus from " + lastFocus 6857 // + " to " + newFocus); 6858 if (newFocus != null) { 6859 //Slog.i(TAG, "Gaining focus: " + newFocus); 6860 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 6861 notifyFocusChanged(); 6862 } 6863 6864 if (lastFocus != null) { 6865 //Slog.i(TAG, "Losing focus: " + lastFocus); 6866 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 6867 } 6868 } 6869 } break; 6870 6871 case REPORT_LOSING_FOCUS: { 6872 ArrayList<WindowState> losers; 6873 6874 synchronized(mWindowMap) { 6875 losers = mLosingFocus; 6876 mLosingFocus = new ArrayList<WindowState>(); 6877 } 6878 6879 final int N = losers.size(); 6880 for (int i=0; i<N; i++) { 6881 //Slog.i(TAG, "Losing delayed focus: " + losers.get(i)); 6882 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 6883 } 6884 } break; 6885 6886 case DO_TRAVERSAL: { 6887 synchronized(mWindowMap) { 6888 mTraversalScheduled = false; 6889 performLayoutAndPlaceSurfacesLocked(); 6890 } 6891 } break; 6892 6893 case ADD_STARTING: { 6894 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 6895 final StartingData sd = wtoken.startingData; 6896 6897 if (sd == null) { 6898 // Animation has been canceled... do nothing. 6899 return; 6900 } 6901 6902 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 6903 + wtoken + ": pkg=" + sd.pkg); 6904 6905 View view = null; 6906 try { 6907 view = mPolicy.addStartingWindow( 6908 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 6909 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.windowFlags); 6910 } catch (Exception e) { 6911 Slog.w(TAG, "Exception when adding starting window", e); 6912 } 6913 6914 if (view != null) { 6915 boolean abort = false; 6916 6917 synchronized(mWindowMap) { 6918 if (wtoken.removed || wtoken.startingData == null) { 6919 // If the window was successfully added, then 6920 // we need to remove it. 6921 if (wtoken.startingWindow != null) { 6922 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 6923 "Aborted starting " + wtoken 6924 + ": removed=" + wtoken.removed 6925 + " startingData=" + wtoken.startingData); 6926 wtoken.startingWindow = null; 6927 wtoken.startingData = null; 6928 abort = true; 6929 } 6930 } else { 6931 wtoken.startingView = view; 6932 } 6933 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 6934 "Added starting " + wtoken 6935 + ": startingWindow=" 6936 + wtoken.startingWindow + " startingView=" 6937 + wtoken.startingView); 6938 } 6939 6940 if (abort) { 6941 try { 6942 mPolicy.removeStartingWindow(wtoken.token, view); 6943 } catch (Exception e) { 6944 Slog.w(TAG, "Exception when removing starting window", e); 6945 } 6946 } 6947 } 6948 } break; 6949 6950 case REMOVE_STARTING: { 6951 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 6952 IBinder token = null; 6953 View view = null; 6954 synchronized (mWindowMap) { 6955 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 6956 + wtoken + ": startingWindow=" 6957 + wtoken.startingWindow + " startingView=" 6958 + wtoken.startingView); 6959 if (wtoken.startingWindow != null) { 6960 view = wtoken.startingView; 6961 token = wtoken.token; 6962 wtoken.startingData = null; 6963 wtoken.startingView = null; 6964 wtoken.startingWindow = null; 6965 wtoken.startingDisplayed = false; 6966 } 6967 } 6968 if (view != null) { 6969 try { 6970 mPolicy.removeStartingWindow(token, view); 6971 } catch (Exception e) { 6972 Slog.w(TAG, "Exception when removing starting window", e); 6973 } 6974 } 6975 } break; 6976 6977 case FINISHED_STARTING: { 6978 IBinder token = null; 6979 View view = null; 6980 while (true) { 6981 synchronized (mWindowMap) { 6982 final int N = mFinishedStarting.size(); 6983 if (N <= 0) { 6984 break; 6985 } 6986 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 6987 6988 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 6989 "Finished starting " + wtoken 6990 + ": startingWindow=" + wtoken.startingWindow 6991 + " startingView=" + wtoken.startingView); 6992 6993 if (wtoken.startingWindow == null) { 6994 continue; 6995 } 6996 6997 view = wtoken.startingView; 6998 token = wtoken.token; 6999 wtoken.startingData = null; 7000 wtoken.startingView = null; 7001 wtoken.startingWindow = null; 7002 wtoken.startingDisplayed = false; 7003 } 7004 7005 try { 7006 mPolicy.removeStartingWindow(token, view); 7007 } catch (Exception e) { 7008 Slog.w(TAG, "Exception when removing starting window", e); 7009 } 7010 } 7011 } break; 7012 7013 case REPORT_APPLICATION_TOKEN_DRAWN: { 7014 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7015 7016 try { 7017 if (DEBUG_VISIBILITY) Slog.v( 7018 TAG, "Reporting drawn in " + wtoken); 7019 wtoken.appToken.windowsDrawn(); 7020 } catch (RemoteException ex) { 7021 } 7022 } break; 7023 7024 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7025 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7026 7027 boolean nowVisible = msg.arg1 != 0; 7028 boolean nowGone = msg.arg2 != 0; 7029 7030 try { 7031 if (DEBUG_VISIBILITY) Slog.v( 7032 TAG, "Reporting visible in " + wtoken 7033 + " visible=" + nowVisible 7034 + " gone=" + nowGone); 7035 if (nowVisible) { 7036 wtoken.appToken.windowsVisible(); 7037 } else { 7038 wtoken.appToken.windowsGone(); 7039 } 7040 } catch (RemoteException ex) { 7041 } 7042 } break; 7043 7044 case WINDOW_FREEZE_TIMEOUT: { 7045 // TODO(multidisplay): Can non-default displays rotate? 7046 synchronized (mWindowMap) { 7047 Slog.w(TAG, "Window freeze timeout expired."); 7048 final WindowList windows = getDefaultWindowListLocked(); 7049 int i = windows.size(); 7050 while (i > 0) { 7051 i--; 7052 WindowState w = windows.get(i); 7053 if (w.mOrientationChanging) { 7054 w.mOrientationChanging = false; 7055 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 7056 - mDisplayFreezeTime); 7057 Slog.w(TAG, "Force clearing orientation change: " + w); 7058 } 7059 } 7060 performLayoutAndPlaceSurfacesLocked(); 7061 } 7062 break; 7063 } 7064 7065 case APP_TRANSITION_TIMEOUT: { 7066 synchronized (mWindowMap) { 7067 if (mAppTransition.isTransitionSet()) { 7068 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT"); 7069 mAppTransition.setTimeout(); 7070 mAnimatingAppTokens.clear(); 7071 mAnimatingAppTokens.addAll(mAppTokens); 7072 performLayoutAndPlaceSurfacesLocked(); 7073 } 7074 } 7075 break; 7076 } 7077 7078 case PERSIST_ANIMATION_SCALE: { 7079 Settings.Global.putFloat(mContext.getContentResolver(), 7080 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); 7081 Settings.Global.putFloat(mContext.getContentResolver(), 7082 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); 7083 Settings.Global.putFloat(mContext.getContentResolver(), 7084 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale); 7085 break; 7086 } 7087 7088 case FORCE_GC: { 7089 synchronized (mWindowMap) { 7090 // Since we're holding both mWindowMap and mAnimator we don't need to 7091 // hold mAnimator.mLayoutToAnim. 7092 if (mAnimator.mAnimating || mAnimationScheduled) { 7093 // If we are animating, don't do the gc now but 7094 // delay a bit so we don't interrupt the animation. 7095 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 7096 return; 7097 } 7098 // If we are currently rotating the display, it will 7099 // schedule a new message when done. 7100 if (mDisplayFrozen) { 7101 return; 7102 } 7103 } 7104 Runtime.getRuntime().gc(); 7105 break; 7106 } 7107 7108 case ENABLE_SCREEN: { 7109 performEnableScreen(); 7110 break; 7111 } 7112 7113 case APP_FREEZE_TIMEOUT: { 7114 synchronized (mWindowMap) { 7115 Slog.w(TAG, "App freeze timeout expired."); 7116 int i = mAppTokens.size(); 7117 while (i > 0) { 7118 i--; 7119 AppWindowToken tok = mAppTokens.get(i); 7120 if (tok.mAppAnimator.freezingScreen) { 7121 Slog.w(TAG, "Force clearing freeze: " + tok); 7122 unsetAppFreezingScreenLocked(tok, true, true); 7123 } 7124 } 7125 } 7126 break; 7127 } 7128 7129 case CLIENT_FREEZE_TIMEOUT: { 7130 synchronized (mWindowMap) { 7131 if (mClientFreezingScreen) { 7132 mClientFreezingScreen = false; 7133 mLastFinishedFreezeSource = "client-timeout"; 7134 stopFreezingDisplayLocked(); 7135 } 7136 } 7137 break; 7138 } 7139 7140 case SEND_NEW_CONFIGURATION: { 7141 removeMessages(SEND_NEW_CONFIGURATION); 7142 sendNewConfiguration(); 7143 break; 7144 } 7145 7146 case REPORT_WINDOWS_CHANGE: { 7147 if (mWindowsChanged) { 7148 synchronized (mWindowMap) { 7149 mWindowsChanged = false; 7150 } 7151 notifyWindowsChanged(); 7152 } 7153 break; 7154 } 7155 7156 case DRAG_START_TIMEOUT: { 7157 IBinder win = (IBinder)msg.obj; 7158 if (DEBUG_DRAG) { 7159 Slog.w(TAG, "Timeout starting drag by win " + win); 7160 } 7161 synchronized (mWindowMap) { 7162 // !!! TODO: ANR the app that has failed to start the drag in time 7163 if (mDragState != null) { 7164 mDragState.unregister(); 7165 mInputMonitor.updateInputWindowsLw(true /*force*/); 7166 mDragState.reset(); 7167 mDragState = null; 7168 } 7169 } 7170 break; 7171 } 7172 7173 case DRAG_END_TIMEOUT: { 7174 IBinder win = (IBinder)msg.obj; 7175 if (DEBUG_DRAG) { 7176 Slog.w(TAG, "Timeout ending drag to win " + win); 7177 } 7178 synchronized (mWindowMap) { 7179 // !!! TODO: ANR the drag-receiving app 7180 if (mDragState != null) { 7181 mDragState.mDragResult = false; 7182 mDragState.endDragLw(); 7183 } 7184 } 7185 break; 7186 } 7187 7188 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7189 notifyHardKeyboardStatusChange(); 7190 break; 7191 } 7192 7193 case BOOT_TIMEOUT: { 7194 performBootTimeout(); 7195 break; 7196 } 7197 7198 case WAITING_FOR_DRAWN_TIMEOUT: { 7199 Pair<WindowState, IRemoteCallback> pair; 7200 synchronized (mWindowMap) { 7201 pair = (Pair<WindowState, IRemoteCallback>)msg.obj; 7202 Slog.w(TAG, "Timeout waiting for drawn: " + pair.first); 7203 if (!mWaitingForDrawn.remove(pair)) { 7204 return; 7205 } 7206 } 7207 try { 7208 pair.second.sendResult(null); 7209 } catch (RemoteException e) { 7210 } 7211 break; 7212 } 7213 7214 case SHOW_STRICT_MODE_VIOLATION: { 7215 showStrictModeViolation(msg.arg1, msg.arg2); 7216 break; 7217 } 7218 7219 case DO_ANIMATION_CALLBACK: { 7220 try { 7221 ((IRemoteCallback)msg.obj).sendResult(null); 7222 } catch (RemoteException e) { 7223 } 7224 break; 7225 } 7226 7227 case DO_DISPLAY_ADDED: 7228 synchronized (mWindowMap) { 7229 handleDisplayAddedLocked(msg.arg1); 7230 } 7231 break; 7232 7233 case DO_DISPLAY_REMOVED: 7234 synchronized (mWindowMap) { 7235 handleDisplayRemovedLocked(msg.arg1); 7236 } 7237 break; 7238 7239 case DO_DISPLAY_CHANGED: 7240 synchronized (mWindowMap) { 7241 handleDisplayChangedLocked(msg.arg1); 7242 } 7243 break; 7244 } 7245 if (DEBUG_WINDOW_TRACE) { 7246 Slog.v(TAG, "handleMessage: exit"); 7247 } 7248 } 7249 } 7250 7251 // ------------------------------------------------------------- 7252 // IWindowManager API 7253 // ------------------------------------------------------------- 7254 7255 @Override 7256 public IWindowSession openSession(IInputMethodClient client, 7257 IInputContext inputContext) { 7258 if (client == null) throw new IllegalArgumentException("null client"); 7259 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7260 Session session = new Session(this, client, inputContext); 7261 return session; 7262 } 7263 7264 @Override 7265 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7266 synchronized (mWindowMap) { 7267 // The focus for the client is the window immediately below 7268 // where we would place the input method window. 7269 int idx = findDesiredInputMethodWindowIndexLocked(false); 7270 if (idx > 0) { 7271 // TODO(multidisplay): IMEs are only supported on the default display. 7272 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 7273 if (DEBUG_INPUT_METHOD) { 7274 Slog.i(TAG, "Desired input method target: " + imFocus); 7275 Slog.i(TAG, "Current focus: " + mCurrentFocus); 7276 Slog.i(TAG, "Last focus: " + mLastFocus); 7277 } 7278 if (imFocus != null) { 7279 // This may be a starting window, in which case we still want 7280 // to count it as okay. 7281 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7282 && imFocus.mAppToken != null) { 7283 // The client has definitely started, so it really should 7284 // have a window in this app token. Let's look for it. 7285 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7286 WindowState w = imFocus.mAppToken.windows.get(i); 7287 if (w != imFocus) { 7288 Log.i(TAG, "Switching to real app window: " + w); 7289 imFocus = w; 7290 break; 7291 } 7292 } 7293 } 7294 if (DEBUG_INPUT_METHOD) { 7295 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7296 if (imFocus.mSession.mClient != null) { 7297 Slog.i(TAG, "IM target client binder: " 7298 + imFocus.mSession.mClient.asBinder()); 7299 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 7300 } 7301 } 7302 if (imFocus.mSession.mClient != null && 7303 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7304 return true; 7305 } 7306 } 7307 } 7308 7309 // Okay, how about this... what is the current focus? 7310 // It seems in some cases we may not have moved the IM 7311 // target window, such as when it was in a pop-up window, 7312 // so let's also look at the current focus. (An example: 7313 // go to Gmail, start searching so the keyboard goes up, 7314 // press home. Sometimes the IME won't go down.) 7315 // Would be nice to fix this more correctly, but it's 7316 // way at the end of a release, and this should be good enough. 7317 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 7318 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7319 return true; 7320 } 7321 } 7322 return false; 7323 } 7324 7325 @Override 7326 public void getInitialDisplaySize(int displayId, Point size) { 7327 synchronized (mWindowMap) { 7328 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7329 if (displayContent != null) { 7330 synchronized(displayContent.mDisplaySizeLock) { 7331 size.x = displayContent.mInitialDisplayWidth; 7332 size.y = displayContent.mInitialDisplayHeight; 7333 } 7334 } 7335 } 7336 } 7337 7338 @Override 7339 public void getBaseDisplaySize(int displayId, Point size) { 7340 synchronized (mWindowMap) { 7341 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7342 if (displayContent != null) { 7343 synchronized(displayContent.mDisplaySizeLock) { 7344 size.x = displayContent.mBaseDisplayWidth; 7345 size.y = displayContent.mBaseDisplayHeight; 7346 } 7347 } 7348 } 7349 } 7350 7351 @Override 7352 public void setForcedDisplaySize(int displayId, int width, int height) { 7353 if (mContext.checkCallingOrSelfPermission( 7354 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7355 PackageManager.PERMISSION_GRANTED) { 7356 throw new SecurityException("Must hold permission " + 7357 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7358 } 7359 if (displayId != Display.DEFAULT_DISPLAY) { 7360 throw new IllegalArgumentException("Can only set the default display"); 7361 } 7362 synchronized(mWindowMap) { 7363 // Set some sort of reasonable bounds on the size of the display that we 7364 // will try to emulate. 7365 final int MIN_WIDTH = 200; 7366 final int MIN_HEIGHT = 200; 7367 final int MAX_SCALE = 2; 7368 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7369 if (displayContent != null) { 7370 width = Math.min(Math.max(width, MIN_WIDTH), 7371 displayContent.mInitialDisplayWidth * MAX_SCALE); 7372 height = Math.min(Math.max(height, MIN_HEIGHT), 7373 displayContent.mInitialDisplayHeight * MAX_SCALE); 7374 setForcedDisplaySizeLocked(displayContent, width, height); 7375 Settings.Global.putString(mContext.getContentResolver(), 7376 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 7377 } 7378 } 7379 } 7380 7381 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 7382 final String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 7383 Settings.Global.DISPLAY_SIZE_FORCED); 7384 if (sizeStr != null && sizeStr.length() > 0) { 7385 final int pos = sizeStr.indexOf(','); 7386 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 7387 int width, height; 7388 try { 7389 width = Integer.parseInt(sizeStr.substring(0, pos)); 7390 height = Integer.parseInt(sizeStr.substring(pos+1)); 7391 synchronized(displayContent.mDisplaySizeLock) { 7392 if (displayContent.mBaseDisplayWidth != width 7393 || displayContent.mBaseDisplayHeight != height) { 7394 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 7395 displayContent.mBaseDisplayWidth = width; 7396 displayContent.mBaseDisplayHeight = height; 7397 } 7398 } 7399 } catch (NumberFormatException ex) { 7400 } 7401 } 7402 } 7403 final String densityStr = Settings.Global.getString(mContext.getContentResolver(), 7404 Settings.Global.DISPLAY_DENSITY_FORCED); 7405 if (densityStr != null && densityStr.length() > 0) { 7406 int density; 7407 try { 7408 density = Integer.parseInt(densityStr); 7409 synchronized(displayContent.mDisplaySizeLock) { 7410 if (displayContent.mBaseDisplayDensity != density) { 7411 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 7412 displayContent.mBaseDisplayDensity = density; 7413 } 7414 } 7415 } catch (NumberFormatException ex) { 7416 } 7417 } 7418 } 7419 7420 // displayContent must not be null 7421 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 7422 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7423 7424 synchronized(displayContent.mDisplaySizeLock) { 7425 displayContent.mBaseDisplayWidth = width; 7426 displayContent.mBaseDisplayHeight = height; 7427 } 7428 reconfigureDisplayLocked(displayContent); 7429 } 7430 7431 @Override 7432 public void clearForcedDisplaySize(int displayId) { 7433 if (mContext.checkCallingOrSelfPermission( 7434 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7435 PackageManager.PERMISSION_GRANTED) { 7436 throw new SecurityException("Must hold permission " + 7437 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7438 } 7439 if (displayId != Display.DEFAULT_DISPLAY) { 7440 throw new IllegalArgumentException("Can only set the default display"); 7441 } 7442 synchronized(mWindowMap) { 7443 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7444 if (displayContent != null) { 7445 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 7446 displayContent.mInitialDisplayHeight); 7447 Settings.Global.putString(mContext.getContentResolver(), 7448 Settings.Global.DISPLAY_SIZE_FORCED, ""); 7449 } 7450 } 7451 } 7452 7453 @Override 7454 public int getInitialDisplayDensity(int displayId) { 7455 synchronized (mWindowMap) { 7456 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7457 if (displayContent != null) { 7458 synchronized(displayContent.mDisplaySizeLock) { 7459 return displayContent.mInitialDisplayDensity; 7460 } 7461 } 7462 } 7463 return -1; 7464 } 7465 7466 @Override 7467 public int getBaseDisplayDensity(int displayId) { 7468 synchronized (mWindowMap) { 7469 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7470 if (displayContent != null) { 7471 synchronized(displayContent.mDisplaySizeLock) { 7472 return displayContent.mBaseDisplayDensity; 7473 } 7474 } 7475 } 7476 return -1; 7477 } 7478 7479 @Override 7480 public void setForcedDisplayDensity(int displayId, int density) { 7481 if (mContext.checkCallingOrSelfPermission( 7482 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7483 PackageManager.PERMISSION_GRANTED) { 7484 throw new SecurityException("Must hold permission " + 7485 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7486 } 7487 if (displayId != Display.DEFAULT_DISPLAY) { 7488 throw new IllegalArgumentException("Can only set the default display"); 7489 } 7490 synchronized(mWindowMap) { 7491 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7492 if (displayContent != null) { 7493 setForcedDisplayDensityLocked(displayContent, density); 7494 Settings.Global.putString(mContext.getContentResolver(), 7495 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 7496 } 7497 } 7498 } 7499 7500 // displayContent must not be null 7501 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 7502 Slog.i(TAG, "Using new display density: " + density); 7503 7504 synchronized(displayContent.mDisplaySizeLock) { 7505 displayContent.mBaseDisplayDensity = density; 7506 } 7507 reconfigureDisplayLocked(displayContent); 7508 } 7509 7510 @Override 7511 public void clearForcedDisplayDensity(int displayId) { 7512 if (mContext.checkCallingOrSelfPermission( 7513 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7514 PackageManager.PERMISSION_GRANTED) { 7515 throw new SecurityException("Must hold permission " + 7516 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7517 } 7518 if (displayId != Display.DEFAULT_DISPLAY) { 7519 throw new IllegalArgumentException("Can only set the default display"); 7520 } 7521 synchronized(mWindowMap) { 7522 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7523 if (displayContent != null) { 7524 setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity); 7525 Settings.Global.putString(mContext.getContentResolver(), 7526 Settings.Global.DISPLAY_DENSITY_FORCED, ""); 7527 } 7528 } 7529 } 7530 7531 // displayContent must not be null 7532 private void reconfigureDisplayLocked(DisplayContent displayContent) { 7533 // TODO: Multidisplay: for now only use with default display. 7534 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 7535 displayContent.mBaseDisplayWidth, 7536 displayContent.mBaseDisplayHeight, 7537 displayContent.mBaseDisplayDensity); 7538 7539 displayContent.layoutNeeded = true; 7540 7541 boolean configChanged = updateOrientationFromAppTokensLocked(false); 7542 mTempConfiguration.setToDefaults(); 7543 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 7544 if (computeScreenConfigurationLocked(mTempConfiguration)) { 7545 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 7546 configChanged = true; 7547 } 7548 } 7549 7550 if (configChanged) { 7551 mWaitingForConfig = true; 7552 startFreezingDisplayLocked(false, 0, 0); 7553 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 7554 } 7555 7556 performLayoutAndPlaceSurfacesLocked(); 7557 } 7558 7559 @Override 7560 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 7561 if (mContext.checkCallingOrSelfPermission( 7562 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7563 PackageManager.PERMISSION_GRANTED) { 7564 throw new SecurityException("Must hold permission " + 7565 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7566 } 7567 synchronized(mWindowMap) { 7568 DisplayContent displayContent = getDisplayContentLocked(displayId); 7569 if (displayContent != null) { 7570 mDisplayManagerService.setOverscan(displayId, left, top, right, bottom); 7571 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7572 synchronized(displayContent.mDisplaySizeLock) { 7573 displayInfo.overscanLeft = left; 7574 displayInfo.overscanTop = top; 7575 displayInfo.overscanRight = right; 7576 displayInfo.overscanBottom = bottom; 7577 } 7578 mPolicy.setDisplayOverscan(displayContent.getDisplay(), left, top, right, bottom); 7579 displayContent.layoutNeeded = true; 7580 mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom); 7581 mDisplaySettings.writeSettingsLocked(); 7582 performLayoutAndPlaceSurfacesLocked(); 7583 } 7584 } 7585 } 7586 7587 @Override 7588 public boolean hasSystemNavBar() { 7589 return mPolicy.hasSystemNavBar(); 7590 } 7591 7592 // ------------------------------------------------------------- 7593 // Internals 7594 // ------------------------------------------------------------- 7595 7596 final WindowState windowForClientLocked(Session session, IWindow client, 7597 boolean throwOnError) { 7598 return windowForClientLocked(session, client.asBinder(), throwOnError); 7599 } 7600 7601 final WindowState windowForClientLocked(Session session, IBinder client, 7602 boolean throwOnError) { 7603 WindowState win = mWindowMap.get(client); 7604 if (localLOGV) Slog.v( 7605 TAG, "Looking up client " + client + ": " + win); 7606 if (win == null) { 7607 RuntimeException ex = new IllegalArgumentException( 7608 "Requested window " + client + " does not exist"); 7609 if (throwOnError) { 7610 throw ex; 7611 } 7612 Slog.w(TAG, "Failed looking up window", ex); 7613 return null; 7614 } 7615 if (session != null && win.mSession != session) { 7616 RuntimeException ex = new IllegalArgumentException( 7617 "Requested window " + client + " is in session " + 7618 win.mSession + ", not " + session); 7619 if (throwOnError) { 7620 throw ex; 7621 } 7622 Slog.w(TAG, "Failed looking up window", ex); 7623 return null; 7624 } 7625 7626 return win; 7627 } 7628 7629 final void rebuildAppWindowListLocked() { 7630 DisplayContentsIterator iterator = new DisplayContentsIterator(); 7631 while (iterator.hasNext()) { 7632 rebuildAppWindowListLocked(iterator.next()); 7633 } 7634 } 7635 7636 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 7637 final WindowList windows = displayContent.getWindowList(); 7638 int NW = windows.size(); 7639 int i; 7640 int lastBelow = -1; 7641 int numRemoved = 0; 7642 7643 if (mRebuildTmp.length < NW) { 7644 mRebuildTmp = new WindowState[NW+10]; 7645 } 7646 7647 // First remove all existing app windows. 7648 i=0; 7649 while (i < NW) { 7650 WindowState w = windows.get(i); 7651 if (w.mAppToken != null) { 7652 WindowState win = windows.remove(i); 7653 win.mRebuilding = true; 7654 mRebuildTmp[numRemoved] = win; 7655 mWindowsChanged = true; 7656 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 7657 "Rebuild removing window: " + win); 7658 NW--; 7659 numRemoved++; 7660 continue; 7661 } else if (lastBelow == i-1) { 7662 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 7663 lastBelow = i; 7664 } 7665 } 7666 i++; 7667 } 7668 7669 // Keep whatever windows were below the app windows still below, 7670 // by skipping them. 7671 lastBelow++; 7672 i = lastBelow; 7673 7674 // First add all of the exiting app tokens... these are no longer 7675 // in the main app list, but still have windows shown. We put them 7676 // in the back because now that the animation is over we no longer 7677 // will care about them. 7678 int NT = mExitingAppTokens.size(); 7679 for (int j=0; j<NT; j++) { 7680 i = reAddAppWindowsLocked(displayContent, i, mExitingAppTokens.get(j)); 7681 } 7682 7683 // And add in the still active app tokens in Z order. 7684 NT = mAnimatingAppTokens.size(); 7685 for (int j=0; j<NT; j++) { 7686 i = reAddAppWindowsLocked(displayContent, i, mAnimatingAppTokens.get(j)); 7687 } 7688 7689 i -= lastBelow; 7690 if (i != numRemoved) { 7691 Slog.w(TAG, "Rebuild removed " + numRemoved 7692 + " windows but added " + i); 7693 for (i=0; i<numRemoved; i++) { 7694 WindowState ws = mRebuildTmp[i]; 7695 if (ws.mRebuilding) { 7696 StringWriter sw = new StringWriter(); 7697 PrintWriter pw = new PrintWriter(sw); 7698 ws.dump(pw, "", true); 7699 pw.flush(); 7700 Slog.w(TAG, "This window was lost: " + ws); 7701 Slog.w(TAG, sw.toString()); 7702 ws.mWinAnimator.destroySurfaceLocked(); 7703 } 7704 } 7705 Slog.w(TAG, "Current app token list:"); 7706 dumpAnimatingAppTokensLocked(); 7707 Slog.w(TAG, "Final window list:"); 7708 dumpWindowsLocked(); 7709 } 7710 } 7711 7712 private final void assignLayersLocked(WindowList windows) { 7713 int N = windows.size(); 7714 int curBaseLayer = 0; 7715 int curLayer = 0; 7716 int i; 7717 7718 if (DEBUG_LAYERS) { 7719 RuntimeException here = new RuntimeException("here"); 7720 here.fillInStackTrace(); 7721 Slog.v(TAG, "Assigning layers", here); 7722 } 7723 7724 boolean anyLayerChanged = false; 7725 7726 for (i=0; i<N; i++) { 7727 final WindowState w = windows.get(i); 7728 final WindowStateAnimator winAnimator = w.mWinAnimator; 7729 boolean layerChanged = false; 7730 int oldLayer = w.mLayer; 7731 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 7732 || (i > 0 && w.mIsWallpaper)) { 7733 curLayer += WINDOW_LAYER_MULTIPLIER; 7734 w.mLayer = curLayer; 7735 } else { 7736 curBaseLayer = curLayer = w.mBaseLayer; 7737 w.mLayer = curLayer; 7738 } 7739 if (w.mLayer != oldLayer) { 7740 layerChanged = true; 7741 anyLayerChanged = true; 7742 } 7743 oldLayer = winAnimator.mAnimLayer; 7744 if (w.mTargetAppToken != null) { 7745 winAnimator.mAnimLayer = 7746 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 7747 } else if (w.mAppToken != null) { 7748 winAnimator.mAnimLayer = 7749 w.mLayer + w.mAppToken.mAppAnimator.animLayerAdjustment; 7750 } else { 7751 winAnimator.mAnimLayer = w.mLayer; 7752 } 7753 if (w.mIsImWindow) { 7754 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 7755 } else if (w.mIsWallpaper) { 7756 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 7757 } 7758 if (winAnimator.mAnimLayer != oldLayer) { 7759 layerChanged = true; 7760 anyLayerChanged = true; 7761 } 7762 if (layerChanged && mAnimator.isDimmingLocked(winAnimator)) { 7763 // Force an animation pass just to update the mDimAnimator layer. 7764 scheduleAnimationLocked(); 7765 } 7766 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 7767 + "mBase=" + w.mBaseLayer 7768 + " mLayer=" + w.mLayer 7769 + (w.mAppToken == null ? 7770 "" : " mAppLayer=" + w.mAppToken.mAppAnimator.animLayerAdjustment) 7771 + " =mAnimLayer=" + winAnimator.mAnimLayer); 7772 //System.out.println( 7773 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 7774 } 7775 7776 //TODO (multidisplay): Magnification is supported only for the default display. 7777 if (mDisplayMagnifier != null && anyLayerChanged 7778 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) { 7779 mDisplayMagnifier.onWindowLayersChangedLocked(); 7780 } 7781 } 7782 7783 private final void performLayoutAndPlaceSurfacesLocked() { 7784 int loopCount = 6; 7785 do { 7786 mTraversalScheduled = false; 7787 performLayoutAndPlaceSurfacesLockedLoop(); 7788 mH.removeMessages(H.DO_TRAVERSAL); 7789 loopCount--; 7790 } while (mTraversalScheduled && loopCount > 0); 7791 mInnerFields.mWallpaperActionPending = false; 7792 } 7793 7794 private boolean mInLayout = false; 7795 private final void performLayoutAndPlaceSurfacesLockedLoop() { 7796 if (mInLayout) { 7797 if (DEBUG) { 7798 throw new RuntimeException("Recursive call!"); 7799 } 7800 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 7801 + Debug.getCallers(3)); 7802 return; 7803 } 7804 7805 if (mWaitingForConfig) { 7806 // Our configuration has changed (most likely rotation), but we 7807 // don't yet have the complete configuration to report to 7808 // applications. Don't do any window layout until we have it. 7809 return; 7810 } 7811 7812 if (!mDisplayReady) { 7813 // Not yet initialized, nothing to do. 7814 return; 7815 } 7816 7817 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 7818 mInLayout = true; 7819 boolean recoveringMemory = false; 7820 7821 try { 7822 if (mForceRemoves != null) { 7823 recoveringMemory = true; 7824 // Wait a little bit for things to settle down, and off we go. 7825 for (int i=0; i<mForceRemoves.size(); i++) { 7826 WindowState ws = mForceRemoves.get(i); 7827 Slog.i(TAG, "Force removing: " + ws); 7828 removeWindowInnerLocked(ws.mSession, ws); 7829 } 7830 mForceRemoves = null; 7831 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 7832 Object tmp = new Object(); 7833 synchronized (tmp) { 7834 try { 7835 tmp.wait(250); 7836 } catch (InterruptedException e) { 7837 } 7838 } 7839 } 7840 } catch (RuntimeException e) { 7841 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 7842 } 7843 7844 try { 7845 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 7846 7847 mInLayout = false; 7848 7849 if (needsLayout()) { 7850 if (++mLayoutRepeatCount < 6) { 7851 requestTraversalLocked(); 7852 } else { 7853 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 7854 mLayoutRepeatCount = 0; 7855 } 7856 } else { 7857 mLayoutRepeatCount = 0; 7858 } 7859 7860 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 7861 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 7862 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE); 7863 } 7864 } catch (RuntimeException e) { 7865 mInLayout = false; 7866 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 7867 } 7868 7869 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 7870 } 7871 7872 private final void performLayoutLockedInner(final DisplayContent displayContent, 7873 boolean initial, boolean updateInputWindows) { 7874 if (!displayContent.layoutNeeded) { 7875 return; 7876 } 7877 displayContent.layoutNeeded = false; 7878 WindowList windows = displayContent.getWindowList(); 7879 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 7880 7881 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7882 final int dw = displayInfo.logicalWidth; 7883 final int dh = displayInfo.logicalHeight; 7884 7885 final int NFW = mFakeWindows.size(); 7886 for (int i=0; i<NFW; i++) { 7887 mFakeWindows.get(i).layout(dw, dh); 7888 } 7889 7890 final int N = windows.size(); 7891 int i; 7892 7893 if (DEBUG_LAYOUT) { 7894 Slog.v(TAG, "-------------------------------------"); 7895 Slog.v(TAG, "performLayout: needed=" 7896 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 7897 } 7898 7899 WindowStateAnimator universeBackground = null; 7900 7901 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); 7902 if (isDefaultDisplay) { 7903 // Not needed on non-default displays. 7904 mSystemDecorLayer = mPolicy.getSystemDecorRectLw(mSystemDecorRect); 7905 mScreenRect.set(0, 0, dw, dh); 7906 } 7907 7908 int seq = mLayoutSeq+1; 7909 if (seq < 0) seq = 0; 7910 mLayoutSeq = seq; 7911 7912 boolean behindDream = false; 7913 7914 // First perform layout of any root windows (not attached 7915 // to another window). 7916 int topAttached = -1; 7917 for (i = N-1; i >= 0; i--) { 7918 final WindowState win = windows.get(i); 7919 7920 // Don't do layout of a window if it is not visible, or 7921 // soon won't be visible, to avoid wasting time and funky 7922 // changes while a window is animating away. 7923 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) 7924 || win.isGoneForLayoutLw(); 7925 7926 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 7927 Slog.v(TAG, "1ST PASS " + win 7928 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 7929 + " mLayoutAttached=" + win.mLayoutAttached 7930 + " screen changed=" + win.isConfigChanged()); 7931 final AppWindowToken atoken = win.mAppToken; 7932 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 7933 + win.mViewVisibility + " mRelayoutCalled=" 7934 + win.mRelayoutCalled + " hidden=" 7935 + win.mRootToken.hidden + " hiddenRequested=" 7936 + (atoken != null && atoken.hiddenRequested) 7937 + " mAttachedHidden=" + win.mAttachedHidden); 7938 else Slog.v(TAG, " VIS: mViewVisibility=" 7939 + win.mViewVisibility + " mRelayoutCalled=" 7940 + win.mRelayoutCalled + " hidden=" 7941 + win.mRootToken.hidden + " hiddenRequested=" 7942 + (atoken != null && atoken.hiddenRequested) 7943 + " mAttachedHidden=" + win.mAttachedHidden); 7944 } 7945 7946 // If this view is GONE, then skip it -- keep the current 7947 // frame, and let the caller know so they can ignore it 7948 // if they want. (We do the normal layout for INVISIBLE 7949 // windows, since that means "perform layout as normal, 7950 // just don't display"). 7951 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 7952 || (win.mAttrs.type == TYPE_KEYGUARD && win.isConfigChanged()) 7953 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 7954 if (!win.mLayoutAttached) { 7955 if (initial) { 7956 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 7957 win.mContentChanged = false; 7958 } 7959 if (win.mAttrs.type == TYPE_DREAM) { 7960 // Don't layout windows behind a dream, so that if it 7961 // does stuff like hide the status bar we won't get a 7962 // bad transition when it goes away. 7963 behindDream = true; 7964 } 7965 win.mLayoutNeeded = false; 7966 win.prelayout(); 7967 mPolicy.layoutWindowLw(win, win.mAttrs, null); 7968 win.mLayoutSeq = seq; 7969 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 7970 + win.mFrame + " mContainingFrame=" 7971 + win.mContainingFrame + " mDisplayFrame=" 7972 + win.mDisplayFrame); 7973 } else { 7974 if (topAttached < 0) topAttached = i; 7975 } 7976 } 7977 if (win.mViewVisibility == View.VISIBLE 7978 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 7979 && universeBackground == null) { 7980 universeBackground = win.mWinAnimator; 7981 } 7982 } 7983 7984 if (mAnimator.mUniverseBackground != universeBackground) { 7985 mFocusMayChange = true; 7986 mAnimator.mUniverseBackground = universeBackground; 7987 } 7988 7989 boolean attachedBehindDream = false; 7990 7991 // Now perform layout of attached windows, which usually 7992 // depend on the position of the window they are attached to. 7993 // XXX does not deal with windows that are attached to windows 7994 // that are themselves attached. 7995 for (i = topAttached; i >= 0; i--) { 7996 final WindowState win = windows.get(i); 7997 7998 if (win.mLayoutAttached) { 7999 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 8000 + " mHaveFrame=" + win.mHaveFrame 8001 + " mViewVisibility=" + win.mViewVisibility 8002 + " mRelayoutCalled=" + win.mRelayoutCalled); 8003 // If this view is GONE, then skip it -- keep the current 8004 // frame, and let the caller know so they can ignore it 8005 // if they want. (We do the normal layout for INVISIBLE 8006 // windows, since that means "perform layout as normal, 8007 // just don't display"). 8008 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) { 8009 continue; 8010 } 8011 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8012 || !win.mHaveFrame || win.mLayoutNeeded) { 8013 if (initial) { 8014 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8015 win.mContentChanged = false; 8016 } 8017 win.mLayoutNeeded = false; 8018 win.prelayout(); 8019 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 8020 win.mLayoutSeq = seq; 8021 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8022 + win.mFrame + " mContainingFrame=" 8023 + win.mContainingFrame + " mDisplayFrame=" 8024 + win.mDisplayFrame); 8025 } 8026 } else if (win.mAttrs.type == TYPE_DREAM) { 8027 // Don't layout windows behind a dream, so that if it 8028 // does stuff like hide the status bar we won't get a 8029 // bad transition when it goes away. 8030 attachedBehindDream = behindDream; 8031 } 8032 } 8033 8034 // Window frames may have changed. Tell the input dispatcher about it. 8035 mInputMonitor.setUpdateInputWindowsNeededLw(); 8036 if (updateInputWindows) { 8037 mInputMonitor.updateInputWindowsLw(false /*force*/); 8038 } 8039 8040 mPolicy.finishLayoutLw(); 8041 } 8042 8043 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8044 // If the screen is currently frozen or off, then keep 8045 // it frozen/off until this window draws at its new 8046 // orientation. 8047 if (!okToDisplay()) { 8048 if (DEBUG_ORIENTATION) Slog.v(TAG, 8049 "Changing surface while display frozen: " + w); 8050 w.mOrientationChanging = true; 8051 w.mLastFreezeDuration = 0; 8052 mInnerFields.mOrientationChangeComplete = false; 8053 if (!mWindowsFreezingScreen) { 8054 mWindowsFreezingScreen = true; 8055 // XXX should probably keep timeout from 8056 // when we first froze the display. 8057 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8058 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 8059 WINDOW_FREEZE_TIMEOUT_DURATION); 8060 } 8061 } 8062 } 8063 8064 /** 8065 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8066 * @param windows List of windows on default display. 8067 * @return bitmap indicating if another pass through layout must be made. 8068 */ 8069 public int handleAppTransitionReadyLocked(WindowList windows) { 8070 int changes = 0; 8071 int i; 8072 int NN = mOpeningApps.size(); 8073 boolean goodToGo = true; 8074 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8075 "Checking " + NN + " opening apps (frozen=" 8076 + mDisplayFrozen + " timeout=" 8077 + mAppTransition.isTimeout() + ")..."); 8078 if (!mDisplayFrozen && !mAppTransition.isTimeout()) { 8079 // If the display isn't frozen, wait to do anything until 8080 // all of the apps are ready. Otherwise just go because 8081 // we'll unfreeze the display when everyone is ready. 8082 for (i=0; i<NN && goodToGo; i++) { 8083 AppWindowToken wtoken = mOpeningApps.get(i); 8084 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8085 "Check opening app=" + wtoken + ": allDrawn=" 8086 + wtoken.allDrawn + " startingDisplayed=" 8087 + wtoken.startingDisplayed + " startingMoved=" 8088 + wtoken.startingMoved); 8089 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8090 && !wtoken.startingMoved) { 8091 goodToGo = false; 8092 } 8093 } 8094 } 8095 if (goodToGo) { 8096 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8097 int transit = mAppTransition.getAppTransition(); 8098 if (mSkipAppTransitionAnimation) { 8099 transit = AppTransition.TRANSIT_UNSET; 8100 } 8101 mAppTransition.goodToGo(); 8102 mStartingIconInTransition = false; 8103 mSkipAppTransitionAnimation = false; 8104 8105 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8106 8107 rebuildAppWindowListLocked(); 8108 8109 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8110 WindowState oldWallpaper = 8111 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8112 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8113 ? null : mWallpaperTarget; 8114 8115 mInnerFields.mWallpaperMayChange = false; 8116 8117 // The top-most window will supply the layout params, 8118 // and we will determine it below. 8119 LayoutParams animLp = null; 8120 int bestAnimLayer = -1; 8121 boolean fullscreenAnim = false; 8122 8123 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8124 "New wallpaper target=" + mWallpaperTarget 8125 + ", oldWallpaper=" + oldWallpaper 8126 + ", lower target=" + mLowerWallpaperTarget 8127 + ", upper target=" + mUpperWallpaperTarget); 8128 8129 boolean openingAppHasWallpaper = false; 8130 boolean closingAppHasWallpaper = false; 8131 final AppWindowToken lowerWallpaperAppToken; 8132 final AppWindowToken upperWallpaperAppToken; 8133 if (mLowerWallpaperTarget == null) { 8134 lowerWallpaperAppToken = upperWallpaperAppToken = null; 8135 } else { 8136 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken; 8137 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken; 8138 } 8139 8140 // Do a first pass through the tokens for two 8141 // things: 8142 // (1) Determine if both the closing and opening 8143 // app token sets are wallpaper targets, in which 8144 // case special animations are needed 8145 // (since the wallpaper needs to stay static 8146 // behind them). 8147 // (2) Find the layout params of the top-most 8148 // application window in the tokens, which is 8149 // what will control the animation theme. 8150 final int NC = mClosingApps.size(); 8151 NN = NC + mOpeningApps.size(); 8152 for (i=0; i<NN; i++) { 8153 final AppWindowToken wtoken; 8154 if (i < NC) { 8155 wtoken = mClosingApps.get(i); 8156 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8157 closingAppHasWallpaper = true; 8158 } 8159 } else { 8160 wtoken = mOpeningApps.get(i - NC); 8161 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8162 openingAppHasWallpaper = true; 8163 } 8164 } 8165 8166 if (wtoken.appFullscreen) { 8167 WindowState ws = wtoken.findMainWindow(); 8168 if (ws != null) { 8169 animLp = ws.mAttrs; 8170 bestAnimLayer = ws.mLayer; 8171 fullscreenAnim = true; 8172 } 8173 } else if (!fullscreenAnim) { 8174 WindowState ws = wtoken.findMainWindow(); 8175 if (ws != null) { 8176 if (ws.mLayer > bestAnimLayer) { 8177 animLp = ws.mAttrs; 8178 bestAnimLayer = ws.mLayer; 8179 } 8180 } 8181 } 8182 } 8183 8184 if (closingAppHasWallpaper && openingAppHasWallpaper) { 8185 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!"); 8186 switch (transit) { 8187 case AppTransition.TRANSIT_ACTIVITY_OPEN: 8188 case AppTransition.TRANSIT_TASK_OPEN: 8189 case AppTransition.TRANSIT_TASK_TO_FRONT: 8190 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN; 8191 break; 8192 case AppTransition.TRANSIT_ACTIVITY_CLOSE: 8193 case AppTransition.TRANSIT_TASK_CLOSE: 8194 case AppTransition.TRANSIT_TASK_TO_BACK: 8195 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; 8196 break; 8197 } 8198 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); 8199 } else if ((oldWallpaper != null) && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 8200 // We are transitioning from an activity with 8201 // a wallpaper to one without. 8202 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; 8203 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8204 "New transit away from wallpaper: " + transit); 8205 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) { 8206 // We are transitioning from an activity without 8207 // a wallpaper to now showing the wallpaper 8208 transit = AppTransition.TRANSIT_WALLPAPER_OPEN; 8209 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8210 "New transit into wallpaper: " + transit); 8211 } 8212 8213 // If all closing windows are obscured, then there is 8214 // no need to do an animation. This is the case, for 8215 // example, when this transition is being done behind 8216 // the lock screen. 8217 if (!mPolicy.allowAppAnimationsLw()) { 8218 animLp = null; 8219 } 8220 8221 AppWindowToken topOpeningApp = null; 8222 int topOpeningLayer = 0; 8223 8224 NN = mOpeningApps.size(); 8225 for (i=0; i<NN; i++) { 8226 AppWindowToken wtoken = mOpeningApps.get(i); 8227 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 8228 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 8229 appAnimator.clearThumbnail(); 8230 wtoken.inPendingTransaction = false; 8231 appAnimator.animation = null; 8232 setTokenVisibilityLocked(wtoken, animLp, true, transit, false); 8233 wtoken.updateReportedVisibilityLocked(); 8234 wtoken.waitingToShow = false; 8235 8236 appAnimator.mAllAppWinAnimators.clear(); 8237 final int N = wtoken.allAppWindows.size(); 8238 for (int j = 0; j < N; j++) { 8239 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 8240 } 8241 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 8242 8243 if (animLp != null) { 8244 int layer = -1; 8245 for (int j=0; j<wtoken.windows.size(); j++) { 8246 WindowState win = wtoken.windows.get(j); 8247 if (win.mWinAnimator.mAnimLayer > layer) { 8248 layer = win.mWinAnimator.mAnimLayer; 8249 } 8250 } 8251 if (topOpeningApp == null || layer > topOpeningLayer) { 8252 topOpeningApp = wtoken; 8253 topOpeningLayer = layer; 8254 } 8255 } 8256 } 8257 NN = mClosingApps.size(); 8258 for (i=0; i<NN; i++) { 8259 AppWindowToken wtoken = mClosingApps.get(i); 8260 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8261 "Now closing app " + wtoken); 8262 wtoken.mAppAnimator.clearThumbnail(); 8263 wtoken.inPendingTransaction = false; 8264 wtoken.mAppAnimator.animation = null; 8265 setTokenVisibilityLocked(wtoken, animLp, false, 8266 transit, false); 8267 wtoken.updateReportedVisibilityLocked(); 8268 wtoken.waitingToHide = false; 8269 // Force the allDrawn flag, because we want to start 8270 // this guy's animations regardless of whether it's 8271 // gotten drawn. 8272 wtoken.allDrawn = true; 8273 wtoken.deferClearAllDrawn = false; 8274 } 8275 8276 AppWindowAnimator appAnimator = 8277 topOpeningApp == null ? null : topOpeningApp.mAppAnimator; 8278 Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail(); 8279 if (nextAppTransitionThumbnail != null && appAnimator != null 8280 && appAnimator.animation != null) { 8281 // This thumbnail animation is very special, we need to have 8282 // an extra surface with the thumbnail included with the animation. 8283 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(), 8284 nextAppTransitionThumbnail.getHeight()); 8285 try { 8286 // TODO(multi-display): support other displays 8287 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8288 final Display display = displayContent.getDisplay(); 8289 SurfaceControl surfaceControl = new SurfaceControl(mFxSession, 8290 "thumbnail anim", 8291 dirty.width(), dirty.height(), 8292 PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 8293 surfaceControl.setLayerStack(display.getLayerStack()); 8294 appAnimator.thumbnail = surfaceControl; 8295 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE"); 8296 Surface drawSurface = new Surface(); 8297 drawSurface.copyFrom(surfaceControl); 8298 Canvas c = drawSurface.lockCanvas(dirty); 8299 c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null); 8300 drawSurface.unlockCanvasAndPost(c); 8301 drawSurface.release(); 8302 appAnimator.thumbnailLayer = topOpeningLayer; 8303 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 8304 Animation anim = mAppTransition.createThumbnailAnimationLocked( 8305 transit, true, true, displayInfo.appWidth, displayInfo.appHeight); 8306 appAnimator.thumbnailAnimation = anim; 8307 anim.restrictDuration(MAX_ANIMATION_DURATION); 8308 anim.scaleCurrentDuration(mTransitionAnimationScale); 8309 Point p = new Point(); 8310 mAppTransition.getStartingPoint(p); 8311 appAnimator.thumbnailX = p.x; 8312 appAnimator.thumbnailY = p.y; 8313 } catch (SurfaceControl.OutOfResourcesException e) { 8314 Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width() 8315 + " h=" + dirty.height(), e); 8316 appAnimator.clearThumbnail(); 8317 } catch (Surface.OutOfResourcesException e) { 8318 Slog.e(TAG, "Can't allocate Canvas surface w=" + dirty.width() 8319 + " h=" + dirty.height(), e); 8320 appAnimator.clearThumbnail(); 8321 } 8322 } 8323 8324 mAppTransition.postAnimationCallback(); 8325 mAppTransition.clear(); 8326 8327 mOpeningApps.clear(); 8328 mClosingApps.clear(); 8329 8330 // This has changed the visibility of windows, so perform 8331 // a new layout to get them all up-to-date. 8332 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT 8333 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 8334 getDefaultDisplayContentLocked().layoutNeeded = true; 8335 8336 // TODO(multidisplay): IMEs are only supported on the default display. 8337 if (windows == getDefaultWindowListLocked() 8338 && !moveInputMethodWindowsIfNeededLocked(true)) { 8339 assignLayersLocked(windows); 8340 } 8341 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/); 8342 mFocusMayChange = false; 8343 } 8344 8345 return changes; 8346 } 8347 8348 /** 8349 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8350 * @return bitmap indicating if another pass through layout must be made. 8351 */ 8352 private int handleAnimatingStoppedAndTransitionLocked() { 8353 int changes = 0; 8354 8355 mAppTransition.setIdle(); 8356 // Restore window app tokens to the ActivityManager views 8357 for (int i = mAnimatingAppTokens.size() - 1; i >= 0; i--) { 8358 mAnimatingAppTokens.get(i).sendingToBottom = false; 8359 } 8360 mAnimatingAppTokens.clear(); 8361 mAnimatingAppTokens.addAll(mAppTokens); 8362 rebuildAppWindowListLocked(); 8363 8364 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8365 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 8366 "Wallpaper layer changed: assigning layers + relayout"); 8367 moveInputMethodWindowsIfNeededLocked(true); 8368 mInnerFields.mWallpaperMayChange = true; 8369 // Since the window list has been rebuilt, focus might 8370 // have to be recomputed since the actual order of windows 8371 // might have changed again. 8372 mFocusMayChange = true; 8373 8374 return changes; 8375 } 8376 8377 private void updateResizingWindows(final WindowState w) { 8378 final WindowStateAnimator winAnimator = w.mWinAnimator; 8379 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { 8380 w.mOverscanInsetsChanged |= 8381 !w.mLastOverscanInsets.equals(w.mOverscanInsets); 8382 w.mContentInsetsChanged |= 8383 !w.mLastContentInsets.equals(w.mContentInsets); 8384 w.mVisibleInsetsChanged |= 8385 !w.mLastVisibleInsets.equals(w.mVisibleInsets); 8386 boolean configChanged = w.isConfigChanged(); 8387 if (DEBUG_CONFIGURATION && configChanged) { 8388 Slog.v(TAG, "Win " + w + " config changed: " 8389 + mCurConfiguration); 8390 } 8391 if (localLOGV) Slog.v(TAG, "Resizing " + w 8392 + ": configChanged=" + configChanged 8393 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8394 w.mLastFrame.set(w.mFrame); 8395 if (w.mContentInsetsChanged 8396 || w.mVisibleInsetsChanged 8397 || winAnimator.mSurfaceResized 8398 || configChanged) { 8399 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8400 Slog.v(TAG, "Resize reasons: " 8401 + " contentInsetsChanged=" + w.mContentInsetsChanged 8402 + " " + w.mContentInsets.toShortString() 8403 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8404 + " " + w.mVisibleInsets.toShortString() 8405 + " surfaceResized=" + winAnimator.mSurfaceResized 8406 + " configChanged=" + configChanged); 8407 } 8408 8409 w.mLastOverscanInsets.set(w.mOverscanInsets); 8410 w.mLastContentInsets.set(w.mContentInsets); 8411 w.mLastVisibleInsets.set(w.mVisibleInsets); 8412 makeWindowFreezingScreenIfNeededLocked(w); 8413 // If the orientation is changing, then we need to 8414 // hold off on unfreezing the display until this 8415 // window has been redrawn; to do that, we need 8416 // to go through the process of getting informed 8417 // by the application when it has finished drawing. 8418 if (w.mOrientationChanging) { 8419 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 8420 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 8421 + w + ", surface " + winAnimator.mSurfaceControl); 8422 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 8423 if (w.mAppToken != null) { 8424 w.mAppToken.allDrawn = false; 8425 w.mAppToken.deferClearAllDrawn = false; 8426 } 8427 } 8428 if (!mResizingWindows.contains(w)) { 8429 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8430 "Resizing window " + w + " to " + winAnimator.mSurfaceW 8431 + "x" + winAnimator.mSurfaceH); 8432 mResizingWindows.add(w); 8433 } 8434 } else if (w.mOrientationChanging) { 8435 if (w.isDrawnLw()) { 8436 if (DEBUG_ORIENTATION) Slog.v(TAG, 8437 "Orientation not waiting for draw in " 8438 + w + ", surface " + winAnimator.mSurfaceControl); 8439 w.mOrientationChanging = false; 8440 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 8441 - mDisplayFreezeTime); 8442 } 8443 } 8444 } 8445 } 8446 8447 /** 8448 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8449 * 8450 * @param w WindowState this method is applied to. 8451 * @param currentTime The time which animations use for calculating transitions. 8452 * @param innerDw Width of app window. 8453 * @param innerDh Height of app window. 8454 */ 8455 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 8456 final int innerDw, final int innerDh) { 8457 final WindowManager.LayoutParams attrs = w.mAttrs; 8458 final int attrFlags = attrs.flags; 8459 final boolean canBeSeen = w.isDisplayedLw(); 8460 8461 if (w.mHasSurface) { 8462 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8463 mInnerFields.mHoldScreen = w.mSession; 8464 } 8465 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 8466 && mInnerFields.mScreenBrightness < 0) { 8467 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 8468 } 8469 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 8470 && mInnerFields.mButtonBrightness < 0) { 8471 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 8472 } 8473 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0 8474 && mInnerFields.mUserActivityTimeout < 0) { 8475 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout; 8476 } 8477 8478 final int type = attrs.type; 8479 if (canBeSeen 8480 && (type == TYPE_SYSTEM_DIALOG 8481 || type == TYPE_RECENTS_OVERLAY 8482 || type == TYPE_KEYGUARD 8483 || type == TYPE_SYSTEM_ERROR)) { 8484 mInnerFields.mSyswin = true; 8485 } 8486 8487 if (canBeSeen) { 8488 if (type == TYPE_DREAM || type == TYPE_KEYGUARD) { 8489 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_MIRROR; 8490 } else if (mInnerFields.mDisplayHasContent 8491 == LayoutFields.DISPLAY_CONTENT_UNKNOWN) { 8492 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNIQUE; 8493 } 8494 } 8495 } 8496 8497 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8498 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8499 // This window completely covers everything behind it, 8500 // so we want to leave all of them as undimmed (for 8501 // performance reasons). 8502 mInnerFields.mObscured = true; 8503 } 8504 } 8505 8506 private void handleFlagDimBehind(WindowState w, int innerDw, int innerDh) { 8507 final WindowManager.LayoutParams attrs = w.mAttrs; 8508 if ((attrs.flags & FLAG_DIM_BEHIND) != 0 8509 && w.isDisplayedLw() 8510 && !w.mExiting) { 8511 mInnerFields.mDimming = true; 8512 final WindowStateAnimator winAnimator = w.mWinAnimator; 8513 if (!mAnimator.isDimmingLocked(winAnimator)) { 8514 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming."); 8515 startDimmingLocked(winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount); 8516 } 8517 } 8518 } 8519 8520 private void updateAllDrawnLocked() { 8521 // See if any windows have been drawn, so they (and others 8522 // associated with them) can now be shown. 8523 final ArrayList<AppWindowToken> appTokens = mAnimatingAppTokens; 8524 final int NT = appTokens.size(); 8525 for (int i=0; i<NT; i++) { 8526 AppWindowToken wtoken = appTokens.get(i); 8527 if (!wtoken.allDrawn) { 8528 int numInteresting = wtoken.numInterestingWindows; 8529 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 8530 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, 8531 "allDrawn: " + wtoken 8532 + " interesting=" + numInteresting 8533 + " drawn=" + wtoken.numDrawnWindows); 8534 wtoken.allDrawn = true; 8535 } 8536 } 8537 } 8538 } 8539 8540 // "Something has changed! Let's make it correct now." 8541 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 8542 if (DEBUG_WINDOW_TRACE) { 8543 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 8544 + Debug.getCallers(3)); 8545 } 8546 8547 final long currentTime = SystemClock.uptimeMillis(); 8548 8549 int i; 8550 8551 if (mFocusMayChange) { 8552 mFocusMayChange = false; 8553 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 8554 false /*updateInputWindows*/); 8555 } 8556 8557 // Initialize state of exiting tokens. 8558 for (i=mExitingTokens.size()-1; i>=0; i--) { 8559 mExitingTokens.get(i).hasVisible = false; 8560 } 8561 8562 // Initialize state of exiting applications. 8563 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 8564 mExitingAppTokens.get(i).hasVisible = false; 8565 } 8566 8567 mInnerFields.mHoldScreen = null; 8568 mInnerFields.mScreenBrightness = -1; 8569 mInnerFields.mButtonBrightness = -1; 8570 mInnerFields.mUserActivityTimeout = -1; 8571 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN; 8572 8573 mTransactionSequence++; 8574 8575 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked(); 8576 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 8577 final int defaultDw = defaultInfo.logicalWidth; 8578 final int defaultDh = defaultInfo.logicalHeight; 8579 8580 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 8581 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 8582 SurfaceControl.openTransaction(); 8583 try { 8584 8585 if (mWatermark != null) { 8586 mWatermark.positionSurface(defaultDw, defaultDh); 8587 } 8588 if (mStrictModeFlash != null) { 8589 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 8590 } 8591 8592 boolean focusDisplayed = false; 8593 boolean updateAllDrawn = false; 8594 8595 DisplayContentsIterator iterator = new DisplayContentsIterator(); 8596 while (iterator.hasNext()) { 8597 final DisplayContent displayContent = iterator.next(); 8598 WindowList windows = displayContent.getWindowList(); 8599 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8600 final int displayId = displayContent.getDisplayId(); 8601 final int dw = displayInfo.logicalWidth; 8602 final int dh = displayInfo.logicalHeight; 8603 final int innerDw = displayInfo.appWidth; 8604 final int innerDh = displayInfo.appHeight; 8605 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 8606 8607 // Reset for each display unless we are forcing mirroring. 8608 if (mInnerFields.mDisplayHasContent != LayoutFields.DISPLAY_CONTENT_MIRROR) { 8609 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN; 8610 } 8611 8612 int repeats = 0; 8613 do { 8614 repeats++; 8615 if (repeats > 6) { 8616 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 8617 displayContent.layoutNeeded = false; 8618 break; 8619 } 8620 8621 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 8622 displayContent.pendingLayoutChanges); 8623 8624 if ((displayContent.pendingLayoutChanges & 8625 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 && 8626 (adjustWallpaperWindowsLocked() & 8627 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 8628 assignLayersLocked(windows); 8629 displayContent.layoutNeeded = true; 8630 } 8631 8632 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 8633 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 8634 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 8635 if (updateOrientationFromAppTokensLocked(true)) { 8636 displayContent.layoutNeeded = true; 8637 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8638 } 8639 } 8640 8641 if ((displayContent.pendingLayoutChanges 8642 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 8643 displayContent.layoutNeeded = true; 8644 } 8645 8646 // FIRST LOOP: Perform a layout, if needed. 8647 if (repeats < 4) { 8648 performLayoutLockedInner(displayContent, repeats == 1, 8649 false /*updateInputWindows*/); 8650 } else { 8651 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 8652 } 8653 8654 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 8655 // it is animating. 8656 displayContent.pendingLayoutChanges = 0; 8657 8658 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 8659 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 8660 8661 if (isDefaultDisplay) { 8662 mPolicy.beginPostLayoutPolicyLw(dw, dh); 8663 for (i = windows.size() - 1; i >= 0; i--) { 8664 WindowState w = windows.get(i); 8665 if (w.mHasSurface) { 8666 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); 8667 } 8668 } 8669 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 8670 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 8671 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges); 8672 } 8673 } while (displayContent.pendingLayoutChanges != 0); 8674 8675 mInnerFields.mObscured = false; 8676 mInnerFields.mDimming = false; 8677 mInnerFields.mSyswin = false; 8678 8679 // Only used if default window 8680 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 8681 8682 final int N = windows.size(); 8683 for (i=N-1; i>=0; i--) { 8684 WindowState w = windows.get(i); 8685 8686 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 8687 8688 // Update effect. 8689 w.mObscured = mInnerFields.mObscured; 8690 if (!mInnerFields.mObscured) { 8691 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 8692 } 8693 8694 if (!mInnerFields.mDimming) { 8695 handleFlagDimBehind(w, innerDw, innerDh); 8696 } 8697 8698 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 8699 && w.isVisibleLw()) { 8700 // This is the wallpaper target and its obscured state 8701 // changed... make sure the current wallaper's visibility 8702 // has been updated accordingly. 8703 updateWallpaperVisibilityLocked(); 8704 } 8705 8706 final WindowStateAnimator winAnimator = w.mWinAnimator; 8707 8708 // If the window has moved due to its containing 8709 // content frame changing, then we'd like to animate 8710 // it. 8711 if (w.mHasSurface && w.shouldAnimateMove()) { 8712 // Frame has moved, containing content frame 8713 // has also moved, and we're not currently animating... 8714 // let's do something. 8715 Animation a = AnimationUtils.loadAnimation(mContext, 8716 com.android.internal.R.anim.window_move_from_decor); 8717 winAnimator.setAnimation(a); 8718 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 8719 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 8720 try { 8721 w.mClient.moved(w.mFrame.left, w.mFrame.top); 8722 } catch (RemoteException e) { 8723 } 8724 } 8725 8726 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 8727 w.mContentChanged = false; 8728 8729 // Moved from updateWindowsAndWallpaperLocked(). 8730 if (w.mHasSurface) { 8731 // Take care of the window being ready to display. 8732 final boolean committed = 8733 winAnimator.commitFinishDrawingLocked(currentTime); 8734 if (isDefaultDisplay && committed) { 8735 if (w.mAttrs.type == TYPE_DREAM) { 8736 // HACK: When a dream is shown, it may at that 8737 // point hide the lock screen. So we need to 8738 // redo the layout to let the phone window manager 8739 // make this happen. 8740 displayContent.pendingLayoutChanges |= 8741 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 8742 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 8743 debugLayoutRepeats( 8744 "dream and commitFinishDrawingLocked true", 8745 displayContent.pendingLayoutChanges); 8746 } 8747 } 8748 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 8749 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 8750 "First draw done in potential wallpaper target " + w); 8751 mInnerFields.mWallpaperMayChange = true; 8752 displayContent.pendingLayoutChanges |= 8753 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 8754 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 8755 debugLayoutRepeats( 8756 "wallpaper and commitFinishDrawingLocked true", 8757 displayContent.pendingLayoutChanges); 8758 } 8759 } 8760 } 8761 8762 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 8763 8764 final AppWindowToken atoken = w.mAppToken; 8765 if (DEBUG_STARTING_WINDOW && atoken != null 8766 && w == atoken.startingWindow) { 8767 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 8768 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 8769 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 8770 } 8771 if (atoken != null 8772 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 8773 if (atoken.lastTransactionSequence != mTransactionSequence) { 8774 atoken.lastTransactionSequence = mTransactionSequence; 8775 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 8776 atoken.startingDisplayed = false; 8777 } 8778 if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 8779 && !w.mExiting && !w.mDestroying) { 8780 if (WindowManagerService.DEBUG_VISIBILITY || 8781 WindowManagerService.DEBUG_ORIENTATION) { 8782 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 8783 + ", isAnimating=" + winAnimator.isAnimating()); 8784 if (!w.isDrawnLw()) { 8785 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl 8786 + " pv=" + w.mPolicyVisibility 8787 + " mDrawState=" + winAnimator.mDrawState 8788 + " ah=" + w.mAttachedHidden 8789 + " th=" + atoken.hiddenRequested 8790 + " a=" + winAnimator.mAnimating); 8791 } 8792 } 8793 if (w != atoken.startingWindow) { 8794 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 8795 atoken.numInterestingWindows++; 8796 if (w.isDrawnLw()) { 8797 atoken.numDrawnWindows++; 8798 if (WindowManagerService.DEBUG_VISIBILITY || 8799 WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG, 8800 "tokenMayBeDrawn: " + atoken 8801 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 8802 + " mAppFreezing=" + w.mAppFreezing); 8803 updateAllDrawn = true; 8804 } 8805 } 8806 } else if (w.isDrawnLw()) { 8807 atoken.startingDisplayed = true; 8808 } 8809 } 8810 } 8811 } 8812 8813 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 8814 && w.isDisplayedLw()) { 8815 focusDisplayed = true; 8816 } 8817 8818 updateResizingWindows(w); 8819 } 8820 8821 final boolean hasUniqueContent; 8822 switch (mInnerFields.mDisplayHasContent) { 8823 case LayoutFields.DISPLAY_CONTENT_MIRROR: 8824 hasUniqueContent = isDefaultDisplay; 8825 break; 8826 case LayoutFields.DISPLAY_CONTENT_UNIQUE: 8827 hasUniqueContent = true; 8828 break; 8829 case LayoutFields.DISPLAY_CONTENT_UNKNOWN: 8830 default: 8831 hasUniqueContent = false; 8832 break; 8833 } 8834 mDisplayManagerService.setDisplayHasContent(displayId, hasUniqueContent, 8835 true /* inTraversal, must call performTraversalInTrans... below */); 8836 8837 if (!mInnerFields.mDimming && mAnimator.isDimmingLocked(displayId)) { 8838 stopDimmingLocked(displayId); 8839 } 8840 } 8841 8842 if (updateAllDrawn) { 8843 updateAllDrawnLocked(); 8844 } 8845 8846 if (focusDisplayed) { 8847 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 8848 } 8849 8850 // Give the display manager a chance to adjust properties 8851 // like display rotation if it needs to. 8852 mDisplayManagerService.performTraversalInTransactionFromWindowManager(); 8853 8854 } catch (RuntimeException e) { 8855 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 8856 } finally { 8857 SurfaceControl.closeTransaction(); 8858 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 8859 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 8860 } 8861 8862 final WindowList defaultWindows = defaultDisplay.getWindowList(); 8863 8864 // If we are ready to perform an app transition, check through 8865 // all of the app tokens to be shown and see if they are ready 8866 // to go. 8867 if (mAppTransition.isReady()) { 8868 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 8869 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 8870 defaultDisplay.pendingLayoutChanges); 8871 } 8872 8873 if (!mAnimator.mAnimating && mAppTransition.isRunning()) { 8874 // We have finished the animation of an app transition. To do 8875 // this, we have delayed a lot of operations like showing and 8876 // hiding apps, moving apps in Z-order, etc. The app token list 8877 // reflects the correct Z-order, but the window list may now 8878 // be out of sync with it. So here we will just rebuild the 8879 // entire app window list. Fun! 8880 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 8881 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 8882 defaultDisplay.pendingLayoutChanges); 8883 } 8884 8885 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 8886 && !mAppTransition.isReady()) { 8887 // At this point, there was a window with a wallpaper that 8888 // was force hiding other windows behind it, but now it 8889 // is going away. This may be simple -- just animate 8890 // away the wallpaper and its window -- or it may be 8891 // hard -- the wallpaper now needs to be shown behind 8892 // something that was hidden. 8893 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 8894 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 8895 defaultDisplay.pendingLayoutChanges); 8896 } 8897 mInnerFields.mWallpaperForceHidingChanged = false; 8898 8899 if (mInnerFields.mWallpaperMayChange) { 8900 if (WindowManagerService.DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 8901 "Wallpaper may change! Adjusting"); 8902 defaultDisplay.pendingLayoutChanges |= 8903 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 8904 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange", 8905 defaultDisplay.pendingLayoutChanges); 8906 } 8907 8908 if (mFocusMayChange) { 8909 mFocusMayChange = false; 8910 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 8911 false /*updateInputWindows*/)) { 8912 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 8913 } 8914 } 8915 8916 if (needsLayout()) { 8917 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 8918 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 8919 defaultDisplay.pendingLayoutChanges); 8920 } 8921 8922 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 8923 WindowState win = mResizingWindows.get(i); 8924 if (win.mAppFreezing) { 8925 // Don't remove this window until rotation has completed. 8926 continue; 8927 } 8928 final WindowStateAnimator winAnimator = win.mWinAnimator; 8929 try { 8930 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8931 "Reporting new frame to " + win + ": " + win.mCompatFrame); 8932 int diff = 0; 8933 boolean configChanged = win.isConfigChanged(); 8934 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) 8935 && configChanged) { 8936 Slog.i(TAG, "Sending new config to window " + win + ": " 8937 + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH 8938 + " / " + mCurConfiguration + " / 0x" 8939 + Integer.toHexString(diff)); 8940 } 8941 win.setConfiguration(mCurConfiguration); 8942 if (DEBUG_ORIENTATION && 8943 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i( 8944 TAG, "Resizing " + win + " WITH DRAW PENDING"); 8945 final IWindow client = win.mClient; 8946 final Rect frame = win.mFrame; 8947 final Rect overscanInsets = win.mLastOverscanInsets; 8948 final Rect contentInsets = win.mLastContentInsets; 8949 final Rect visibleInsets = win.mLastVisibleInsets; 8950 final boolean reportDraw 8951 = winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING; 8952 final Configuration newConfig = configChanged ? win.mConfiguration : null; 8953 if (win.mClient instanceof IWindow.Stub) { 8954 // To prevent deadlock simulate one-way call if win.mClient is a local object. 8955 mH.post(new Runnable() { 8956 @Override 8957 public void run() { 8958 try { 8959 client.resized(frame, overscanInsets, contentInsets, 8960 visibleInsets, reportDraw, newConfig); 8961 } catch (RemoteException e) { 8962 // Not a remote call, RemoteException won't be raised. 8963 } 8964 } 8965 }); 8966 } else { 8967 client.resized(frame, overscanInsets, contentInsets, visibleInsets, reportDraw, 8968 newConfig); 8969 } 8970 win.mOverscanInsetsChanged = false; 8971 win.mContentInsetsChanged = false; 8972 win.mVisibleInsetsChanged = false; 8973 winAnimator.mSurfaceResized = false; 8974 } catch (RemoteException e) { 8975 win.mOrientationChanging = false; 8976 win.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 8977 - mDisplayFreezeTime); 8978 } 8979 mResizingWindows.remove(i); 8980 } 8981 8982 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 8983 "With display frozen, orientationChangeComplete=" 8984 + mInnerFields.mOrientationChangeComplete); 8985 if (mInnerFields.mOrientationChangeComplete) { 8986 if (mWindowsFreezingScreen) { 8987 mWindowsFreezingScreen = false; 8988 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource; 8989 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8990 } 8991 stopFreezingDisplayLocked(); 8992 } 8993 8994 // Destroy the surface of any windows that are no longer visible. 8995 boolean wallpaperDestroyed = false; 8996 i = mDestroySurface.size(); 8997 if (i > 0) { 8998 do { 8999 i--; 9000 WindowState win = mDestroySurface.get(i); 9001 win.mDestroying = false; 9002 if (mInputMethodWindow == win) { 9003 mInputMethodWindow = null; 9004 } 9005 if (win == mWallpaperTarget) { 9006 wallpaperDestroyed = true; 9007 } 9008 win.mWinAnimator.destroySurfaceLocked(); 9009 } while (i > 0); 9010 mDestroySurface.clear(); 9011 } 9012 9013 // Time to remove any exiting tokens? 9014 for (i=mExitingTokens.size()-1; i>=0; i--) { 9015 WindowToken token = mExitingTokens.get(i); 9016 if (!token.hasVisible) { 9017 mExitingTokens.remove(i); 9018 if (token.windowType == TYPE_WALLPAPER) { 9019 mWallpaperTokens.remove(token); 9020 } 9021 } 9022 } 9023 9024 // Time to remove any exiting applications? 9025 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 9026 AppWindowToken token = mExitingAppTokens.get(i); 9027 if (!token.hasVisible && !mClosingApps.contains(token)) { 9028 // Make sure there is no animation running on this token, 9029 // so any windows associated with it will be removed as 9030 // soon as their animations are complete 9031 token.mAppAnimator.clearAnimation(); 9032 token.mAppAnimator.animating = false; 9033 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 9034 "performLayout: App token exiting now removed" + token); 9035 mAppTokens.remove(token); 9036 mAnimatingAppTokens.remove(token); 9037 mExitingAppTokens.remove(i); 9038 } 9039 } 9040 9041 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 9042 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 9043 try { 9044 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 9045 } catch (RemoteException e) { 9046 } 9047 } 9048 mRelayoutWhileAnimating.clear(); 9049 } 9050 9051 if (wallpaperDestroyed) { 9052 defaultDisplay.pendingLayoutChanges |= 9053 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9054 defaultDisplay.layoutNeeded = true; 9055 } 9056 9057 DisplayContentsIterator iterator = new DisplayContentsIterator(); 9058 while (iterator.hasNext()) { 9059 DisplayContent displayContent = iterator.next(); 9060 if (displayContent.pendingLayoutChanges != 0) { 9061 displayContent.layoutNeeded = true; 9062 } 9063 } 9064 9065 // Finally update all input windows now that the window changes have stabilized. 9066 mInputMonitor.updateInputWindowsLw(true /*force*/); 9067 9068 setHoldScreenLocked(mInnerFields.mHoldScreen); 9069 if (!mDisplayFrozen) { 9070 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 9071 mPowerManager.setScreenBrightnessOverrideFromWindowManager(-1); 9072 } else { 9073 mPowerManager.setScreenBrightnessOverrideFromWindowManager( 9074 toBrightnessOverride(mInnerFields.mScreenBrightness)); 9075 } 9076 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 9077 mPowerManager.setButtonBrightnessOverrideFromWindowManager(-1); 9078 } else { 9079 mPowerManager.setButtonBrightnessOverrideFromWindowManager( 9080 toBrightnessOverride(mInnerFields.mButtonBrightness)); 9081 } 9082 mPowerManager.setUserActivityTimeoutOverrideFromWindowManager( 9083 mInnerFields.mUserActivityTimeout); 9084 } 9085 9086 if (mTurnOnScreen) { 9087 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 9088 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 9089 mTurnOnScreen = false; 9090 } 9091 9092 if (mInnerFields.mUpdateRotation) { 9093 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9094 if (updateRotationUncheckedLocked(false)) { 9095 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9096 } else { 9097 mInnerFields.mUpdateRotation = false; 9098 } 9099 } 9100 9101 if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded 9102 && !mInnerFields.mUpdateRotation) { 9103 checkDrawnWindowsLocked(); 9104 } 9105 9106 final int N = mPendingRemove.size(); 9107 if (N > 0) { 9108 if (mPendingRemoveTmp.length < N) { 9109 mPendingRemoveTmp = new WindowState[N+10]; 9110 } 9111 mPendingRemove.toArray(mPendingRemoveTmp); 9112 mPendingRemove.clear(); 9113 DisplayContentList displayList = new DisplayContentList(); 9114 for (i = 0; i < N; i++) { 9115 WindowState w = mPendingRemoveTmp[i]; 9116 removeWindowInnerLocked(w.mSession, w); 9117 if (!displayList.contains(w.mDisplayContent)) { 9118 displayList.add(w.mDisplayContent); 9119 } 9120 } 9121 9122 for (DisplayContent displayContent : displayList) { 9123 assignLayersLocked(displayContent.getWindowList()); 9124 displayContent.layoutNeeded = true; 9125 } 9126 } 9127 9128 // Check to see if we are now in a state where the screen should 9129 // be enabled, because the window obscured flags have changed. 9130 enableScreenIfNeededLocked(); 9131 9132 scheduleAnimationLocked(); 9133 9134 if (DEBUG_WINDOW_TRACE) { 9135 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" 9136 + mAnimator.mAnimating); 9137 } 9138 } 9139 9140 private int toBrightnessOverride(float value) { 9141 return (int)(value * PowerManager.BRIGHTNESS_ON); 9142 } 9143 9144 void checkDrawnWindowsLocked() { 9145 if (mWaitingForDrawn.size() > 0) { 9146 for (int j=mWaitingForDrawn.size()-1; j>=0; j--) { 9147 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j); 9148 WindowState win = pair.first; 9149 //Slog.i(TAG, "Waiting for drawn " + win + ": removed=" 9150 // + win.mRemoved + " visible=" + win.isVisibleLw() 9151 // + " shown=" + win.mSurfaceShown); 9152 if (win.mRemoved || !win.isVisibleLw()) { 9153 // Window has been removed or made invisible; no draw 9154 // will now happen, so stop waiting. 9155 Slog.w(TAG, "Aborted waiting for drawn: " + pair.first); 9156 try { 9157 pair.second.sendResult(null); 9158 } catch (RemoteException e) { 9159 } 9160 mWaitingForDrawn.remove(pair); 9161 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9162 } else if (win.mWinAnimator.mSurfaceShown) { 9163 // Window is now drawn (and shown). 9164 try { 9165 pair.second.sendResult(null); 9166 } catch (RemoteException e) { 9167 } 9168 mWaitingForDrawn.remove(pair); 9169 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9170 } 9171 } 9172 } 9173 } 9174 9175 @Override 9176 public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) { 9177 if (token != null && callback != null) { 9178 synchronized (mWindowMap) { 9179 WindowState win = windowForClientLocked(null, token, true); 9180 if (win != null) { 9181 Pair<WindowState, IRemoteCallback> pair = 9182 new Pair<WindowState, IRemoteCallback>(win, callback); 9183 Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9184 mH.sendMessageDelayed(m, 2000); 9185 mWaitingForDrawn.add(pair); 9186 checkDrawnWindowsLocked(); 9187 return true; 9188 } 9189 } 9190 } 9191 return false; 9192 } 9193 9194 void setHoldScreenLocked(final Session newHoldScreen) { 9195 final boolean hold = newHoldScreen != null; 9196 9197 if (hold && mHoldingScreenOn != newHoldScreen) { 9198 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 9199 } 9200 mHoldingScreenOn = newHoldScreen; 9201 9202 final boolean state = mHoldingScreenWakeLock.isHeld(); 9203 if (hold != state) { 9204 if (hold) { 9205 mHoldingScreenWakeLock.acquire(); 9206 mPolicy.keepScreenOnStartedLw(); 9207 } else { 9208 mPolicy.keepScreenOnStoppedLw(); 9209 mHoldingScreenWakeLock.release(); 9210 } 9211 } 9212 } 9213 9214 @Override 9215 public void requestTraversal() { 9216 synchronized (mWindowMap) { 9217 requestTraversalLocked(); 9218 } 9219 } 9220 9221 void requestTraversalLocked() { 9222 if (!mTraversalScheduled) { 9223 mTraversalScheduled = true; 9224 mH.sendEmptyMessage(H.DO_TRAVERSAL); 9225 } 9226 } 9227 9228 /** Note that Locked in this case is on mLayoutToAnim */ 9229 void scheduleAnimationLocked() { 9230 if (!mAnimationScheduled) { 9231 mAnimationScheduled = true; 9232 mChoreographer.postCallback( 9233 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 9234 } 9235 } 9236 9237 void startDimmingLocked(final WindowStateAnimator winAnimator, final float target) { 9238 mAnimator.setDimWinAnimatorLocked(winAnimator.mWin.getDisplayId(), winAnimator); 9239 } 9240 9241 void stopDimmingLocked(int displayId) { 9242 mAnimator.setDimWinAnimatorLocked(displayId, null); 9243 } 9244 9245 private boolean needsLayout() { 9246 DisplayContentsIterator iterator = new DisplayContentsIterator(); 9247 while (iterator.hasNext()) { 9248 if (iterator.next().layoutNeeded) { 9249 return true; 9250 } 9251 } 9252 return false; 9253 } 9254 9255 boolean copyAnimToLayoutParamsLocked() { 9256 boolean doRequest = false; 9257 9258 final int bulkUpdateParams = mAnimator.mBulkUpdateParams; 9259 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 9260 mInnerFields.mUpdateRotation = true; 9261 doRequest = true; 9262 } 9263 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 9264 mInnerFields.mWallpaperMayChange = true; 9265 doRequest = true; 9266 } 9267 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 9268 mInnerFields.mWallpaperForceHidingChanged = true; 9269 doRequest = true; 9270 } 9271 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 9272 mInnerFields.mOrientationChangeComplete = false; 9273 } else { 9274 mInnerFields.mOrientationChangeComplete = true; 9275 mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource; 9276 if (mWindowsFreezingScreen) { 9277 doRequest = true; 9278 } 9279 } 9280 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 9281 mTurnOnScreen = true; 9282 } 9283 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) { 9284 mInnerFields.mWallpaperActionPending = true; 9285 } 9286 9287 return doRequest; 9288 } 9289 9290 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9291 boolean secure) { 9292 final SurfaceControl surface = winAnimator.mSurfaceControl; 9293 boolean leakedSurface = false; 9294 boolean killedApps = false; 9295 9296 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9297 winAnimator.mSession.mPid, operation); 9298 9299 if (mForceRemoves == null) { 9300 mForceRemoves = new ArrayList<WindowState>(); 9301 } 9302 9303 long callingIdentity = Binder.clearCallingIdentity(); 9304 try { 9305 // There was some problem... first, do a sanity check of the 9306 // window list to make sure we haven't left any dangling surfaces 9307 // around. 9308 9309 AllWindowsIterator iterator = new AllWindowsIterator(); 9310 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 9311 while (iterator.hasNext()) { 9312 WindowState ws = iterator.next(); 9313 WindowStateAnimator wsa = ws.mWinAnimator; 9314 if (wsa.mSurfaceControl != null) { 9315 if (!mSessions.contains(wsa.mSession)) { 9316 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 9317 + ws + " surface=" + wsa.mSurfaceControl 9318 + " token=" + ws.mToken 9319 + " pid=" + ws.mSession.mPid 9320 + " uid=" + ws.mSession.mUid); 9321 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9322 wsa.mSurfaceControl.destroy(); 9323 wsa.mSurfaceShown = false; 9324 wsa.mSurfaceControl = null; 9325 ws.mHasSurface = false; 9326 mForceRemoves.add(ws); 9327 leakedSurface = true; 9328 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9329 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 9330 + ws + " surface=" + wsa.mSurfaceControl 9331 + " token=" + ws.mAppToken); 9332 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9333 wsa.mSurfaceControl.destroy(); 9334 wsa.mSurfaceShown = false; 9335 wsa.mSurfaceControl = null; 9336 ws.mHasSurface = false; 9337 leakedSurface = true; 9338 } 9339 } 9340 } 9341 9342 if (!leakedSurface) { 9343 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 9344 SparseIntArray pidCandidates = new SparseIntArray(); 9345 iterator = new AllWindowsIterator(); 9346 while (iterator.hasNext()) { 9347 WindowState ws = iterator.next(); 9348 if (mForceRemoves.contains(ws)) { 9349 continue; 9350 } 9351 WindowStateAnimator wsa = ws.mWinAnimator; 9352 if (wsa.mSurfaceControl != null) { 9353 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9354 } 9355 } 9356 if (pidCandidates.size() > 0) { 9357 int[] pids = new int[pidCandidates.size()]; 9358 for (int i=0; i<pids.length; i++) { 9359 pids[i] = pidCandidates.keyAt(i); 9360 } 9361 try { 9362 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9363 killedApps = true; 9364 } 9365 } catch (RemoteException e) { 9366 } 9367 } 9368 } 9369 9370 if (leakedSurface || killedApps) { 9371 // We managed to reclaim some memory, so get rid of the trouble 9372 // surface and ask the app to request another one. 9373 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 9374 if (surface != null) { 9375 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9376 "RECOVER DESTROY", null); 9377 surface.destroy(); 9378 winAnimator.mSurfaceShown = false; 9379 winAnimator.mSurfaceControl = null; 9380 winAnimator.mWin.mHasSurface = false; 9381 } 9382 9383 try { 9384 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9385 } catch (RemoteException e) { 9386 } 9387 } 9388 } finally { 9389 Binder.restoreCallingIdentity(callingIdentity); 9390 } 9391 9392 return leakedSurface || killedApps; 9393 } 9394 9395 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9396 WindowState newFocus = computeFocusedWindowLocked(); 9397 if (mCurrentFocus != newFocus) { 9398 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9399 // This check makes sure that we don't already have the focus 9400 // change message pending. 9401 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9402 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9403 if (localLOGV) Slog.v( 9404 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus); 9405 final WindowState oldFocus = mCurrentFocus; 9406 mCurrentFocus = newFocus; 9407 mAnimator.setCurrentFocus(newFocus); 9408 mLosingFocus.remove(newFocus); 9409 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9410 9411 // TODO(multidisplay): Focused windows on default display only. 9412 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9413 9414 final WindowState imWindow = mInputMethodWindow; 9415 if (newFocus != imWindow && oldFocus != imWindow) { 9416 if (moveInputMethodWindowsIfNeededLocked( 9417 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS && 9418 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) { 9419 displayContent.layoutNeeded = true; 9420 } 9421 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9422 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9423 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9424 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9425 // Client will do the layout, but we need to assign layers 9426 // for handleNewWindowLocked() below. 9427 assignLayersLocked(displayContent.getWindowList()); 9428 } 9429 } 9430 9431 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9432 // The change in focus caused us to need to do a layout. Okay. 9433 displayContent.layoutNeeded = true; 9434 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9435 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9436 } 9437 } 9438 9439 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9440 // If we defer assigning layers, then the caller is responsible for 9441 // doing this part. 9442 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 9443 } 9444 9445 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9446 return true; 9447 } 9448 return false; 9449 } 9450 9451 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 9452 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9453 } 9454 9455 private WindowState computeFocusedWindowLocked() { 9456 if (mAnimator.mUniverseBackground != null 9457 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 9458 return mAnimator.mUniverseBackground.mWin; 9459 } 9460 9461 final int displayCount = mDisplayContents.size(); 9462 for (int i = 0; i < displayCount; i++) { 9463 final DisplayContent displayContent = mDisplayContents.valueAt(i); 9464 WindowState win = findFocusedWindowLocked(displayContent); 9465 if (win != null) { 9466 return win; 9467 } 9468 } 9469 return null; 9470 } 9471 9472 private WindowState findFocusedWindowLocked(DisplayContent displayContent) { 9473 int nextAppIndex = mAppTokens.size()-1; 9474 WindowToken nextApp = nextAppIndex >= 0 ? mAppTokens.get(nextAppIndex) : null; 9475 9476 final WindowList windows = displayContent.getWindowList(); 9477 for (int i = windows.size() - 1; i >= 0; i--) { 9478 final WindowState win = windows.get(i); 9479 9480 if (localLOGV || DEBUG_FOCUS) Slog.v( 9481 TAG, "Looking for focus: " + i 9482 + " = " + win 9483 + ", flags=" + win.mAttrs.flags 9484 + ", canReceive=" + win.canReceiveKeys()); 9485 9486 AppWindowToken thisApp = win.mAppToken; 9487 9488 // If this window's application has been removed, just skip it. 9489 if (thisApp != null && (thisApp.removed || thisApp.sendingToBottom)) { 9490 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping app because " + (thisApp.removed 9491 ? "removed" : "sendingToBottom")); 9492 continue; 9493 } 9494 9495 // If there is a focused app, don't allow focus to go to any 9496 // windows below it. If this is an application window, step 9497 // through the app tokens until we find its app. 9498 if (thisApp != null && nextApp != null && thisApp != nextApp 9499 && win.mAttrs.type != TYPE_APPLICATION_STARTING) { 9500 int origAppIndex = nextAppIndex; 9501 while (nextAppIndex > 0) { 9502 if (nextApp == mFocusedApp) { 9503 // Whoops, we are below the focused app... no focus 9504 // for you! 9505 if (localLOGV || DEBUG_FOCUS) Slog.v( 9506 TAG, "Reached focused app: " + mFocusedApp); 9507 return null; 9508 } 9509 nextAppIndex--; 9510 nextApp = mAppTokens.get(nextAppIndex); 9511 if (nextApp == thisApp) { 9512 break; 9513 } 9514 } 9515 if (thisApp != nextApp) { 9516 // Uh oh, the app token doesn't exist! This shouldn't 9517 // happen, but if it does we can get totally hosed... 9518 // so restart at the original app. 9519 nextAppIndex = origAppIndex; 9520 nextApp = mAppTokens.get(nextAppIndex); 9521 } 9522 } 9523 9524 // Dispatch to this window if it is wants key events. 9525 if (win.canReceiveKeys()) { 9526 if (DEBUG_FOCUS) Slog.v( 9527 TAG, "Found focus @ " + i + " = " + win); 9528 return win; 9529 } 9530 } 9531 return null; 9532 } 9533 9534 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 9535 if (mDisplayFrozen) { 9536 return; 9537 } 9538 9539 if (!mDisplayReady || !mPolicy.isScreenOnFully()) { 9540 // No need to freeze the screen before the system is ready or if 9541 // the screen is off. 9542 return; 9543 } 9544 9545 mScreenFrozenLock.acquire(); 9546 9547 mDisplayFrozen = true; 9548 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 9549 mLastFinishedFreezeSource = null; 9550 9551 mInputMonitor.freezeInputDispatchingLw(); 9552 9553 // Clear the last input window -- that is just used for 9554 // clean transitions between IMEs, and if we are freezing 9555 // the screen then the whole world is changing behind the scenes. 9556 mPolicy.setLastInputMethodWindowLw(null, null); 9557 9558 if (mAppTransition.isTransitionSet()) { 9559 mAppTransition.freeze(); 9560 } 9561 9562 if (PROFILE_ORIENTATION) { 9563 File file = new File("/data/system/frozen"); 9564 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 9565 } 9566 9567 if (CUSTOM_SCREEN_ROTATION) { 9568 mExitAnimId = exitAnim; 9569 mEnterAnimId = enterAnim; 9570 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9571 final int displayId = displayContent.getDisplayId(); 9572 ScreenRotationAnimation screenRotationAnimation = 9573 mAnimator.getScreenRotationAnimationLocked(displayId); 9574 if (screenRotationAnimation != null) { 9575 screenRotationAnimation.kill(); 9576 } 9577 9578 // TODO(multidisplay): rotation on main screen only. 9579 final Display display = displayContent.getDisplay(); 9580 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9581 screenRotationAnimation = new ScreenRotationAnimation(mContext, 9582 display, mFxSession, inTransaction, displayInfo.logicalWidth, 9583 displayInfo.logicalHeight, display.getRotation()); 9584 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 9585 } 9586 } 9587 9588 private void stopFreezingDisplayLocked() { 9589 if (!mDisplayFrozen) { 9590 return; 9591 } 9592 9593 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen 9594 || mClientFreezingScreen) { 9595 if (DEBUG_ORIENTATION) Slog.d(TAG, 9596 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 9597 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 9598 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 9599 + ", mClientFreezingScreen=" + mClientFreezingScreen); 9600 return; 9601 } 9602 9603 mDisplayFrozen = false; 9604 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 9605 StringBuilder sb = new StringBuilder(128); 9606 sb.append("Screen frozen for "); 9607 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 9608 if (mLastFinishedFreezeSource != null) { 9609 sb.append(" due to "); 9610 sb.append(mLastFinishedFreezeSource); 9611 } 9612 Slog.i(TAG, sb.toString()); 9613 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 9614 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 9615 if (PROFILE_ORIENTATION) { 9616 Debug.stopMethodTracing(); 9617 } 9618 9619 boolean updateRotation = false; 9620 9621 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9622 final int displayId = displayContent.getDisplayId(); 9623 ScreenRotationAnimation screenRotationAnimation = 9624 mAnimator.getScreenRotationAnimationLocked(displayId); 9625 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 9626 && screenRotationAnimation.hasScreenshot()) { 9627 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 9628 // TODO(multidisplay): rotation on main screen only. 9629 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9630 // Get rotation animation again, with new top window 9631 boolean isDimming = mAnimator.isDimmingLocked(Display.DEFAULT_DISPLAY); 9632 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 9633 mExitAnimId = mEnterAnimId = 0; 9634 } 9635 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 9636 mTransitionAnimationScale, displayInfo.logicalWidth, 9637 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 9638 scheduleAnimationLocked(); 9639 } else { 9640 screenRotationAnimation.kill(); 9641 screenRotationAnimation = null; 9642 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 9643 updateRotation = true; 9644 } 9645 } else { 9646 if (screenRotationAnimation != null) { 9647 screenRotationAnimation.kill(); 9648 screenRotationAnimation = null; 9649 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 9650 } 9651 updateRotation = true; 9652 } 9653 9654 mInputMonitor.thawInputDispatchingLw(); 9655 9656 boolean configChanged; 9657 9658 // While the display is frozen we don't re-compute the orientation 9659 // to avoid inconsistent states. However, something interesting 9660 // could have actually changed during that time so re-evaluate it 9661 // now to catch that. 9662 configChanged = updateOrientationFromAppTokensLocked(false); 9663 9664 // A little kludge: a lot could have happened while the 9665 // display was frozen, so now that we are coming back we 9666 // do a gc so that any remote references the system 9667 // processes holds on others can be released if they are 9668 // no longer needed. 9669 mH.removeMessages(H.FORCE_GC); 9670 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 9671 9672 mScreenFrozenLock.release(); 9673 9674 if (updateRotation) { 9675 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9676 configChanged |= updateRotationUncheckedLocked(false); 9677 } 9678 9679 if (configChanged) { 9680 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9681 } 9682 } 9683 9684 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 9685 DisplayMetrics dm) { 9686 if (index < tokens.length) { 9687 String str = tokens[index]; 9688 if (str != null && str.length() > 0) { 9689 try { 9690 int val = Integer.parseInt(str); 9691 return val; 9692 } catch (Exception e) { 9693 } 9694 } 9695 } 9696 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 9697 return defDps; 9698 } 9699 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 9700 return val; 9701 } 9702 9703 void createWatermarkInTransaction() { 9704 if (mWatermark != null) { 9705 return; 9706 } 9707 9708 File file = new File("/system/etc/setup.conf"); 9709 FileInputStream in = null; 9710 DataInputStream ind = null; 9711 try { 9712 in = new FileInputStream(file); 9713 ind = new DataInputStream(in); 9714 String line = ind.readLine(); 9715 if (line != null) { 9716 String[] toks = line.split("%"); 9717 if (toks != null && toks.length > 0) { 9718 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 9719 mRealDisplayMetrics, mFxSession, toks); 9720 } 9721 } 9722 } catch (FileNotFoundException e) { 9723 } catch (IOException e) { 9724 } finally { 9725 if (ind != null) { 9726 try { 9727 ind.close(); 9728 } catch (IOException e) { 9729 } 9730 } else if (in != null) { 9731 try { 9732 in.close(); 9733 } catch (IOException e) { 9734 } 9735 } 9736 } 9737 } 9738 9739 @Override 9740 public void statusBarVisibilityChanged(int visibility) { 9741 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 9742 != PackageManager.PERMISSION_GRANTED) { 9743 throw new SecurityException("Caller does not hold permission " 9744 + android.Manifest.permission.STATUS_BAR); 9745 } 9746 9747 synchronized (mWindowMap) { 9748 mLastStatusBarVisibility = visibility; 9749 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 9750 updateStatusBarVisibilityLocked(visibility); 9751 } 9752 } 9753 9754 // TOOD(multidisplay): StatusBar on multiple screens? 9755 void updateStatusBarVisibilityLocked(int visibility) { 9756 mInputManager.setSystemUiVisibility(visibility); 9757 final WindowList windows = getDefaultWindowListLocked(); 9758 final int N = windows.size(); 9759 for (int i = 0; i < N; i++) { 9760 WindowState ws = windows.get(i); 9761 try { 9762 int curValue = ws.mSystemUiVisibility; 9763 int diff = curValue ^ visibility; 9764 // We are only interested in differences of one of the 9765 // clearable flags... 9766 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 9767 // ...if it has actually been cleared. 9768 diff &= ~visibility; 9769 int newValue = (curValue&~diff) | (visibility&diff); 9770 if (newValue != curValue) { 9771 ws.mSeq++; 9772 ws.mSystemUiVisibility = newValue; 9773 } 9774 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 9775 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 9776 visibility, newValue, diff); 9777 } 9778 } catch (RemoteException e) { 9779 // so sorry 9780 } 9781 } 9782 } 9783 9784 @Override 9785 public void reevaluateStatusBarVisibility() { 9786 synchronized (mWindowMap) { 9787 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 9788 updateStatusBarVisibilityLocked(visibility); 9789 performLayoutAndPlaceSurfacesLocked(); 9790 } 9791 } 9792 9793 @Override 9794 public FakeWindow addFakeWindow(Looper looper, 9795 InputEventReceiver.Factory inputEventReceiverFactory, 9796 String name, int windowType, int layoutParamsFlags, boolean canReceiveKeys, 9797 boolean hasFocus, boolean touchFullscreen) { 9798 synchronized (mWindowMap) { 9799 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 9800 name, windowType, 9801 layoutParamsFlags, canReceiveKeys, hasFocus, touchFullscreen); 9802 int i=0; 9803 while (i<mFakeWindows.size()) { 9804 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 9805 break; 9806 } 9807 } 9808 mFakeWindows.add(i, fw); 9809 mInputMonitor.updateInputWindowsLw(true); 9810 return fw; 9811 } 9812 } 9813 9814 boolean removeFakeWindowLocked(FakeWindow window) { 9815 synchronized (mWindowMap) { 9816 if (mFakeWindows.remove(window)) { 9817 mInputMonitor.updateInputWindowsLw(true); 9818 return true; 9819 } 9820 return false; 9821 } 9822 } 9823 9824 // It is assumed that this method is called only by InputMethodManagerService. 9825 public void saveLastInputMethodWindowForTransition() { 9826 synchronized (mWindowMap) { 9827 // TODO(multidisplay): Pass in the displayID. 9828 DisplayContent displayContent = getDefaultDisplayContentLocked(); 9829 if (mInputMethodWindow != null) { 9830 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 9831 } 9832 } 9833 } 9834 9835 @Override 9836 public boolean hasNavigationBar() { 9837 return mPolicy.hasNavigationBar(); 9838 } 9839 9840 @Override 9841 public void lockNow(Bundle options) { 9842 mPolicy.lockNow(options); 9843 } 9844 9845 @Override 9846 public boolean isSafeModeEnabled() { 9847 return mSafeMode; 9848 } 9849 9850 @Override 9851 public void showAssistant() { 9852 // TODO: What permission? 9853 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER) 9854 != PackageManager.PERMISSION_GRANTED) { 9855 return; 9856 } 9857 mPolicy.showAssistant(); 9858 } 9859 9860 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 9861 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 9862 mPolicy.dump(" ", pw, args); 9863 } 9864 9865 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 9866 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 9867 mAnimator.dumpLocked(pw, " ", dumpAll); 9868 } 9869 9870 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 9871 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 9872 if (mTokenMap.size() > 0) { 9873 pw.println(" All tokens:"); 9874 Iterator<WindowToken> it = mTokenMap.values().iterator(); 9875 while (it.hasNext()) { 9876 WindowToken token = it.next(); 9877 pw.print(" "); pw.print(token); 9878 if (dumpAll) { 9879 pw.println(':'); 9880 token.dump(pw, " "); 9881 } else { 9882 pw.println(); 9883 } 9884 } 9885 } 9886 if (mWallpaperTokens.size() > 0) { 9887 pw.println(); 9888 pw.println(" Wallpaper tokens:"); 9889 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 9890 WindowToken token = mWallpaperTokens.get(i); 9891 pw.print(" Wallpaper #"); pw.print(i); 9892 pw.print(' '); pw.print(token); 9893 if (dumpAll) { 9894 pw.println(':'); 9895 token.dump(pw, " "); 9896 } else { 9897 pw.println(); 9898 } 9899 } 9900 } 9901 if (mAppTokens.size() > 0) { 9902 pw.println(); 9903 pw.println(" Application tokens in Z order:"); 9904 for (int i=mAppTokens.size()-1; i>=0; i--) { 9905 pw.print(" App #"); pw.print(i); 9906 pw.print(' '); pw.print(mAppTokens.get(i)); pw.println(":"); 9907 mAppTokens.get(i).dump(pw, " "); 9908 } 9909 } 9910 if (mFinishedStarting.size() > 0) { 9911 pw.println(); 9912 pw.println(" Finishing start of application tokens:"); 9913 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 9914 WindowToken token = mFinishedStarting.get(i); 9915 pw.print(" Finished Starting #"); pw.print(i); 9916 pw.print(' '); pw.print(token); 9917 if (dumpAll) { 9918 pw.println(':'); 9919 token.dump(pw, " "); 9920 } else { 9921 pw.println(); 9922 } 9923 } 9924 } 9925 if (mExitingTokens.size() > 0) { 9926 pw.println(); 9927 pw.println(" Exiting tokens:"); 9928 for (int i=mExitingTokens.size()-1; i>=0; i--) { 9929 WindowToken token = mExitingTokens.get(i); 9930 pw.print(" Exiting #"); pw.print(i); 9931 pw.print(' '); pw.print(token); 9932 if (dumpAll) { 9933 pw.println(':'); 9934 token.dump(pw, " "); 9935 } else { 9936 pw.println(); 9937 } 9938 } 9939 } 9940 if (mExitingAppTokens.size() > 0) { 9941 pw.println(); 9942 pw.println(" Exiting application tokens:"); 9943 for (int i=mExitingAppTokens.size()-1; i>=0; i--) { 9944 WindowToken token = mExitingAppTokens.get(i); 9945 pw.print(" Exiting App #"); pw.print(i); 9946 pw.print(' '); pw.print(token); 9947 if (dumpAll) { 9948 pw.println(':'); 9949 token.dump(pw, " "); 9950 } else { 9951 pw.println(); 9952 } 9953 } 9954 } 9955 if (mAppTransition.isRunning() && mAnimatingAppTokens.size() > 0) { 9956 pw.println(); 9957 pw.println(" Application tokens during animation:"); 9958 for (int i=mAnimatingAppTokens.size()-1; i>=0; i--) { 9959 WindowToken token = mAnimatingAppTokens.get(i); 9960 pw.print(" App moving to bottom #"); pw.print(i); 9961 pw.print(' '); pw.print(token); 9962 if (dumpAll) { 9963 pw.println(':'); 9964 token.dump(pw, " "); 9965 } else { 9966 pw.println(); 9967 } 9968 } 9969 } 9970 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 9971 pw.println(); 9972 if (mOpeningApps.size() > 0) { 9973 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 9974 } 9975 if (mClosingApps.size() > 0) { 9976 pw.print(" mClosingApps="); pw.println(mClosingApps); 9977 } 9978 } 9979 } 9980 9981 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 9982 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 9983 if (mSessions.size() > 0) { 9984 Iterator<Session> it = mSessions.iterator(); 9985 while (it.hasNext()) { 9986 Session s = it.next(); 9987 pw.print(" Session "); pw.print(s); pw.println(':'); 9988 s.dump(pw, " "); 9989 } 9990 } 9991 } 9992 9993 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 9994 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 9995 if (mDisplayReady) { 9996 DisplayContentsIterator dCIterator = new DisplayContentsIterator(); 9997 while (dCIterator.hasNext()) { 9998 dCIterator.next().dump(" ", pw); 9999 } 10000 } else { 10001 pw.println(" NO DISPLAY"); 10002 } 10003 } 10004 10005 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 10006 ArrayList<WindowState> windows) { 10007 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 10008 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 10009 } 10010 10011 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 10012 ArrayList<WindowState> windows) { 10013 int j = 0; 10014 final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR); 10015 while (iterator.hasNext()) { 10016 final WindowState w = iterator.next(); 10017 if (windows == null || windows.contains(w)) { 10018 pw.print(" Window #"); pw.print(j++); pw.print(' '); 10019 pw.print(w); pw.println(":"); 10020 w.dump(pw, " ", dumpAll || windows != null); 10021 } 10022 } 10023 if (mInputMethodDialogs.size() > 0) { 10024 pw.println(); 10025 pw.println(" Input method dialogs:"); 10026 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 10027 WindowState w = mInputMethodDialogs.get(i); 10028 if (windows == null || windows.contains(w)) { 10029 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 10030 } 10031 } 10032 } 10033 if (mPendingRemove.size() > 0) { 10034 pw.println(); 10035 pw.println(" Remove pending for:"); 10036 for (int i=mPendingRemove.size()-1; i>=0; i--) { 10037 WindowState w = mPendingRemove.get(i); 10038 if (windows == null || windows.contains(w)) { 10039 pw.print(" Remove #"); pw.print(i); pw.print(' '); 10040 pw.print(w); 10041 if (dumpAll) { 10042 pw.println(":"); 10043 w.dump(pw, " ", true); 10044 } else { 10045 pw.println(); 10046 } 10047 } 10048 } 10049 } 10050 if (mForceRemoves != null && mForceRemoves.size() > 0) { 10051 pw.println(); 10052 pw.println(" Windows force removing:"); 10053 for (int i=mForceRemoves.size()-1; i>=0; i--) { 10054 WindowState w = mForceRemoves.get(i); 10055 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10056 pw.print(w); 10057 if (dumpAll) { 10058 pw.println(":"); 10059 w.dump(pw, " ", true); 10060 } else { 10061 pw.println(); 10062 } 10063 } 10064 } 10065 if (mDestroySurface.size() > 0) { 10066 pw.println(); 10067 pw.println(" Windows waiting to destroy their surface:"); 10068 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10069 WindowState w = mDestroySurface.get(i); 10070 if (windows == null || windows.contains(w)) { 10071 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10072 pw.print(w); 10073 if (dumpAll) { 10074 pw.println(":"); 10075 w.dump(pw, " ", true); 10076 } else { 10077 pw.println(); 10078 } 10079 } 10080 } 10081 } 10082 if (mLosingFocus.size() > 0) { 10083 pw.println(); 10084 pw.println(" Windows losing focus:"); 10085 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10086 WindowState w = mLosingFocus.get(i); 10087 if (windows == null || windows.contains(w)) { 10088 pw.print(" Losing #"); pw.print(i); pw.print(' '); 10089 pw.print(w); 10090 if (dumpAll) { 10091 pw.println(":"); 10092 w.dump(pw, " ", true); 10093 } else { 10094 pw.println(); 10095 } 10096 } 10097 } 10098 } 10099 if (mResizingWindows.size() > 0) { 10100 pw.println(); 10101 pw.println(" Windows waiting to resize:"); 10102 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10103 WindowState w = mResizingWindows.get(i); 10104 if (windows == null || windows.contains(w)) { 10105 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 10106 pw.print(w); 10107 if (dumpAll) { 10108 pw.println(":"); 10109 w.dump(pw, " ", true); 10110 } else { 10111 pw.println(); 10112 } 10113 } 10114 } 10115 } 10116 if (mWaitingForDrawn.size() > 0) { 10117 pw.println(); 10118 pw.println(" Clients waiting for these windows to be drawn:"); 10119 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10120 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i); 10121 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first); 10122 pw.print(": "); pw.println(pair.second); 10123 } 10124 } 10125 pw.println(); 10126 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10127 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10128 if (mLastFocus != mCurrentFocus) { 10129 pw.print(" mLastFocus="); pw.println(mLastFocus); 10130 } 10131 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10132 if (mInputMethodTarget != null) { 10133 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10134 } 10135 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10136 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10137 pw.print(" mLastDisplayFreezeDuration="); 10138 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 10139 if ( mLastFinishedFreezeSource != null) { 10140 pw.print(" due to "); 10141 pw.print(mLastFinishedFreezeSource); 10142 } 10143 pw.println(); 10144 if (dumpAll) { 10145 pw.print(" mSystemDecorRect="); pw.print(mSystemDecorRect.toShortString()); 10146 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 10147 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 10148 if (mLastStatusBarVisibility != 0) { 10149 pw.print(" mLastStatusBarVisibility=0x"); 10150 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 10151 } 10152 if (mInputMethodWindow != null) { 10153 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10154 } 10155 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 10156 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) { 10157 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 10158 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 10159 } 10160 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 10161 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 10162 if (mInputMethodAnimLayerAdjustment != 0 || 10163 mWallpaperAnimLayerAdjustment != 0) { 10164 pw.print(" mInputMethodAnimLayerAdjustment="); 10165 pw.print(mInputMethodAnimLayerAdjustment); 10166 pw.print(" mWallpaperAnimLayerAdjustment="); 10167 pw.println(mWallpaperAnimLayerAdjustment); 10168 } 10169 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10170 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10171 if (needsLayout()) { 10172 pw.print(" layoutNeeded on displays="); 10173 DisplayContentsIterator dcIterator = new DisplayContentsIterator(); 10174 while (dcIterator.hasNext()) { 10175 final DisplayContent displayContent = dcIterator.next(); 10176 if (displayContent.layoutNeeded) { 10177 pw.print(displayContent.getDisplayId()); 10178 } 10179 } 10180 pw.println(); 10181 } 10182 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 10183 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10184 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 10185 pw.print(" client="); pw.print(mClientFreezingScreen); 10186 pw.print(" apps="); pw.print(mAppsFreezingScreen); 10187 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 10188 pw.print(" mRotation="); pw.print(mRotation); 10189 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 10190 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 10191 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 10192 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 10193 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); 10194 pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale); 10195 pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale); 10196 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); 10197 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 10198 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 10199 pw.println(" mLayoutToAnim:"); 10200 mAppTransition.dump(pw); 10201 } 10202 } 10203 10204 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10205 int opti, boolean dumpAll) { 10206 WindowList windows = new WindowList(); 10207 if ("visible".equals(name)) { 10208 synchronized(mWindowMap) { 10209 final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR); 10210 while (iterator.hasNext()) { 10211 final WindowState w = iterator.next(); 10212 if (w.mWinAnimator.mSurfaceShown) { 10213 windows.add(w); 10214 } 10215 } 10216 } 10217 } else { 10218 int objectId = 0; 10219 // See if this is an object ID. 10220 try { 10221 objectId = Integer.parseInt(name, 16); 10222 name = null; 10223 } catch (RuntimeException e) { 10224 } 10225 synchronized(mWindowMap) { 10226 final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR); 10227 while (iterator.hasNext()) { 10228 final WindowState w = iterator.next(); 10229 if (name != null) { 10230 if (w.mAttrs.getTitle().toString().contains(name)) { 10231 windows.add(w); 10232 } 10233 } else if (System.identityHashCode(w) == objectId) { 10234 windows.add(w); 10235 } 10236 } 10237 } 10238 } 10239 10240 if (windows.size() <= 0) { 10241 return false; 10242 } 10243 10244 synchronized(mWindowMap) { 10245 dumpWindowsLocked(pw, dumpAll, windows); 10246 } 10247 return true; 10248 } 10249 10250 void dumpLastANRLocked(PrintWriter pw) { 10251 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10252 if (mLastANRState == null) { 10253 pw.println(" <no ANR has occurred since boot>"); 10254 } else { 10255 pw.println(mLastANRState); 10256 } 10257 } 10258 10259 /** 10260 * Saves information about the state of the window manager at 10261 * the time an ANR occurred before anything else in the system changes 10262 * in response. 10263 * 10264 * @param appWindowToken The application that ANR'd, may be null. 10265 * @param windowState The window that ANR'd, may be null. 10266 */ 10267 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState) { 10268 StringWriter sw = new StringWriter(); 10269 PrintWriter pw = new PrintWriter(sw); 10270 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10271 if (appWindowToken != null) { 10272 pw.println(" Application at fault: " + appWindowToken.stringName); 10273 } 10274 if (windowState != null) { 10275 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10276 } 10277 pw.println(); 10278 dumpWindowsNoHeaderLocked(pw, true, null); 10279 pw.close(); 10280 mLastANRState = sw.toString(); 10281 } 10282 10283 @Override 10284 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10285 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10286 != PackageManager.PERMISSION_GRANTED) { 10287 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10288 + Binder.getCallingPid() 10289 + ", uid=" + Binder.getCallingUid()); 10290 return; 10291 } 10292 10293 boolean dumpAll = false; 10294 10295 int opti = 0; 10296 while (opti < args.length) { 10297 String opt = args[opti]; 10298 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10299 break; 10300 } 10301 opti++; 10302 if ("-a".equals(opt)) { 10303 dumpAll = true; 10304 } else if ("-h".equals(opt)) { 10305 pw.println("Window manager dump options:"); 10306 pw.println(" [-a] [-h] [cmd] ..."); 10307 pw.println(" cmd may be one of:"); 10308 pw.println(" l[astanr]: last ANR information"); 10309 pw.println(" p[policy]: policy state"); 10310 pw.println(" a[animator]: animator state"); 10311 pw.println(" s[essions]: active sessions"); 10312 pw.println(" d[isplays]: active display contents"); 10313 pw.println(" t[okens]: token list"); 10314 pw.println(" w[indows]: window list"); 10315 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10316 pw.println(" be a partial substring in a window name, a"); 10317 pw.println(" Window hex object identifier, or"); 10318 pw.println(" \"all\" for all windows, or"); 10319 pw.println(" \"visible\" for the visible windows."); 10320 pw.println(" -a: include all available server state."); 10321 return; 10322 } else { 10323 pw.println("Unknown argument: " + opt + "; use -h for help"); 10324 } 10325 } 10326 10327 // Is the caller requesting to dump a particular piece of data? 10328 if (opti < args.length) { 10329 String cmd = args[opti]; 10330 opti++; 10331 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10332 synchronized(mWindowMap) { 10333 dumpLastANRLocked(pw); 10334 } 10335 return; 10336 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10337 synchronized(mWindowMap) { 10338 dumpPolicyLocked(pw, args, true); 10339 } 10340 return; 10341 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 10342 synchronized(mWindowMap) { 10343 dumpAnimatorLocked(pw, args, true); 10344 } 10345 return; 10346 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10347 synchronized(mWindowMap) { 10348 dumpSessionsLocked(pw, true); 10349 } 10350 return; 10351 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 10352 synchronized(mWindowMap) { 10353 dumpDisplayContentsLocked(pw, true); 10354 } 10355 return; 10356 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10357 synchronized(mWindowMap) { 10358 dumpTokensLocked(pw, true); 10359 } 10360 return; 10361 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10362 synchronized(mWindowMap) { 10363 dumpWindowsLocked(pw, true, null); 10364 } 10365 return; 10366 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10367 synchronized(mWindowMap) { 10368 dumpWindowsLocked(pw, true, null); 10369 } 10370 return; 10371 } else { 10372 // Dumping a single name? 10373 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10374 pw.println("Bad window command, or no windows match: " + cmd); 10375 pw.println("Use -h for help."); 10376 } 10377 return; 10378 } 10379 } 10380 10381 synchronized(mWindowMap) { 10382 pw.println(); 10383 if (dumpAll) { 10384 pw.println("-------------------------------------------------------------------------------"); 10385 } 10386 dumpLastANRLocked(pw); 10387 pw.println(); 10388 if (dumpAll) { 10389 pw.println("-------------------------------------------------------------------------------"); 10390 } 10391 dumpPolicyLocked(pw, args, dumpAll); 10392 pw.println(); 10393 if (dumpAll) { 10394 pw.println("-------------------------------------------------------------------------------"); 10395 } 10396 dumpAnimatorLocked(pw, args, dumpAll); 10397 pw.println(); 10398 if (dumpAll) { 10399 pw.println("-------------------------------------------------------------------------------"); 10400 } 10401 dumpSessionsLocked(pw, dumpAll); 10402 pw.println(); 10403 if (dumpAll) { 10404 pw.println("-------------------------------------------------------------------------------"); 10405 } 10406 dumpDisplayContentsLocked(pw, dumpAll); 10407 pw.println(); 10408 if (dumpAll) { 10409 pw.println("-------------------------------------------------------------------------------"); 10410 } 10411 dumpTokensLocked(pw, dumpAll); 10412 pw.println(); 10413 if (dumpAll) { 10414 pw.println("-------------------------------------------------------------------------------"); 10415 } 10416 dumpWindowsLocked(pw, dumpAll, null); 10417 } 10418 } 10419 10420 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10421 @Override 10422 public void monitor() { 10423 synchronized (mWindowMap) { } 10424 } 10425 10426 public interface OnHardKeyboardStatusChangeListener { 10427 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 10428 } 10429 10430 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 10431 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 10432 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 10433 Integer.toHexString(pendingLayoutChanges)); 10434 } 10435 } 10436 10437 private DisplayContent newDisplayContentLocked(final Display display) { 10438 DisplayContent displayContent = new DisplayContent(display); 10439 mDisplayContents.put(display.getDisplayId(), displayContent); 10440 final Rect rect = new Rect(); 10441 DisplayInfo info = displayContent.getDisplayInfo(); 10442 mDisplaySettings.getOverscanLocked(info.name, rect); 10443 info.overscanLeft = rect.left; 10444 info.overscanTop = rect.top; 10445 info.overscanRight = rect.right; 10446 info.overscanBottom = rect.bottom; 10447 mDisplayManagerService.setOverscan(display.getDisplayId(), rect.left, rect.top, 10448 rect.right, rect.bottom); 10449 mPolicy.setDisplayOverscan(displayContent.getDisplay(), rect.left, rect.top, 10450 rect.right, rect.bottom); 10451 return displayContent; 10452 } 10453 10454 public void createDisplayContentLocked(final Display display) { 10455 if (display == null) { 10456 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 10457 } 10458 newDisplayContentLocked(display); 10459 } 10460 10461 /** 10462 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 10463 * there is a Display for the displayId. 10464 * @param displayId The display the caller is interested in. 10465 * @return The DisplayContent associated with displayId or null if there is no Display for it. 10466 */ 10467 public DisplayContent getDisplayContentLocked(final int displayId) { 10468 DisplayContent displayContent = mDisplayContents.get(displayId); 10469 if (displayContent == null) { 10470 final Display display = mDisplayManager.getDisplay(displayId); 10471 if (display != null) { 10472 displayContent = newDisplayContentLocked(display); 10473 } 10474 } 10475 return displayContent; 10476 } 10477 10478 class DisplayContentsIterator implements Iterator<DisplayContent> { 10479 private int cur; 10480 10481 @Override 10482 public boolean hasNext() { 10483 return cur < mDisplayContents.size(); 10484 } 10485 10486 @Override 10487 public DisplayContent next() { 10488 if (hasNext()) { 10489 return mDisplayContents.valueAt(cur++); 10490 } 10491 throw new NoSuchElementException(); 10492 } 10493 10494 @Override 10495 public void remove() { 10496 throw new IllegalArgumentException("AllDisplayContentIterator.remove not implemented"); 10497 } 10498 } 10499 10500 final static boolean REVERSE_ITERATOR = true; 10501 class AllWindowsIterator implements Iterator<WindowState> { 10502 private DisplayContent mDisplayContent; 10503 private DisplayContentsIterator mDisplayContentsIterator; 10504 private WindowList mWindowList; 10505 private int mWindowListIndex; 10506 private boolean mReverse; 10507 10508 AllWindowsIterator() { 10509 mDisplayContentsIterator = new DisplayContentsIterator(); 10510 mDisplayContent = mDisplayContentsIterator.next(); 10511 mWindowList = mDisplayContent.getWindowList(); 10512 } 10513 10514 AllWindowsIterator(boolean reverse) { 10515 this(); 10516 mReverse = reverse; 10517 mWindowListIndex = reverse ? mWindowList.size() - 1 : 0; 10518 } 10519 10520 @Override 10521 public boolean hasNext() { 10522 if (mReverse) { 10523 return mWindowListIndex >= 0; 10524 } 10525 return mWindowListIndex < mWindowList.size(); 10526 } 10527 10528 @Override 10529 public WindowState next() { 10530 if (hasNext()) { 10531 WindowState win = mWindowList.get(mWindowListIndex); 10532 if (mReverse) { 10533 mWindowListIndex--; 10534 if (mWindowListIndex < 0 && mDisplayContentsIterator.hasNext()) { 10535 mDisplayContent = mDisplayContentsIterator.next(); 10536 mWindowList = mDisplayContent.getWindowList(); 10537 mWindowListIndex = mWindowList.size() - 1; 10538 } 10539 } else { 10540 mWindowListIndex++; 10541 if (mWindowListIndex >= mWindowList.size() 10542 && mDisplayContentsIterator.hasNext()) { 10543 mDisplayContent = mDisplayContentsIterator.next(); 10544 mWindowList = mDisplayContent.getWindowList(); 10545 mWindowListIndex = 0; 10546 } 10547 } 10548 return win; 10549 } 10550 throw new NoSuchElementException(); 10551 } 10552 10553 @Override 10554 public void remove() { 10555 throw new IllegalArgumentException("AllWindowsIterator.remove not implemented"); 10556 } 10557 } 10558 10559 // There is an inherent assumption that this will never return null. 10560 public DisplayContent getDefaultDisplayContentLocked() { 10561 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 10562 } 10563 10564 public WindowList getDefaultWindowListLocked() { 10565 return getDefaultDisplayContentLocked().getWindowList(); 10566 } 10567 10568 public DisplayInfo getDefaultDisplayInfoLocked() { 10569 return getDefaultDisplayContentLocked().getDisplayInfo(); 10570 } 10571 10572 /** 10573 * Return the list of WindowStates associated on the passed display. 10574 * @param display The screen to return windows from. 10575 * @return The list of WindowStates on the screen, or null if the there is no screen. 10576 */ 10577 public WindowList getWindowListLocked(final Display display) { 10578 return getWindowListLocked(display.getDisplayId()); 10579 } 10580 10581 /** 10582 * Return the list of WindowStates associated on the passed display. 10583 * @param displayId The screen to return windows from. 10584 * @return The list of WindowStates on the screen, or null if the there is no screen. 10585 */ 10586 public WindowList getWindowListLocked(final int displayId) { 10587 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10588 return displayContent != null ? displayContent.getWindowList() : null; 10589 } 10590 10591 @Override 10592 public void onDisplayAdded(int displayId) { 10593 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 10594 } 10595 10596 private void handleDisplayAddedLocked(int displayId) { 10597 final Display display = mDisplayManager.getDisplay(displayId); 10598 if (display != null) { 10599 createDisplayContentLocked(display); 10600 displayReady(displayId); 10601 } 10602 } 10603 10604 @Override 10605 public void onDisplayRemoved(int displayId) { 10606 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 10607 } 10608 10609 private void handleDisplayRemovedLocked(int displayId) { 10610 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10611 if (displayContent != null) { 10612 mDisplayContents.delete(displayId); 10613 WindowList windows = displayContent.getWindowList(); 10614 while (!windows.isEmpty()) { 10615 final WindowState win = windows.get(windows.size() - 1); 10616 removeWindowLocked(win.mSession, win); 10617 } 10618 } 10619 mAnimator.removeDisplayLocked(displayId); 10620 } 10621 10622 @Override 10623 public void onDisplayChanged(int displayId) { 10624 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 10625 } 10626 10627 private void handleDisplayChangedLocked(int displayId) { 10628 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10629 if (displayContent != null) { 10630 displayContent.updateDisplayInfo(); 10631 } 10632 } 10633} 10634