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