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