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