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