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