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