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