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