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