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