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