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