WindowManagerService.java revision 73850cb6991074e33c31d310ccb63a1f863f7b4e
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 boolean doRequest = false; 6875 // TODO(cmautner): As the number of bits grows, use masks of bit groups to 6876 // eliminate unnecessary tests. 6877 if ((msg.arg1 & LayoutFields.SET_UPDATE_ROTATION) != 0) { 6878 mInnerFields.mUpdateRotation = true; 6879 doRequest = true; 6880 } 6881 if ((msg.arg1 & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 6882 mInnerFields.mWallpaperMayChange = true; 6883 doRequest = true; 6884 } 6885 if ((msg.arg1 & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 6886 mInnerFields.mWallpaperForceHidingChanged = true; 6887 doRequest = true; 6888 } 6889 if ((msg.arg1 & LayoutFields.CLEAR_ORIENTATION_CHANGE_COMPLETE) != 0) { 6890 mInnerFields.mOrientationChangeComplete = false; 6891 } else { 6892 mInnerFields.mOrientationChangeComplete = true; 6893 if (mWindowsFreezingScreen) { 6894 doRequest = true; 6895 } 6896 } 6897 6898 if (doRequest) { 6899 requestTraversalLocked(); 6900 } 6901 } 6902 break; 6903 } 6904 6905 // Animation messages. Move to Window{State}Animator 6906 case SET_TRANSPARENT_REGION: { 6907 Pair<WindowStateAnimator, Region> pair = 6908 (Pair<WindowStateAnimator, Region>) msg.obj; 6909 final WindowStateAnimator winAnimator = pair.first; 6910 winAnimator.setTransparentRegionHint(pair.second); 6911 6912 scheduleAnimationLocked(); 6913 break; 6914 } 6915 6916 case SET_WALLPAPER_OFFSET: { 6917 final WindowStateAnimator winAnimator = (WindowStateAnimator) msg.obj; 6918 winAnimator.setWallpaperOffset(msg.arg1, msg.arg2); 6919 6920 scheduleAnimationLocked(); 6921 break; 6922 } 6923 6924 case SET_DIM_PARAMETERS: { 6925 mAnimator.mDimParams = (DimAnimator.Parameters) msg.obj; 6926 6927 scheduleAnimationLocked(); 6928 break; 6929 } 6930 6931 case SET_MOVE_ANIMATION: { 6932 WindowAnimator.SetAnimationParams params = 6933 (WindowAnimator.SetAnimationParams) msg.obj; 6934 WindowStateAnimator winAnimator = params.mWinAnimator; 6935 winAnimator.setAnimation(params.mAnimation); 6936 winAnimator.mAnimDw = params.mAnimDw; 6937 winAnimator.mAnimDh = params.mAnimDh; 6938 6939 scheduleAnimationLocked(); 6940 break; 6941 } 6942 } 6943 } 6944 } 6945 6946 // ------------------------------------------------------------- 6947 // IWindowManager API 6948 // ------------------------------------------------------------- 6949 6950 public IWindowSession openSession(IInputMethodClient client, 6951 IInputContext inputContext) { 6952 if (client == null) throw new IllegalArgumentException("null client"); 6953 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 6954 Session session = new Session(this, client, inputContext); 6955 return session; 6956 } 6957 6958 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 6959 synchronized (mWindowMap) { 6960 // The focus for the client is the window immediately below 6961 // where we would place the input method window. 6962 int idx = findDesiredInputMethodWindowIndexLocked(false); 6963 WindowState imFocus; 6964 if (idx > 0) { 6965 imFocus = mWindows.get(idx-1); 6966 //Log.i(TAG, "Desired input method target: " + imFocus); 6967 //Log.i(TAG, "Current focus: " + this.mCurrentFocus); 6968 //Log.i(TAG, "Last focus: " + this.mLastFocus); 6969 if (imFocus != null) { 6970 // This may be a starting window, in which case we still want 6971 // to count it as okay. 6972 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 6973 && imFocus.mAppToken != null) { 6974 // The client has definitely started, so it really should 6975 // have a window in this app token. Let's look for it. 6976 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 6977 WindowState w = imFocus.mAppToken.windows.get(i); 6978 if (w != imFocus) { 6979 //Log.i(TAG, "Switching to real app window: " + w); 6980 imFocus = w; 6981 break; 6982 } 6983 } 6984 } 6985 //Log.i(TAG, "IM target client: " + imFocus.mSession.mClient); 6986 //if (imFocus.mSession.mClient != null) { 6987 // Log.i(TAG, "IM target client binder: " + imFocus.mSession.mClient.asBinder()); 6988 // Log.i(TAG, "Requesting client binder: " + client.asBinder()); 6989 //} 6990 if (imFocus.mSession.mClient != null && 6991 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 6992 return true; 6993 } 6994 6995 // Okay, how about this... what is the current focus? 6996 // It seems in some cases we may not have moved the IM 6997 // target window, such as when it was in a pop-up window, 6998 // so let's also look at the current focus. (An example: 6999 // go to Gmail, start searching so the keyboard goes up, 7000 // press home. Sometimes the IME won't go down.) 7001 // Would be nice to fix this more correctly, but it's 7002 // way at the end of a release, and this should be good enough. 7003 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null && 7004 mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7005 return true; 7006 } 7007 } 7008 } 7009 } 7010 return false; 7011 } 7012 7013 public void getDisplaySize(Point size) { 7014 synchronized(mDisplaySizeLock) { 7015 size.x = mAppDisplayWidth; 7016 size.y = mAppDisplayHeight; 7017 } 7018 } 7019 7020 public void getRealDisplaySize(Point size) { 7021 synchronized(mDisplaySizeLock) { 7022 size.x = mCurDisplayWidth; 7023 size.y = mCurDisplayHeight; 7024 } 7025 } 7026 7027 public void getInitialDisplaySize(Point size) { 7028 synchronized(mDisplaySizeLock) { 7029 size.x = mInitialDisplayWidth; 7030 size.y = mInitialDisplayHeight; 7031 } 7032 } 7033 7034 public int getMaximumSizeDimension() { 7035 synchronized(mDisplaySizeLock) { 7036 // Do this based on the raw screen size, until we are smarter. 7037 return mBaseDisplayWidth > mBaseDisplayHeight 7038 ? mBaseDisplayWidth : mBaseDisplayHeight; 7039 } 7040 } 7041 7042 public void setForcedDisplaySize(int longDimen, int shortDimen) { 7043 synchronized(mWindowMap) { 7044 int width, height; 7045 if (mInitialDisplayWidth < mInitialDisplayHeight) { 7046 width = shortDimen < mInitialDisplayWidth 7047 ? shortDimen : mInitialDisplayWidth; 7048 height = longDimen < mInitialDisplayHeight 7049 ? longDimen : mInitialDisplayHeight; 7050 } else { 7051 width = longDimen < mInitialDisplayWidth 7052 ? longDimen : mInitialDisplayWidth; 7053 height = shortDimen < mInitialDisplayHeight 7054 ? shortDimen : mInitialDisplayHeight; 7055 } 7056 setForcedDisplaySizeLocked(width, height); 7057 Settings.Secure.putString(mContext.getContentResolver(), 7058 Settings.Secure.DISPLAY_SIZE_FORCED, width + "," + height); 7059 } 7060 } 7061 7062 private void rebuildBlackFrame() { 7063 if (mBlackFrame != null) { 7064 mBlackFrame.kill(); 7065 mBlackFrame = null; 7066 } 7067 if (mBaseDisplayWidth < mInitialDisplayWidth 7068 || mBaseDisplayHeight < mInitialDisplayHeight) { 7069 int initW, initH, baseW, baseH; 7070 final boolean rotated = (mRotation == Surface.ROTATION_90 7071 || mRotation == Surface.ROTATION_270); 7072 if (rotated) { 7073 initW = mInitialDisplayHeight; 7074 initH = mInitialDisplayWidth; 7075 baseW = mBaseDisplayHeight; 7076 baseH = mBaseDisplayWidth; 7077 } else { 7078 initW = mInitialDisplayWidth; 7079 initH = mInitialDisplayHeight; 7080 baseW = mBaseDisplayWidth; 7081 baseH = mBaseDisplayHeight; 7082 } 7083 Rect outer = new Rect(0, 0, initW, initH); 7084 Rect inner = new Rect(0, 0, baseW, baseH); 7085 try { 7086 mBlackFrame = new BlackFrame(mFxSession, outer, inner, MASK_LAYER); 7087 } catch (Surface.OutOfResourcesException e) { 7088 } 7089 } 7090 } 7091 7092 private void readForcedDisplaySizeLocked() { 7093 final String str = Settings.Secure.getString(mContext.getContentResolver(), 7094 Settings.Secure.DISPLAY_SIZE_FORCED); 7095 if (str == null || str.length() == 0) { 7096 return; 7097 } 7098 final int pos = str.indexOf(','); 7099 if (pos <= 0 || str.lastIndexOf(',') != pos) { 7100 return; 7101 } 7102 int width, height; 7103 try { 7104 width = Integer.parseInt(str.substring(0, pos)); 7105 height = Integer.parseInt(str.substring(pos+1)); 7106 } catch (NumberFormatException ex) { 7107 return; 7108 } 7109 setForcedDisplaySizeLocked(width, height); 7110 } 7111 7112 private void setForcedDisplaySizeLocked(int width, int height) { 7113 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7114 7115 synchronized(mDisplaySizeLock) { 7116 mBaseDisplayWidth = width; 7117 mBaseDisplayHeight = height; 7118 } 7119 mPolicy.setInitialDisplaySize(mDisplay, mBaseDisplayWidth, mBaseDisplayHeight); 7120 7121 mLayoutNeeded = true; 7122 7123 boolean configChanged = updateOrientationFromAppTokensLocked(false); 7124 mTempConfiguration.setToDefaults(); 7125 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 7126 if (computeScreenConfigurationLocked(mTempConfiguration)) { 7127 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 7128 configChanged = true; 7129 } 7130 } 7131 7132 if (configChanged) { 7133 mWaitingForConfig = true; 7134 startFreezingDisplayLocked(false); 7135 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 7136 } 7137 7138 rebuildBlackFrame(); 7139 7140 performLayoutAndPlaceSurfacesLocked(); 7141 } 7142 7143 public void clearForcedDisplaySize() { 7144 synchronized(mWindowMap) { 7145 setForcedDisplaySizeLocked(mInitialDisplayWidth, mInitialDisplayHeight); 7146 Settings.Secure.putString(mContext.getContentResolver(), 7147 Settings.Secure.DISPLAY_SIZE_FORCED, ""); 7148 } 7149 } 7150 7151 public boolean hasSystemNavBar() { 7152 return mPolicy.hasSystemNavBar(); 7153 } 7154 7155 // ------------------------------------------------------------- 7156 // Internals 7157 // ------------------------------------------------------------- 7158 7159 final WindowState windowForClientLocked(Session session, IWindow client, 7160 boolean throwOnError) { 7161 return windowForClientLocked(session, client.asBinder(), throwOnError); 7162 } 7163 7164 final WindowState windowForClientLocked(Session session, IBinder client, 7165 boolean throwOnError) { 7166 WindowState win = mWindowMap.get(client); 7167 if (localLOGV) Slog.v( 7168 TAG, "Looking up client " + client + ": " + win); 7169 if (win == null) { 7170 RuntimeException ex = new IllegalArgumentException( 7171 "Requested window " + client + " does not exist"); 7172 if (throwOnError) { 7173 throw ex; 7174 } 7175 Slog.w(TAG, "Failed looking up window", ex); 7176 return null; 7177 } 7178 if (session != null && win.mSession != session) { 7179 RuntimeException ex = new IllegalArgumentException( 7180 "Requested window " + client + " is in session " + 7181 win.mSession + ", not " + session); 7182 if (throwOnError) { 7183 throw ex; 7184 } 7185 Slog.w(TAG, "Failed looking up window", ex); 7186 return null; 7187 } 7188 7189 return win; 7190 } 7191 7192 final void rebuildAppWindowListLocked() { 7193 int NW = mWindows.size(); 7194 int i; 7195 int lastWallpaper = -1; 7196 int numRemoved = 0; 7197 7198 if (mRebuildTmp.length < NW) { 7199 mRebuildTmp = new WindowState[NW+10]; 7200 } 7201 7202 // First remove all existing app windows. 7203 i=0; 7204 while (i < NW) { 7205 WindowState w = mWindows.get(i); 7206 if (w.mAppToken != null) { 7207 WindowState win = mWindows.remove(i); 7208 win.mRebuilding = true; 7209 mRebuildTmp[numRemoved] = win; 7210 mWindowsChanged = true; 7211 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 7212 "Rebuild removing window: " + win); 7213 NW--; 7214 numRemoved++; 7215 continue; 7216 } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER 7217 && lastWallpaper == i-1) { 7218 lastWallpaper = i; 7219 } 7220 i++; 7221 } 7222 7223 // The wallpaper window(s) typically live at the bottom of the stack, 7224 // so skip them before adding app tokens. 7225 lastWallpaper++; 7226 i = lastWallpaper; 7227 7228 // First add all of the exiting app tokens... these are no longer 7229 // in the main app list, but still have windows shown. We put them 7230 // in the back because now that the animation is over we no longer 7231 // will care about them. 7232 int NT = mExitingAppTokens.size(); 7233 for (int j=0; j<NT; j++) { 7234 i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j)); 7235 } 7236 7237 // And add in the still active app tokens in Z order. 7238 NT = mAppTokens.size(); 7239 for (int j=0; j<NT; j++) { 7240 i = reAddAppWindowsLocked(i, mAppTokens.get(j)); 7241 } 7242 7243 i -= lastWallpaper; 7244 if (i != numRemoved) { 7245 Slog.w(TAG, "Rebuild removed " + numRemoved 7246 + " windows but added " + i); 7247 for (i=0; i<numRemoved; i++) { 7248 WindowState ws = mRebuildTmp[i]; 7249 if (ws.mRebuilding) { 7250 StringWriter sw = new StringWriter(); 7251 PrintWriter pw = new PrintWriter(sw); 7252 ws.dump(pw, "", true); 7253 pw.flush(); 7254 Slog.w(TAG, "This window was lost: " + ws); 7255 Slog.w(TAG, sw.toString()); 7256 } 7257 } 7258 Slog.w(TAG, "Current app token list:"); 7259 dumpAppTokensLocked(); 7260 Slog.w(TAG, "Final window list:"); 7261 dumpWindowsLocked(); 7262 } 7263 } 7264 7265 private final void assignLayersLocked() { 7266 int N = mWindows.size(); 7267 int curBaseLayer = 0; 7268 int curLayer = 0; 7269 int i; 7270 7271 if (DEBUG_LAYERS) { 7272 RuntimeException here = new RuntimeException("here"); 7273 here.fillInStackTrace(); 7274 Slog.v(TAG, "Assigning layers", here); 7275 } 7276 7277 for (i=0; i<N; i++) { 7278 WindowState w = mWindows.get(i); 7279 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 7280 || (i > 0 && w.mIsWallpaper)) { 7281 curLayer += WINDOW_LAYER_MULTIPLIER; 7282 w.mLayer = curLayer; 7283 } else { 7284 curBaseLayer = curLayer = w.mBaseLayer; 7285 w.mLayer = curLayer; 7286 } 7287 if (w.mTargetAppToken != null) { 7288 w.mWinAnimator.mAnimLayer = 7289 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 7290 } else if (w.mAppToken != null) { 7291 w.mWinAnimator.mAnimLayer = 7292 w.mLayer + w.mAppToken.mAppAnimator.animLayerAdjustment; 7293 } else { 7294 w.mWinAnimator.mAnimLayer = w.mLayer; 7295 } 7296 if (w.mIsImWindow) { 7297 w.mWinAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 7298 } else if (w.mIsWallpaper) { 7299 w.mWinAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 7300 } 7301 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 7302 + w.mWinAnimator.mAnimLayer); 7303 //System.out.println( 7304 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 7305 } 7306 } 7307 7308 private boolean mInLayout = false; 7309 private final void performLayoutAndPlaceSurfacesLocked() { 7310 if (mInLayout) { 7311 if (DEBUG) { 7312 throw new RuntimeException("Recursive call!"); 7313 } 7314 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout"); 7315 return; 7316 } 7317 7318 if (mWaitingForConfig) { 7319 // Our configuration has changed (most likely rotation), but we 7320 // don't yet have the complete configuration to report to 7321 // applications. Don't do any window layout until we have it. 7322 return; 7323 } 7324 7325 if (mDisplay == null) { 7326 // Not yet initialized, nothing to do. 7327 return; 7328 } 7329 7330 mInLayout = true; 7331 boolean recoveringMemory = false; 7332 7333 try { 7334 if (mForceRemoves != null) { 7335 recoveringMemory = true; 7336 // Wait a little bit for things to settle down, and off we go. 7337 for (int i=0; i<mForceRemoves.size(); i++) { 7338 WindowState ws = mForceRemoves.get(i); 7339 Slog.i(TAG, "Force removing: " + ws); 7340 removeWindowInnerLocked(ws.mSession, ws); 7341 } 7342 mForceRemoves = null; 7343 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 7344 Object tmp = new Object(); 7345 synchronized (tmp) { 7346 try { 7347 tmp.wait(250); 7348 } catch (InterruptedException e) { 7349 } 7350 } 7351 } 7352 } catch (RuntimeException e) { 7353 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 7354 } 7355 7356 try { 7357 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 7358 7359 final int N = mPendingRemove.size(); 7360 if (N > 0) { 7361 if (mPendingRemoveTmp.length < N) { 7362 mPendingRemoveTmp = new WindowState[N+10]; 7363 } 7364 mPendingRemove.toArray(mPendingRemoveTmp); 7365 mPendingRemove.clear(); 7366 for (int i=0; i<N; i++) { 7367 WindowState w = mPendingRemoveTmp[i]; 7368 removeWindowInnerLocked(w.mSession, w); 7369 } 7370 7371 mInLayout = false; 7372 assignLayersLocked(); 7373 mLayoutNeeded = true; 7374 performLayoutAndPlaceSurfacesLocked(); 7375 7376 } else { 7377 mInLayout = false; 7378 } 7379 7380 if (mLayoutNeeded) { 7381 if (++mLayoutRepeatCount < 6) { 7382 requestTraversalLocked(); 7383 } else { 7384 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 7385 mLayoutRepeatCount = 0; 7386 } 7387 } else { 7388 mLayoutRepeatCount = 0; 7389 } 7390 7391 if (mAnimator.mAnimating) { 7392 // Do this even if requestTraversalLocked was called above so we get a frame drawn 7393 // at the proper time as well as the one drawn early. 7394 scheduleAnimationLocked(); 7395 } 7396 7397 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 7398 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 7399 mH.sendMessage(mH.obtainMessage(H.REPORT_WINDOWS_CHANGE)); 7400 } 7401 } catch (RuntimeException e) { 7402 mInLayout = false; 7403 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 7404 } 7405 } 7406 7407 private final void performLayoutLockedInner(boolean initial, boolean updateInputWindows) { 7408 if (!mLayoutNeeded) { 7409 return; 7410 } 7411 7412 mLayoutNeeded = false; 7413 7414 final int dw = mCurDisplayWidth; 7415 final int dh = mCurDisplayHeight; 7416 7417 final int NFW = mFakeWindows.size(); 7418 for (int i=0; i<NFW; i++) { 7419 mFakeWindows.get(i).layout(dw, dh); 7420 } 7421 7422 final int N = mWindows.size(); 7423 int i; 7424 7425 if (DEBUG_LAYOUT) { 7426 Slog.v(TAG, "-------------------------------------"); 7427 Slog.v(TAG, "performLayout: needed=" 7428 + mLayoutNeeded + " dw=" + dw + " dh=" + dh); 7429 } 7430 7431 mPolicy.beginLayoutLw(dw, dh, mRotation); 7432 7433 int seq = mLayoutSeq+1; 7434 if (seq < 0) seq = 0; 7435 mLayoutSeq = seq; 7436 7437 // First perform layout of any root windows (not attached 7438 // to another window). 7439 int topAttached = -1; 7440 for (i = N-1; i >= 0; i--) { 7441 final WindowState win = mWindows.get(i); 7442 7443 // Don't do layout of a window if it is not visible, or 7444 // soon won't be visible, to avoid wasting time and funky 7445 // changes while a window is animating away. 7446 final boolean gone = win.isGoneForLayoutLw(); 7447 7448 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 7449 Slog.v(TAG, "1ST PASS " + win 7450 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 7451 + " mLayoutAttached=" + win.mLayoutAttached); 7452 final AppWindowToken atoken = win.mAppToken; 7453 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 7454 + win.mViewVisibility + " mRelayoutCalled=" 7455 + win.mRelayoutCalled + " hidden=" 7456 + win.mRootToken.hidden + " hiddenRequested=" 7457 + (atoken != null && atoken.hiddenRequested) 7458 + " mAttachedHidden=" + win.mAttachedHidden); 7459 else Slog.v(TAG, " VIS: mViewVisibility=" 7460 + win.mViewVisibility + " mRelayoutCalled=" 7461 + win.mRelayoutCalled + " hidden=" 7462 + win.mRootToken.hidden + " hiddenRequested=" 7463 + (atoken != null && atoken.hiddenRequested) 7464 + " mAttachedHidden=" + win.mAttachedHidden); 7465 } 7466 7467 // If this view is GONE, then skip it -- keep the current 7468 // frame, and let the caller know so they can ignore it 7469 // if they want. (We do the normal layout for INVISIBLE 7470 // windows, since that means "perform layout as normal, 7471 // just don't display"). 7472 if (!gone || !win.mHaveFrame || win.mLayoutNeeded) { 7473 if (!win.mLayoutAttached) { 7474 if (initial) { 7475 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 7476 win.mContentChanged = false; 7477 } 7478 win.mLayoutNeeded = false; 7479 win.prelayout(); 7480 mPolicy.layoutWindowLw(win, win.mAttrs, null); 7481 win.mLayoutSeq = seq; 7482 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 7483 + win.mFrame + " mContainingFrame=" 7484 + win.mContainingFrame + " mDisplayFrame=" 7485 + win.mDisplayFrame); 7486 } else { 7487 if (topAttached < 0) topAttached = i; 7488 } 7489 } 7490 } 7491 7492 // Now perform layout of attached windows, which usually 7493 // depend on the position of the window they are attached to. 7494 // XXX does not deal with windows that are attached to windows 7495 // that are themselves attached. 7496 for (i = topAttached; i >= 0; i--) { 7497 final WindowState win = mWindows.get(i); 7498 7499 if (win.mLayoutAttached) { 7500 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 7501 + " mHaveFrame=" + win.mHaveFrame 7502 + " mViewVisibility=" + win.mViewVisibility 7503 + " mRelayoutCalled=" + win.mRelayoutCalled); 7504 // If this view is GONE, then skip it -- keep the current 7505 // frame, and let the caller know so they can ignore it 7506 // if they want. (We do the normal layout for INVISIBLE 7507 // windows, since that means "perform layout as normal, 7508 // just don't display"). 7509 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 7510 || !win.mHaveFrame || win.mLayoutNeeded) { 7511 if (initial) { 7512 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 7513 win.mContentChanged = false; 7514 } 7515 win.mLayoutNeeded = false; 7516 win.prelayout(); 7517 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 7518 win.mLayoutSeq = seq; 7519 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 7520 + win.mFrame + " mContainingFrame=" 7521 + win.mContainingFrame + " mDisplayFrame=" 7522 + win.mDisplayFrame); 7523 } 7524 } 7525 } 7526 7527 // Window frames may have changed. Tell the input dispatcher about it. 7528 mInputMonitor.setUpdateInputWindowsNeededLw(); 7529 if (updateInputWindows) { 7530 mInputMonitor.updateInputWindowsLw(false /*force*/); 7531 } 7532 7533 mPolicy.finishLayoutLw(); 7534 } 7535 7536 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 7537 // If the screen is currently frozen or off, then keep 7538 // it frozen/off until this window draws at its new 7539 // orientation. 7540 if (!okToDisplay()) { 7541 if (DEBUG_ORIENTATION) Slog.v(TAG, 7542 "Changing surface while display frozen: " + w); 7543 w.mOrientationChanging = true; 7544 if (!mWindowsFreezingScreen) { 7545 mWindowsFreezingScreen = true; 7546 // XXX should probably keep timeout from 7547 // when we first froze the display. 7548 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 7549 mH.sendMessageDelayed(mH.obtainMessage( 7550 H.WINDOW_FREEZE_TIMEOUT), 2000); 7551 } 7552 } 7553 } 7554 7555 /** 7556 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 7557 * 7558 * @return bitmap indicating if another pass through layout must be made. 7559 */ 7560 public int handleAppTransitionReadyLocked() { 7561 int changes = 0; 7562 int i; 7563 int NN = mOpeningApps.size(); 7564 boolean goodToGo = true; 7565 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7566 "Checking " + NN + " opening apps (frozen=" 7567 + mDisplayFrozen + " timeout=" 7568 + mAppTransitionTimeout + ")..."); 7569 if (!mDisplayFrozen && !mAppTransitionTimeout) { 7570 // If the display isn't frozen, wait to do anything until 7571 // all of the apps are ready. Otherwise just go because 7572 // we'll unfreeze the display when everyone is ready. 7573 for (i=0; i<NN && goodToGo; i++) { 7574 AppWindowToken wtoken = mOpeningApps.get(i); 7575 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7576 "Check opening app" + wtoken + ": allDrawn=" 7577 + wtoken.allDrawn + " startingDisplayed=" 7578 + wtoken.startingDisplayed); 7579 if (!wtoken.allDrawn && !wtoken.startingDisplayed 7580 && !wtoken.startingMoved) { 7581 goodToGo = false; 7582 } 7583 } 7584 } 7585 if (goodToGo) { 7586 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 7587 int transit = mNextAppTransition; 7588 if (mSkipAppTransitionAnimation) { 7589 transit = WindowManagerPolicy.TRANSIT_UNSET; 7590 } 7591 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 7592 mAppTransitionReady = false; 7593 mAppTransitionRunning = true; 7594 mAppTransitionTimeout = false; 7595 mStartingIconInTransition = false; 7596 mSkipAppTransitionAnimation = false; 7597 7598 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 7599 7600 // If there are applications waiting to come to the 7601 // top of the stack, now is the time to move their windows. 7602 // (Note that we don't do apps going to the bottom 7603 // here -- we want to keep their windows in the old 7604 // Z-order until the animation completes.) 7605 if (mToTopApps.size() > 0) { 7606 NN = mAppTokens.size(); 7607 for (i=0; i<NN; i++) { 7608 AppWindowToken wtoken = mAppTokens.get(i); 7609 if (wtoken.sendingToTop) { 7610 wtoken.sendingToTop = false; 7611 moveAppWindowsLocked(wtoken, NN, false); 7612 } 7613 } 7614 mToTopApps.clear(); 7615 } 7616 7617 WindowState oldWallpaper = mWallpaperTarget; 7618 7619 adjustWallpaperWindowsLocked(); 7620 mInnerFields.mWallpaperMayChange = false; 7621 7622 // The top-most window will supply the layout params, 7623 // and we will determine it below. 7624 LayoutParams animLp = null; 7625 int bestAnimLayer = -1; 7626 boolean fullscreenAnim = false; 7627 7628 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7629 "New wallpaper target=" + mWallpaperTarget 7630 + ", lower target=" + mLowerWallpaperTarget 7631 + ", upper target=" + mUpperWallpaperTarget); 7632 int foundWallpapers = 0; 7633 // Do a first pass through the tokens for two 7634 // things: 7635 // (1) Determine if both the closing and opening 7636 // app token sets are wallpaper targets, in which 7637 // case special animations are needed 7638 // (since the wallpaper needs to stay static 7639 // behind them). 7640 // (2) Find the layout params of the top-most 7641 // application window in the tokens, which is 7642 // what will control the animation theme. 7643 final int NC = mClosingApps.size(); 7644 NN = NC + mOpeningApps.size(); 7645 for (i=0; i<NN; i++) { 7646 AppWindowToken wtoken; 7647 int mode; 7648 if (i < NC) { 7649 wtoken = mClosingApps.get(i); 7650 mode = 1; 7651 } else { 7652 wtoken = mOpeningApps.get(i-NC); 7653 mode = 2; 7654 } 7655 if (mLowerWallpaperTarget != null) { 7656 if (mLowerWallpaperTarget.mAppToken == wtoken 7657 || mUpperWallpaperTarget.mAppToken == wtoken) { 7658 foundWallpapers |= mode; 7659 } 7660 } 7661 if (wtoken.appFullscreen) { 7662 WindowState ws = wtoken.findMainWindow(); 7663 if (ws != null) { 7664 animLp = ws.mAttrs; 7665 bestAnimLayer = ws.mLayer; 7666 fullscreenAnim = true; 7667 } 7668 } else if (!fullscreenAnim) { 7669 WindowState ws = wtoken.findMainWindow(); 7670 if (ws != null) { 7671 if (ws.mLayer > bestAnimLayer) { 7672 animLp = ws.mAttrs; 7673 bestAnimLayer = ws.mLayer; 7674 } 7675 } 7676 } 7677 } 7678 7679 if (foundWallpapers == 3) { 7680 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7681 "Wallpaper animation!"); 7682 switch (transit) { 7683 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: 7684 case WindowManagerPolicy.TRANSIT_TASK_OPEN: 7685 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: 7686 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN; 7687 break; 7688 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: 7689 case WindowManagerPolicy.TRANSIT_TASK_CLOSE: 7690 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: 7691 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE; 7692 break; 7693 } 7694 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7695 "New transit: " + transit); 7696 } else if (oldWallpaper != null) { 7697 // We are transitioning from an activity with 7698 // a wallpaper to one without. 7699 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE; 7700 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7701 "New transit away from wallpaper: " + transit); 7702 } else if (mWallpaperTarget != null) { 7703 // We are transitioning from an activity without 7704 // a wallpaper to now showing the wallpaper 7705 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN; 7706 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7707 "New transit into wallpaper: " + transit); 7708 } 7709 7710 // If all closing windows are obscured, then there is 7711 // no need to do an animation. This is the case, for 7712 // example, when this transition is being done behind 7713 // the lock screen. 7714 if (!mPolicy.allowAppAnimationsLw()) { 7715 animLp = null; 7716 } 7717 7718 AppWindowToken topOpeningApp = null; 7719 int topOpeningLayer = 0; 7720 7721 // TODO(cmautner): Move to animation side. 7722 NN = mOpeningApps.size(); 7723 for (i=0; i<NN; i++) { 7724 AppWindowToken wtoken = mOpeningApps.get(i); 7725 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 7726 wtoken.mAppAnimator.clearThumbnail(); 7727 wtoken.reportedVisible = false; 7728 wtoken.inPendingTransaction = false; 7729 wtoken.mAppAnimator.animation = null; 7730 setTokenVisibilityLocked(wtoken, animLp, true, transit, false); 7731 wtoken.updateReportedVisibilityLocked(); 7732 wtoken.waitingToShow = false; 7733 mAnimator.mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked(); 7734 if (animLp != null) { 7735 int layer = -1; 7736 for (int j=0; j<wtoken.windows.size(); j++) { 7737 WindowState win = wtoken.windows.get(j); 7738 if (win.mWinAnimator.mAnimLayer > layer) { 7739 layer = win.mWinAnimator.mAnimLayer; 7740 } 7741 } 7742 if (topOpeningApp == null || layer > topOpeningLayer) { 7743 topOpeningApp = wtoken; 7744 topOpeningLayer = layer; 7745 } 7746 } 7747 } 7748 NN = mClosingApps.size(); 7749 for (i=0; i<NN; i++) { 7750 AppWindowToken wtoken = mClosingApps.get(i); 7751 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7752 "Now closing app" + wtoken); 7753 wtoken.mAppAnimator.clearThumbnail(); 7754 wtoken.inPendingTransaction = false; 7755 wtoken.mAppAnimator.animation = null; 7756 setTokenVisibilityLocked(wtoken, animLp, false, 7757 transit, false); 7758 wtoken.updateReportedVisibilityLocked(); 7759 wtoken.waitingToHide = false; 7760 // Force the allDrawn flag, because we want to start 7761 // this guy's animations regardless of whether it's 7762 // gotten drawn. 7763 wtoken.allDrawn = true; 7764 } 7765 7766 if (mNextAppTransitionThumbnail != null && topOpeningApp != null 7767 && topOpeningApp.mAppAnimator.animation != null) { 7768 // This thumbnail animation is very special, we need to have 7769 // an extra surface with the thumbnail included with the animation. 7770 Rect dirty = new Rect(0, 0, mNextAppTransitionThumbnail.getWidth(), 7771 mNextAppTransitionThumbnail.getHeight()); 7772 try { 7773 Surface surface = new Surface(mFxSession, Process.myPid(), 7774 "thumbnail anim", 0, dirty.width(), dirty.height(), 7775 PixelFormat.TRANSLUCENT, Surface.HIDDEN); 7776 topOpeningApp.mAppAnimator.thumbnail = surface; 7777 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " 7778 + surface + ": CREATE"); 7779 Surface drawSurface = new Surface(); 7780 drawSurface.copyFrom(surface); 7781 Canvas c = drawSurface.lockCanvas(dirty); 7782 c.drawBitmap(mNextAppTransitionThumbnail, 0, 0, null); 7783 drawSurface.unlockCanvasAndPost(c); 7784 drawSurface.release(); 7785 topOpeningApp.mAppAnimator.thumbnailLayer = topOpeningLayer; 7786 Animation anim = createThumbnailAnimationLocked(transit, true, true); 7787 topOpeningApp.mAppAnimator.thumbnailAnimation = anim; 7788 anim.restrictDuration(MAX_ANIMATION_DURATION); 7789 anim.scaleCurrentDuration(mTransitionAnimationScale); 7790 topOpeningApp.mAppAnimator.thumbnailX = mNextAppTransitionStartX; 7791 topOpeningApp.mAppAnimator.thumbnailY = mNextAppTransitionStartY; 7792 } catch (Surface.OutOfResourcesException e) { 7793 Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width() 7794 + " h=" + dirty.height(), e); 7795 topOpeningApp.mAppAnimator.clearThumbnail(); 7796 } 7797 } 7798 7799 mNextAppTransitionPackage = null; 7800 mNextAppTransitionThumbnail = null; 7801 if (mNextAppTransitionCallback != null) { 7802 try { 7803 mNextAppTransitionCallback.sendResult(null); 7804 } catch (RemoteException e) { 7805 } 7806 } 7807 7808 mOpeningApps.clear(); 7809 mClosingApps.clear(); 7810 7811 // This has changed the visibility of windows, so perform 7812 // a new layout to get them all up-to-date. 7813 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT 7814 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 7815 mLayoutNeeded = true; 7816 if (!moveInputMethodWindowsIfNeededLocked(true)) { 7817 assignLayersLocked(); 7818 } 7819 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 7820 false /*updateInputWindows*/); 7821 mFocusMayChange = false; 7822 } 7823 7824 return changes; 7825 } 7826 7827 /** 7828 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 7829 * 7830 * @return bitmap indicating if another pass through layout must be made. 7831 */ 7832 private int handleAnimatingStoppedAndTransitionLocked() { 7833 int changes = 0; 7834 7835 mAppTransitionRunning = false; 7836 // Clear information about apps that were moving. 7837 mToBottomApps.clear(); 7838 7839 rebuildAppWindowListLocked(); 7840 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 7841 mInnerFields.mAdjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED; 7842 moveInputMethodWindowsIfNeededLocked(false); 7843 mInnerFields.mWallpaperMayChange = true; 7844 // Since the window list has been rebuilt, focus might 7845 // have to be recomputed since the actual order of windows 7846 // might have changed again. 7847 mFocusMayChange = true; 7848 7849 return changes; 7850 } 7851 7852 /** 7853 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 7854 * 7855 * @return bitmap indicating if another pass through layout must be made. 7856 */ 7857 private int animateAwayWallpaperLocked() { 7858 int changes = 0; 7859 WindowState oldWallpaper = mWallpaperTarget; 7860 if (mLowerWallpaperTarget != null 7861 && mLowerWallpaperTarget.mAppToken != null) { 7862 if (DEBUG_WALLPAPER) Slog.v(TAG, 7863 "wallpaperForceHiding changed with lower=" 7864 + mLowerWallpaperTarget); 7865 if (DEBUG_WALLPAPER) Slog.v(TAG, 7866 "hidden=" + mLowerWallpaperTarget.mAppToken.hidden + 7867 " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested); 7868 if (mLowerWallpaperTarget.mAppToken.hidden) { 7869 // The lower target has become hidden before we 7870 // actually started the animation... let's completely 7871 // re-evaluate everything. 7872 mLowerWallpaperTarget = mUpperWallpaperTarget = null; 7873 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 7874 } 7875 } 7876 mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked(); 7877 if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper 7878 + " NEW: " + mWallpaperTarget 7879 + " LOWER: " + mLowerWallpaperTarget); 7880 if (mLowerWallpaperTarget == null) { 7881 // Whoops, we don't need a special wallpaper animation. 7882 // Clear them out. 7883 mAnimator.mForceHiding = false; 7884 for (int i=mWindows.size()-1; i>=0; i--) { 7885 WindowState w = mWindows.get(i); 7886 if (w.mHasSurface) { 7887 final WindowManager.LayoutParams attrs = w.mAttrs; 7888 if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) { 7889 if (DEBUG_FOCUS) Slog.i(TAG, "win=" + w + " force hides other windows"); 7890 mAnimator.mForceHiding = true; 7891 } else if (mPolicy.canBeForceHidden(w, attrs)) { 7892 if (!w.mWinAnimator.mAnimating) { 7893 // We set the animation above so it 7894 // is not yet running. 7895 // TODO(cmautner): We lose the enter animation when this occurs. 7896 w.mWinAnimator.clearAnimation(); 7897 } 7898 } 7899 } 7900 } 7901 } 7902 return changes; 7903 } 7904 7905 private void updateResizingWindows(final WindowState w) { 7906 final WindowStateAnimator winAnimator = w.mWinAnimator; 7907 if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) { 7908 w.mContentInsetsChanged |= 7909 !w.mLastContentInsets.equals(w.mContentInsets); 7910 w.mVisibleInsetsChanged |= 7911 !w.mLastVisibleInsets.equals(w.mVisibleInsets); 7912 boolean configChanged = 7913 w.mConfiguration != mCurConfiguration 7914 && (w.mConfiguration == null 7915 || mCurConfiguration.diff(w.mConfiguration) != 0); 7916 if (DEBUG_CONFIGURATION && configChanged) { 7917 Slog.v(TAG, "Win " + w + " config changed: " 7918 + mCurConfiguration); 7919 } 7920 if (localLOGV) Slog.v(TAG, "Resizing " + w 7921 + ": configChanged=" + configChanged 7922 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 7923 w.mLastFrame.set(w.mFrame); 7924 if (w.mContentInsetsChanged 7925 || w.mVisibleInsetsChanged 7926 || winAnimator.mSurfaceResized 7927 || configChanged) { 7928 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 7929 Slog.v(TAG, "Resize reasons: " 7930 + " contentInsetsChanged=" + w.mContentInsetsChanged 7931 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 7932 + " surfaceResized=" + w.mWinAnimator.mSurfaceResized 7933 + " configChanged=" + configChanged); 7934 } 7935 7936 w.mLastContentInsets.set(w.mContentInsets); 7937 w.mLastVisibleInsets.set(w.mVisibleInsets); 7938 makeWindowFreezingScreenIfNeededLocked(w); 7939 // If the orientation is changing, then we need to 7940 // hold off on unfreezing the display until this 7941 // window has been redrawn; to do that, we need 7942 // to go through the process of getting informed 7943 // by the application when it has finished drawing. 7944 if (w.mOrientationChanging) { 7945 if (DEBUG_ORIENTATION) Slog.v(TAG, 7946 "Orientation start waiting for draw in " 7947 + w + ", surface " + w.mWinAnimator.mSurface); 7948 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 7949 if (w.mAppToken != null) { 7950 w.mAppToken.allDrawn = false; 7951 } 7952 } 7953 if (!mResizingWindows.contains(w)) { 7954 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 7955 "Resizing window " + w + " to " + w.mWinAnimator.mSurfaceW 7956 + "x" + w.mWinAnimator.mSurfaceH); 7957 mResizingWindows.add(w); 7958 } 7959 } else if (w.mOrientationChanging) { 7960 if (w.isDrawnLw()) { 7961 if (DEBUG_ORIENTATION) Slog.v(TAG, 7962 "Orientation not waiting for draw in " 7963 + w + ", surface " + w.mWinAnimator.mSurface); 7964 w.mOrientationChanging = false; 7965 } 7966 } 7967 } 7968 } 7969 7970 /** 7971 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 7972 * 7973 * @param w WindowState this method is applied to. 7974 * @param currentTime The time which animations use for calculating transitions. 7975 * @param innerDw Width of app window. 7976 * @param innerDh Height of app window. 7977 */ 7978 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 7979 final int innerDw, final int innerDh) { 7980 final WindowManager.LayoutParams attrs = w.mAttrs; 7981 final int attrFlags = attrs.flags; 7982 final boolean canBeSeen = w.isDisplayedLw(); 7983 7984 if (w.mHasSurface) { 7985 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 7986 mInnerFields.mHoldScreen = w.mSession; 7987 } 7988 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 7989 && mInnerFields.mScreenBrightness < 0) { 7990 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 7991 } 7992 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 7993 && mInnerFields.mButtonBrightness < 0) { 7994 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 7995 } 7996 if (canBeSeen 7997 && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG 7998 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD 7999 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) { 8000 mInnerFields.mSyswin = true; 8001 } 8002 } 8003 8004 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8005 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8006 // This window completely covers everything behind it, 8007 // so we want to leave all of them as undimmed (for 8008 // performance reasons). 8009 mInnerFields.mObscured = true; 8010 } else if (canBeSeen && (attrFlags & FLAG_DIM_BEHIND) != 0) { 8011 if (localLOGV) Slog.v(TAG, "Win " + w + " obscured=" + mInnerFields.mObscured); 8012 if (!mInnerFields.mDimming) { 8013 //Slog.i(TAG, "DIM BEHIND: " + w); 8014 mInnerFields.mDimming = true; 8015 final int width, height; 8016 if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) { 8017 width = mCurDisplayWidth; 8018 height = mCurDisplayHeight; 8019 } else { 8020 width = innerDw; 8021 height = innerDh; 8022 } 8023 mAnimator.startDimming(w.mWinAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, 8024 width, height); 8025 } 8026 } 8027 } 8028 8029 // "Something has changed! Let's make it correct now." 8030 private final void performLayoutAndPlaceSurfacesLockedInner( 8031 boolean recoveringMemory) { 8032 if (mDisplay == null) { 8033 Slog.i(TAG, "skipping performLayoutAndPlaceSurfacesLockedInner with no mDisplay"); 8034 return; 8035 } 8036 8037 final long currentTime = SystemClock.uptimeMillis(); 8038 final int dw = mCurDisplayWidth; 8039 final int dh = mCurDisplayHeight; 8040 final int innerDw = mAppDisplayWidth; 8041 final int innerDh = mAppDisplayHeight; 8042 8043 int i; 8044 8045 if (mFocusMayChange) { 8046 mFocusMayChange = false; 8047 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 8048 false /*updateInputWindows*/); 8049 } 8050 8051 // Initialize state of exiting tokens. 8052 for (i=mExitingTokens.size()-1; i>=0; i--) { 8053 mExitingTokens.get(i).hasVisible = false; 8054 } 8055 8056 // Initialize state of exiting applications. 8057 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 8058 mExitingAppTokens.get(i).hasVisible = false; 8059 } 8060 8061 mInnerFields.mHoldScreen = null; 8062 mInnerFields.mScreenBrightness = -1; 8063 mInnerFields.mButtonBrightness = -1; 8064 boolean focusDisplayed = false; 8065 mAnimator.mAnimating = false; 8066 boolean createWatermark = false; 8067 8068 if (mFxSession == null) { 8069 mFxSession = new SurfaceSession(); 8070 createWatermark = true; 8071 } 8072 8073 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 8074 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 8075 8076 Surface.openTransaction(); 8077 8078 if (createWatermark) { 8079 createWatermark(); 8080 } 8081 if (mWatermark != null) { 8082 mWatermark.positionSurface(dw, dh); 8083 } 8084 if (mStrictModeFlash != null) { 8085 mStrictModeFlash.positionSurface(dw, dh); 8086 } 8087 8088 try { 8089 int repeats = 0; 8090 8091 do { 8092 repeats++; 8093 if (repeats > 6) { 8094 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 8095 mLayoutNeeded = false; 8096 break; 8097 } 8098 8099 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 8100 mPendingLayoutChanges); 8101 8102 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) { 8103 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 8104 assignLayersLocked(); 8105 mLayoutNeeded = true; 8106 } 8107 } 8108 8109 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 8110 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 8111 if (updateOrientationFromAppTokensLocked(true)) { 8112 mLayoutNeeded = true; 8113 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8114 } 8115 } 8116 8117 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 8118 mLayoutNeeded = true; 8119 } 8120 8121 // FIRST LOOP: Perform a layout, if needed. 8122 if (repeats < 4) { 8123 performLayoutLockedInner(repeats == 1, false /*updateInputWindows*/); 8124 } else { 8125 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 8126 } 8127 8128 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 8129 // it is animating. 8130 mPendingLayoutChanges = 0; 8131 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " + mLayoutRepeatCount, 8132 mPendingLayoutChanges); 8133 mPolicy.beginAnimationLw(dw, dh); 8134 for (i = mWindows.size() - 1; i >= 0; i--) { 8135 WindowState w = mWindows.get(i); 8136 if (w.mHasSurface) { 8137 mPolicy.animatingWindowLw(w, w.mAttrs); 8138 } 8139 } 8140 mPendingLayoutChanges |= mPolicy.finishAnimationLw(); 8141 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishAnimationLw", 8142 mPendingLayoutChanges); 8143 } while (mPendingLayoutChanges != 0); 8144 8145 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 8146 8147 mInnerFields.mObscured = false; 8148 mInnerFields.mDimming = false; 8149 mInnerFields.mSyswin = false; 8150 8151 final int N = mWindows.size(); 8152 for (i=N-1; i>=0; i--) { 8153 WindowState w = mWindows.get(i); 8154 8155 if (someoneLosingFocus && w == mCurrentFocus && w.isDisplayedLw()) { 8156 focusDisplayed = true; 8157 } 8158 8159 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 8160 8161 // Update effect. 8162 w.mObscured = mInnerFields.mObscured; 8163 if (!mInnerFields.mObscured) { 8164 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 8165 } 8166 8167 if (obscuredChanged && mWallpaperTarget == w) { 8168 // This is the wallpaper target and its obscured state 8169 // changed... make sure the current wallaper's visibility 8170 // has been updated accordingly. 8171 updateWallpaperVisibilityLocked(); 8172 } 8173 } 8174 if (!mInnerFields.mDimming && mAnimator.mDimParams != null) { 8175 mAnimator.stopDimming(); 8176 } 8177 } catch (RuntimeException e) { 8178 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 8179 } finally { 8180 Surface.closeTransaction(); 8181 } 8182 8183 // If we are ready to perform an app transition, check through 8184 // all of the app tokens to be shown and see if they are ready 8185 // to go. 8186 if (mAppTransitionReady) { 8187 mPendingLayoutChanges |= handleAppTransitionReadyLocked(); 8188 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 8189 mPendingLayoutChanges); 8190 } 8191 8192 mInnerFields.mAdjResult = 0; 8193 8194 if (!mAnimator.mAnimating && mAppTransitionRunning) { 8195 // We have finished the animation of an app transition. To do 8196 // this, we have delayed a lot of operations like showing and 8197 // hiding apps, moving apps in Z-order, etc. The app token list 8198 // reflects the correct Z-order, but the window list may now 8199 // be out of sync with it. So here we will just rebuild the 8200 // entire app window list. Fun! 8201 mPendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 8202 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 8203 mPendingLayoutChanges); 8204 } 8205 8206 if (mInnerFields.mWallpaperForceHidingChanged && mPendingLayoutChanges == 0 && 8207 !mAppTransitionReady) { 8208 // At this point, there was a window with a wallpaper that 8209 // was force hiding other windows behind it, but now it 8210 // is going away. This may be simple -- just animate 8211 // away the wallpaper and its window -- or it may be 8212 // hard -- the wallpaper now needs to be shown behind 8213 // something that was hidden. 8214 mPendingLayoutChanges |= animateAwayWallpaperLocked(); 8215 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 8216 mPendingLayoutChanges); 8217 } 8218 mInnerFields.mWallpaperForceHidingChanged = false; 8219 8220 if (mInnerFields.mWallpaperMayChange) { 8221 if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, 8222 "Wallpaper may change! Adjusting"); 8223 mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked(); 8224 } 8225 8226 if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 8227 if (DEBUG_WALLPAPER) Slog.v(TAG, 8228 "Wallpaper layer changed: assigning layers + relayout"); 8229 mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8230 assignLayersLocked(); 8231 } else if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) { 8232 if (DEBUG_WALLPAPER) Slog.v(TAG, 8233 "Wallpaper visibility changed: relayout"); 8234 mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8235 } 8236 8237 if (mFocusMayChange) { 8238 mFocusMayChange = false; 8239 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 8240 false /*updateInputWindows*/)) { 8241 mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 8242 mInnerFields.mAdjResult = 0; 8243 } 8244 } 8245 8246 if (mLayoutNeeded) { 8247 mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8248 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", mPendingLayoutChanges); 8249 } 8250 8251 final int N = mWindows.size(); 8252 for (i=N-1; i>=0; i--) { 8253 final WindowState w = mWindows.get(i); 8254 final WindowStateAnimator winAnimator = w.mWinAnimator; 8255 8256 // If the window has moved due to its containing 8257 // content frame changing, then we'd like to animate 8258 // it. 8259 if (w.mHasSurface && w.shouldAnimateMove()) { 8260 // Frame has moved, containing content frame 8261 // has also moved, and we're not currently animating... 8262 // let's do something. 8263 Animation a = AnimationUtils.loadAnimation(mContext, 8264 com.android.internal.R.anim.window_move_from_decor); 8265 winAnimator.setAnimation(a); 8266 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 8267 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 8268 } else { 8269 winAnimator.mAnimDw = innerDw; 8270 winAnimator.mAnimDh = innerDh; 8271 } 8272 8273 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 8274 w.mContentChanged = false; 8275 8276 // TODO(cmautner): Can this move up to the loop at the end of try/catch above? 8277 updateResizingWindows(w); 8278 8279 // Moved from updateWindowsAndWallpaperLocked(). 8280 if (w.mHasSurface) { 8281 // Take care of the window being ready to display. 8282 if (winAnimator.commitFinishDrawingLocked(currentTime)) { 8283 if ((w.mAttrs.flags 8284 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { 8285 if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, 8286 "First draw done in potential wallpaper target " + w); 8287 mInnerFields.mWallpaperMayChange = true; 8288 mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 8289 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 8290 debugLayoutRepeats("updateWindowsAndWallpaperLocked 1", 8291 mPendingLayoutChanges); 8292 } 8293 } 8294 } 8295 } 8296 } 8297 8298 // Update animations of all applications, including those 8299 // associated with exiting/removed apps 8300 mAnimator.animate(); 8301 mPendingLayoutChanges |= mAnimator.mPendingLayoutChanges; 8302 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animate()", mPendingLayoutChanges); 8303 8304 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 8305 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 8306 8307 if (mWatermark != null) { 8308 mWatermark.drawIfNeeded(); 8309 } 8310 8311 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 8312 "With display frozen, orientationChangeComplete=" 8313 + mInnerFields.mOrientationChangeComplete); 8314 if (mInnerFields.mOrientationChangeComplete) { 8315 if (mWindowsFreezingScreen) { 8316 mWindowsFreezingScreen = false; 8317 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8318 } 8319 stopFreezingDisplayLocked(); 8320 } 8321 8322 if (!mResizingWindows.isEmpty()) { 8323 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 8324 WindowState win = mResizingWindows.get(i); 8325 final WindowStateAnimator winAnimator = win.mWinAnimator; 8326 try { 8327 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8328 "Reporting new frame to " + win + ": " + win.mCompatFrame); 8329 int diff = 0; 8330 boolean configChanged = 8331 win.mConfiguration != mCurConfiguration 8332 && (win.mConfiguration == null 8333 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0); 8334 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) 8335 && configChanged) { 8336 Slog.i(TAG, "Sending new config to window " + win + ": " 8337 + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH 8338 + " / " + mCurConfiguration + " / 0x" 8339 + Integer.toHexString(diff)); 8340 } 8341 win.mConfiguration = mCurConfiguration; 8342 if (DEBUG_ORIENTATION && 8343 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i( 8344 TAG, "Resizing " + win + " WITH DRAW PENDING"); 8345 win.mClient.resized((int)winAnimator.mSurfaceW, 8346 (int)winAnimator.mSurfaceH, 8347 win.mLastContentInsets, win.mLastVisibleInsets, 8348 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING, 8349 configChanged ? win.mConfiguration : null); 8350 win.mContentInsetsChanged = false; 8351 win.mVisibleInsetsChanged = false; 8352 winAnimator.mSurfaceResized = false; 8353 } catch (RemoteException e) { 8354 win.mOrientationChanging = false; 8355 } 8356 } 8357 mResizingWindows.clear(); 8358 } 8359 8360 // Destroy the surface of any windows that are no longer visible. 8361 boolean wallpaperDestroyed = false; 8362 i = mDestroySurface.size(); 8363 if (i > 0) { 8364 do { 8365 i--; 8366 WindowState win = mDestroySurface.get(i); 8367 win.mDestroying = false; 8368 if (mInputMethodWindow == win) { 8369 mInputMethodWindow = null; 8370 } 8371 if (win == mWallpaperTarget) { 8372 wallpaperDestroyed = true; 8373 } 8374 win.mWinAnimator.destroySurfaceLocked(); 8375 } while (i > 0); 8376 mDestroySurface.clear(); 8377 } 8378 8379 // Time to remove any exiting tokens? 8380 for (i=mExitingTokens.size()-1; i>=0; i--) { 8381 WindowToken token = mExitingTokens.get(i); 8382 if (!token.hasVisible) { 8383 mExitingTokens.remove(i); 8384 if (token.windowType == TYPE_WALLPAPER) { 8385 mWallpaperTokens.remove(token); 8386 } 8387 } 8388 } 8389 8390 // Time to remove any exiting applications? 8391 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 8392 AppWindowToken token = mExitingAppTokens.get(i); 8393 if (!token.hasVisible && !mClosingApps.contains(token)) { 8394 // Make sure there is no animation running on this token, 8395 // so any windows associated with it will be removed as 8396 // soon as their animations are complete 8397 token.mAppAnimator.clearAnimation(); 8398 token.mAppAnimator.animating = false; 8399 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 8400 "performLayout: App token exiting now removed" + token); 8401 mAppTokens.remove(token); 8402 mExitingAppTokens.remove(i); 8403 } 8404 } 8405 8406 if (!mAnimator.mAnimating && mAppTransitionRunning) { 8407 // We have finished the animation of an app transition. To do 8408 // this, we have delayed a lot of operations like showing and 8409 // hiding apps, moving apps in Z-order, etc. The app token list 8410 // reflects the correct Z-order, but the window list may now 8411 // be out of sync with it. So here we will just rebuild the 8412 // entire app window list. Fun! 8413 mAppTransitionRunning = false; 8414 mLayoutNeeded = true; 8415 rebuildAppWindowListLocked(); 8416 assignLayersLocked(); 8417 // Clear information about apps that were moving. 8418 mToBottomApps.clear(); 8419 } 8420 8421 if (focusDisplayed) { 8422 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 8423 } 8424 if (wallpaperDestroyed) { 8425 mLayoutNeeded |= adjustWallpaperWindowsLocked() != 0; 8426 } 8427 if (mPendingLayoutChanges != 0) { 8428 mLayoutNeeded = true; 8429 } 8430 8431 // Finally update all input windows now that the window changes have stabilized. 8432 mInputMonitor.updateInputWindowsLw(true /*force*/); 8433 8434 setHoldScreenLocked(mInnerFields.mHoldScreen != null); 8435 if (!mDisplayFrozen) { 8436 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 8437 mPowerManager.setScreenBrightnessOverride(-1); 8438 } else { 8439 mPowerManager.setScreenBrightnessOverride((int) 8440 (mInnerFields.mScreenBrightness * Power.BRIGHTNESS_ON)); 8441 } 8442 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 8443 mPowerManager.setButtonBrightnessOverride(-1); 8444 } else { 8445 mPowerManager.setButtonBrightnessOverride((int) 8446 (mInnerFields.mButtonBrightness * Power.BRIGHTNESS_ON)); 8447 } 8448 } 8449 if (mInnerFields.mHoldScreen != mHoldingScreenOn) { 8450 mHoldingScreenOn = mInnerFields.mHoldScreen; 8451 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, mInnerFields.mHoldScreen); 8452 mH.sendMessage(m); 8453 } 8454 8455 if (mTurnOnScreen) { 8456 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 8457 mPowerManager.userActivity(SystemClock.uptimeMillis(), false, 8458 LocalPowerManager.BUTTON_EVENT, true); 8459 mTurnOnScreen = false; 8460 } 8461 8462 if (mInnerFields.mUpdateRotation) { 8463 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 8464 if (updateRotationUncheckedLocked(false)) { 8465 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8466 } else { 8467 mInnerFields.mUpdateRotation = false; 8468 } 8469 } 8470 8471 if (mInnerFields.mOrientationChangeComplete && !mLayoutNeeded && 8472 !mInnerFields.mUpdateRotation) { 8473 checkDrawnWindowsLocked(); 8474 } 8475 8476 // Check to see if we are now in a state where the screen should 8477 // be enabled, because the window obscured flags have changed. 8478 enableScreenIfNeededLocked(); 8479// Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: mPendingLayoutChanges=" 8480// + Integer.toHexString(mPendingLayoutChanges) + " mLayoutNeeded=" + mLayoutNeeded 8481// + " animating=" + mAnimator.mAnimating); 8482 } 8483 8484 void checkDrawnWindowsLocked() { 8485 if (mWaitingForDrawn.size() > 0) { 8486 for (int j=mWaitingForDrawn.size()-1; j>=0; j--) { 8487 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j); 8488 WindowState win = pair.first; 8489 //Slog.i(TAG, "Waiting for drawn " + win + ": removed=" 8490 // + win.mRemoved + " visible=" + win.isVisibleLw() 8491 // + " shown=" + win.mSurfaceShown); 8492 if (win.mRemoved || !win.isVisibleLw()) { 8493 // Window has been removed or made invisible; no draw 8494 // will now happen, so stop waiting. 8495 Slog.w(TAG, "Aborted waiting for drawn: " + pair.first); 8496 try { 8497 pair.second.sendResult(null); 8498 } catch (RemoteException e) { 8499 } 8500 mWaitingForDrawn.remove(pair); 8501 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 8502 } else if (win.mWinAnimator.mSurfaceShown) { 8503 // Window is now drawn (and shown). 8504 try { 8505 pair.second.sendResult(null); 8506 } catch (RemoteException e) { 8507 } 8508 mWaitingForDrawn.remove(pair); 8509 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 8510 } 8511 } 8512 } 8513 } 8514 8515 public void waitForWindowDrawn(IBinder token, IRemoteCallback callback) { 8516 synchronized (mWindowMap) { 8517 WindowState win = windowForClientLocked(null, token, true); 8518 if (win != null) { 8519 Pair<WindowState, IRemoteCallback> pair = 8520 new Pair<WindowState, IRemoteCallback>(win, callback); 8521 Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 8522 mH.sendMessageDelayed(m, 2000); 8523 mWaitingForDrawn.add(pair); 8524 checkDrawnWindowsLocked(); 8525 } 8526 } 8527 } 8528 8529 /** 8530 * Must be called with the main window manager lock held. 8531 */ 8532 void setHoldScreenLocked(boolean holding) { 8533 boolean state = mHoldingScreenWakeLock.isHeld(); 8534 if (holding != state) { 8535 if (holding) { 8536 mPolicy.screenOnStartedLw(); 8537 mHoldingScreenWakeLock.acquire(); 8538 } else { 8539 mPolicy.screenOnStoppedLw(); 8540 mHoldingScreenWakeLock.release(); 8541 } 8542 } 8543 } 8544 8545 void requestTraversalLocked() { 8546 if (!mTraversalScheduled) { 8547 mTraversalScheduled = true; 8548 mH.sendEmptyMessage(H.DO_TRAVERSAL); 8549 } 8550 } 8551 8552 void scheduleAnimationLocked() { 8553 if (!mAnimationScheduled) { 8554 mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationRunnable, null); 8555 mAnimationScheduled = true; 8556 } 8557 } 8558 8559 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 8560 boolean secure) { 8561 final Surface surface = winAnimator.mSurface; 8562 boolean leakedSurface = false; 8563 boolean killedApps = false; 8564 8565 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 8566 winAnimator.mSession.mPid, operation); 8567 8568 if (mForceRemoves == null) { 8569 mForceRemoves = new ArrayList<WindowState>(); 8570 } 8571 8572 long callingIdentity = Binder.clearCallingIdentity(); 8573 try { 8574 // There was some problem... first, do a sanity check of the 8575 // window list to make sure we haven't left any dangling surfaces 8576 // around. 8577 int N = mWindows.size(); 8578 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 8579 for (int i=0; i<N; i++) { 8580 WindowState ws = mWindows.get(i); 8581 WindowStateAnimator wsa = ws.mWinAnimator; 8582 if (wsa.mSurface != null) { 8583 if (!mSessions.contains(wsa.mSession)) { 8584 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 8585 + ws + " surface=" + wsa.mSurface 8586 + " token=" + ws.mToken 8587 + " pid=" + ws.mSession.mPid 8588 + " uid=" + ws.mSession.mUid); 8589 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 8590 wsa.mSurface.destroy(); 8591 wsa.mSurfaceShown = false; 8592 wsa.mSurface = null; 8593 ws.mHasSurface = false; 8594 mAnimator.mWinAnimators.remove(wsa); 8595 mForceRemoves.add(ws); 8596 i--; 8597 N--; 8598 leakedSurface = true; 8599 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 8600 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 8601 + ws + " surface=" + wsa.mSurface 8602 + " token=" + ws.mAppToken); 8603 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 8604 wsa.mSurface.destroy(); 8605 wsa.mSurfaceShown = false; 8606 wsa.mSurface = null; 8607 ws.mHasSurface = false; 8608 mAnimator.mWinAnimators.remove(wsa); 8609 leakedSurface = true; 8610 } 8611 } 8612 } 8613 8614 if (!leakedSurface) { 8615 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 8616 SparseIntArray pidCandidates = new SparseIntArray(); 8617 for (int i=0; i<N; i++) { 8618 WindowStateAnimator wsa = mWindows.get(i).mWinAnimator; 8619 if (wsa.mSurface != null) { 8620 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 8621 } 8622 } 8623 if (pidCandidates.size() > 0) { 8624 int[] pids = new int[pidCandidates.size()]; 8625 for (int i=0; i<pids.length; i++) { 8626 pids[i] = pidCandidates.keyAt(i); 8627 } 8628 try { 8629 if (mActivityManager.killPids(pids, "Free memory", secure)) { 8630 killedApps = true; 8631 } 8632 } catch (RemoteException e) { 8633 } 8634 } 8635 } 8636 8637 if (leakedSurface || killedApps) { 8638 // We managed to reclaim some memory, so get rid of the trouble 8639 // surface and ask the app to request another one. 8640 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 8641 if (surface != null) { 8642 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 8643 "RECOVER DESTROY", null); 8644 surface.destroy(); 8645 winAnimator.mSurfaceShown = false; 8646 winAnimator.mSurface = null; 8647 winAnimator.mWin.mHasSurface = false; 8648 mAnimator.mWinAnimators.remove(winAnimator); 8649 } 8650 8651 try { 8652 winAnimator.mWin.mClient.dispatchGetNewSurface(); 8653 } catch (RemoteException e) { 8654 } 8655 } 8656 } finally { 8657 Binder.restoreCallingIdentity(callingIdentity); 8658 } 8659 8660 return leakedSurface || killedApps; 8661 } 8662 8663 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 8664 WindowState newFocus = computeFocusedWindowLocked(); 8665 if (mCurrentFocus != newFocus) { 8666 // This check makes sure that we don't already have the focus 8667 // change message pending. 8668 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 8669 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 8670 if (localLOGV) Slog.v( 8671 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus); 8672 final WindowState oldFocus = mCurrentFocus; 8673 mCurrentFocus = newFocus; 8674 mAnimator.setCurrentFocus(newFocus); 8675 mLosingFocus.remove(newFocus); 8676 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 8677 8678 final WindowState imWindow = mInputMethodWindow; 8679 if (newFocus != imWindow && oldFocus != imWindow) { 8680 if (moveInputMethodWindowsIfNeededLocked( 8681 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS && 8682 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) { 8683 mLayoutNeeded = true; 8684 } 8685 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 8686 performLayoutLockedInner(true /*initial*/, updateInputWindows); 8687 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 8688 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 8689 // Client will do the layout, but we need to assign layers 8690 // for handleNewWindowLocked() below. 8691 assignLayersLocked(); 8692 } 8693 } 8694 8695 if ((focusChanged&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 8696 // The change in focus caused us to need to do a layout. Okay. 8697 mLayoutNeeded = true; 8698 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 8699 performLayoutLockedInner(true /*initial*/, updateInputWindows); 8700 } 8701 } 8702 8703 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 8704 // If we defer assigning layers, then the caller is responsible for 8705 // doing this part. 8706 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 8707 } 8708 return true; 8709 } 8710 return false; 8711 } 8712 8713 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 8714 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 8715 } 8716 8717 private WindowState computeFocusedWindowLocked() { 8718 WindowState result = null; 8719 WindowState win; 8720 8721 int nextAppIndex = mAppTokens.size()-1; 8722 WindowToken nextApp = nextAppIndex >= 0 8723 ? mAppTokens.get(nextAppIndex) : null; 8724 8725 for (int i = mWindows.size() - 1; i >= 0; i--) { 8726 win = mWindows.get(i); 8727 8728 if (localLOGV || DEBUG_FOCUS) Slog.v( 8729 TAG, "Looking for focus: " + i 8730 + " = " + win 8731 + ", flags=" + win.mAttrs.flags 8732 + ", canReceive=" + win.canReceiveKeys()); 8733 8734 AppWindowToken thisApp = win.mAppToken; 8735 8736 // If this window's application has been removed, just skip it. 8737 if (thisApp != null && thisApp.removed) { 8738 continue; 8739 } 8740 8741 // If there is a focused app, don't allow focus to go to any 8742 // windows below it. If this is an application window, step 8743 // through the app tokens until we find its app. 8744 if (thisApp != null && nextApp != null && thisApp != nextApp 8745 && win.mAttrs.type != TYPE_APPLICATION_STARTING) { 8746 int origAppIndex = nextAppIndex; 8747 while (nextAppIndex > 0) { 8748 if (nextApp == mFocusedApp) { 8749 // Whoops, we are below the focused app... no focus 8750 // for you! 8751 if (localLOGV || DEBUG_FOCUS) Slog.v( 8752 TAG, "Reached focused app: " + mFocusedApp); 8753 return null; 8754 } 8755 nextAppIndex--; 8756 nextApp = mAppTokens.get(nextAppIndex); 8757 if (nextApp == thisApp) { 8758 break; 8759 } 8760 } 8761 if (thisApp != nextApp) { 8762 // Uh oh, the app token doesn't exist! This shouldn't 8763 // happen, but if it does we can get totally hosed... 8764 // so restart at the original app. 8765 nextAppIndex = origAppIndex; 8766 nextApp = mAppTokens.get(nextAppIndex); 8767 } 8768 } 8769 8770 // Dispatch to this window if it is wants key events. 8771 if (win.canReceiveKeys()) { 8772 if (DEBUG_FOCUS) Slog.v( 8773 TAG, "Found focus @ " + i + " = " + win); 8774 result = win; 8775 break; 8776 } 8777 } 8778 8779 return result; 8780 } 8781 8782 private void startFreezingDisplayLocked(boolean inTransaction) { 8783 if (mDisplayFrozen) { 8784 return; 8785 } 8786 8787 if (mDisplay == null || !mPolicy.isScreenOnFully()) { 8788 // No need to freeze the screen before the system is ready or if 8789 // the screen is off. 8790 return; 8791 } 8792 8793 mScreenFrozenLock.acquire(); 8794 8795 mDisplayFrozen = true; 8796 8797 mInputMonitor.freezeInputDispatchingLw(); 8798 8799 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 8800 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 8801 mNextAppTransitionPackage = null; 8802 mNextAppTransitionThumbnail = null; 8803 mAppTransitionReady = true; 8804 } 8805 8806 if (PROFILE_ORIENTATION) { 8807 File file = new File("/data/system/frozen"); 8808 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 8809 } 8810 8811 if (CUSTOM_SCREEN_ROTATION) { 8812 if (mAnimator.mScreenRotationAnimation != null) { 8813 mAnimator.mScreenRotationAnimation.kill(); 8814 mAnimator.mScreenRotationAnimation = null; 8815 } 8816 8817 mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext, 8818 mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight, 8819 mDisplay.getRotation()); 8820 8821 if (!mAnimator.mScreenRotationAnimation.hasScreenshot()) { 8822 Surface.freezeDisplay(0); 8823 } 8824 } else { 8825 Surface.freezeDisplay(0); 8826 } 8827 } 8828 8829 private void stopFreezingDisplayLocked() { 8830 if (!mDisplayFrozen) { 8831 return; 8832 } 8833 8834 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) { 8835 if (DEBUG_ORIENTATION) Slog.d(TAG, 8836 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 8837 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 8838 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen); 8839 return; 8840 } 8841 8842 mDisplayFrozen = false; 8843 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 8844 if (PROFILE_ORIENTATION) { 8845 Debug.stopMethodTracing(); 8846 } 8847 8848 boolean updateRotation = false; 8849 8850 if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null 8851 && mAnimator.mScreenRotationAnimation.hasScreenshot()) { 8852 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 8853 if (mAnimator.mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 8854 mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) { 8855 scheduleAnimationLocked(); 8856 } else { 8857 mAnimator.mScreenRotationAnimation = null; 8858 updateRotation = true; 8859 } 8860 } else { 8861 if (mAnimator.mScreenRotationAnimation != null) { 8862 mAnimator.mScreenRotationAnimation.kill(); 8863 mAnimator.mScreenRotationAnimation = null; 8864 } 8865 updateRotation = true; 8866 } 8867 Surface.unfreezeDisplay(0); 8868 8869 mInputMonitor.thawInputDispatchingLw(); 8870 8871 boolean configChanged; 8872 8873 // While the display is frozen we don't re-compute the orientation 8874 // to avoid inconsistent states. However, something interesting 8875 // could have actually changed during that time so re-evaluate it 8876 // now to catch that. 8877 configChanged = updateOrientationFromAppTokensLocked(false); 8878 8879 // A little kludge: a lot could have happened while the 8880 // display was frozen, so now that we are coming back we 8881 // do a gc so that any remote references the system 8882 // processes holds on others can be released if they are 8883 // no longer needed. 8884 mH.removeMessages(H.FORCE_GC); 8885 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 8886 2000); 8887 8888 mScreenFrozenLock.release(); 8889 8890 if (updateRotation) { 8891 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 8892 configChanged |= updateRotationUncheckedLocked(false); 8893 } 8894 8895 if (configChanged) { 8896 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8897 } 8898 } 8899 8900 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 8901 DisplayMetrics dm) { 8902 if (index < tokens.length) { 8903 String str = tokens[index]; 8904 if (str != null && str.length() > 0) { 8905 try { 8906 int val = Integer.parseInt(str); 8907 return val; 8908 } catch (Exception e) { 8909 } 8910 } 8911 } 8912 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 8913 return defDps; 8914 } 8915 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 8916 return val; 8917 } 8918 8919 void createWatermark() { 8920 if (mWatermark != null) { 8921 return; 8922 } 8923 8924 File file = new File("/system/etc/setup.conf"); 8925 FileInputStream in = null; 8926 try { 8927 in = new FileInputStream(file); 8928 DataInputStream ind = new DataInputStream(in); 8929 String line = ind.readLine(); 8930 if (line != null) { 8931 String[] toks = line.split("%"); 8932 if (toks != null && toks.length > 0) { 8933 mWatermark = new Watermark(mRealDisplayMetrics, mFxSession, toks); 8934 } 8935 } 8936 } catch (FileNotFoundException e) { 8937 } catch (IOException e) { 8938 } finally { 8939 if (in != null) { 8940 try { 8941 in.close(); 8942 } catch (IOException e) { 8943 } 8944 } 8945 } 8946 } 8947 8948 @Override 8949 public void statusBarVisibilityChanged(int visibility) { 8950 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 8951 != PackageManager.PERMISSION_GRANTED) { 8952 throw new SecurityException("Caller does not hold permission " 8953 + android.Manifest.permission.STATUS_BAR); 8954 } 8955 8956 synchronized (mWindowMap) { 8957 mLastStatusBarVisibility = visibility; 8958 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 8959 updateStatusBarVisibilityLocked(visibility); 8960 } 8961 } 8962 8963 void updateStatusBarVisibilityLocked(int visibility) { 8964 mInputManager.setSystemUiVisibility(visibility); 8965 final int N = mWindows.size(); 8966 for (int i = 0; i < N; i++) { 8967 WindowState ws = mWindows.get(i); 8968 try { 8969 int curValue = ws.mSystemUiVisibility; 8970 int diff = curValue ^ visibility; 8971 // We are only interested in differences of one of the 8972 // clearable flags... 8973 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 8974 // ...if it has actually been cleared. 8975 diff &= ~visibility; 8976 int newValue = (curValue&~diff) | (visibility&diff); 8977 if (newValue != curValue) { 8978 ws.mSeq++; 8979 ws.mSystemUiVisibility = newValue; 8980 } 8981 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 8982 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 8983 visibility, newValue, diff); 8984 } 8985 } catch (RemoteException e) { 8986 // so sorry 8987 } 8988 } 8989 } 8990 8991 @Override 8992 public void reevaluateStatusBarVisibility() { 8993 synchronized (mWindowMap) { 8994 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 8995 updateStatusBarVisibilityLocked(visibility); 8996 performLayoutAndPlaceSurfacesLocked(); 8997 } 8998 } 8999 9000 @Override 9001 public FakeWindow addFakeWindow(Looper looper, 9002 InputEventReceiver.Factory inputEventReceiverFactory, 9003 String name, int windowType, int layoutParamsFlags, boolean canReceiveKeys, 9004 boolean hasFocus, boolean touchFullscreen) { 9005 synchronized (mWindowMap) { 9006 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 9007 name, windowType, 9008 layoutParamsFlags, canReceiveKeys, hasFocus, touchFullscreen); 9009 int i=0; 9010 while (i<mFakeWindows.size()) { 9011 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 9012 break; 9013 } 9014 } 9015 mFakeWindows.add(i, fw); 9016 mInputMonitor.updateInputWindowsLw(true); 9017 return fw; 9018 } 9019 } 9020 9021 boolean removeFakeWindowLocked(FakeWindow window) { 9022 synchronized (mWindowMap) { 9023 if (mFakeWindows.remove(window)) { 9024 mInputMonitor.updateInputWindowsLw(true); 9025 return true; 9026 } 9027 return false; 9028 } 9029 } 9030 9031 @Override 9032 public boolean hasNavigationBar() { 9033 return mPolicy.hasNavigationBar(); 9034 } 9035 9036 public void lockNow() { 9037 mPolicy.lockNow(); 9038 } 9039 9040 void dumpPolicyLocked(FileDescriptor fd, PrintWriter pw, String[] args, boolean dumpAll) { 9041 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 9042 mPolicy.dump(" ", fd, pw, args); 9043 } 9044 9045 void dumpTokensLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll) { 9046 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 9047 if (mTokenMap.size() > 0) { 9048 pw.println(" All tokens:"); 9049 Iterator<WindowToken> it = mTokenMap.values().iterator(); 9050 while (it.hasNext()) { 9051 WindowToken token = it.next(); 9052 pw.print(" Token "); pw.print(token.token); 9053 if (dumpAll) { 9054 pw.println(':'); 9055 token.dump(pw, " "); 9056 } else { 9057 pw.println(); 9058 } 9059 } 9060 } 9061 if (mWallpaperTokens.size() > 0) { 9062 pw.println(); 9063 pw.println(" Wallpaper tokens:"); 9064 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 9065 WindowToken token = mWallpaperTokens.get(i); 9066 pw.print(" Wallpaper #"); pw.print(i); 9067 pw.print(' '); pw.print(token); 9068 if (dumpAll) { 9069 pw.println(':'); 9070 token.dump(pw, " "); 9071 } else { 9072 pw.println(); 9073 } 9074 } 9075 } 9076 if (mAppTokens.size() > 0) { 9077 pw.println(); 9078 pw.println(" Application tokens in Z order:"); 9079 for (int i=mAppTokens.size()-1; i>=0; i--) { 9080 pw.print(" App #"); pw.print(i); pw.println(": "); 9081 mAppTokens.get(i).dump(pw, " "); 9082 } 9083 } 9084 if (mFinishedStarting.size() > 0) { 9085 pw.println(); 9086 pw.println(" Finishing start of application tokens:"); 9087 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 9088 WindowToken token = mFinishedStarting.get(i); 9089 pw.print(" Finished Starting #"); 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 (mExitingTokens.size() > 0) { 9100 pw.println(); 9101 pw.println(" Exiting tokens:"); 9102 for (int i=mExitingTokens.size()-1; i>=0; i--) { 9103 WindowToken token = mExitingTokens.get(i); 9104 pw.print(" Exiting #"); 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 if (mExitingAppTokens.size() > 0) { 9115 pw.println(); 9116 pw.println(" Exiting application tokens:"); 9117 for (int i=mExitingAppTokens.size()-1; i>=0; i--) { 9118 WindowToken token = mExitingAppTokens.get(i); 9119 pw.print(" Exiting App #"); pw.print(i); 9120 pw.print(' '); pw.print(token); 9121 if (dumpAll) { 9122 pw.println(':'); 9123 token.dump(pw, " "); 9124 } else { 9125 pw.println(); 9126 } 9127 } 9128 } 9129 pw.println(); 9130 if (mOpeningApps.size() > 0) { 9131 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 9132 } 9133 if (mClosingApps.size() > 0) { 9134 pw.print(" mClosingApps="); pw.println(mClosingApps); 9135 } 9136 if (mToTopApps.size() > 0) { 9137 pw.print(" mToTopApps="); pw.println(mToTopApps); 9138 } 9139 if (mToBottomApps.size() > 0) { 9140 pw.print(" mToBottomApps="); pw.println(mToBottomApps); 9141 } 9142 } 9143 9144 void dumpSessionsLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll) { 9145 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 9146 if (mSessions.size() > 0) { 9147 Iterator<Session> it = mSessions.iterator(); 9148 while (it.hasNext()) { 9149 Session s = it.next(); 9150 pw.print(" Session "); pw.print(s); pw.println(':'); 9151 s.dump(pw, " "); 9152 } 9153 } 9154 } 9155 9156 void dumpWindowsLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll, 9157 ArrayList<WindowState> windows) { 9158 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 9159 for (int i=mWindows.size()-1; i>=0; i--) { 9160 WindowState w = mWindows.get(i); 9161 if (windows == null || windows.contains(w)) { 9162 pw.print(" Window #"); pw.print(i); pw.print(' '); 9163 pw.print(w); pw.println(":"); 9164 w.dump(pw, " ", dumpAll || windows != null); 9165 } 9166 } 9167 if (mInputMethodDialogs.size() > 0) { 9168 pw.println(); 9169 pw.println(" Input method dialogs:"); 9170 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 9171 WindowState w = mInputMethodDialogs.get(i); 9172 if (windows == null || windows.contains(w)) { 9173 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 9174 } 9175 } 9176 } 9177 if (mPendingRemove.size() > 0) { 9178 pw.println(); 9179 pw.println(" Remove pending for:"); 9180 for (int i=mPendingRemove.size()-1; i>=0; i--) { 9181 WindowState w = mPendingRemove.get(i); 9182 if (windows == null || windows.contains(w)) { 9183 pw.print(" Remove #"); pw.print(i); pw.print(' '); 9184 pw.print(w); 9185 if (dumpAll) { 9186 pw.println(":"); 9187 w.dump(pw, " ", true); 9188 } else { 9189 pw.println(); 9190 } 9191 } 9192 } 9193 } 9194 if (mForceRemoves != null && mForceRemoves.size() > 0) { 9195 pw.println(); 9196 pw.println(" Windows force removing:"); 9197 for (int i=mForceRemoves.size()-1; i>=0; i--) { 9198 WindowState w = mForceRemoves.get(i); 9199 pw.print(" Removing #"); pw.print(i); pw.print(' '); 9200 pw.print(w); 9201 if (dumpAll) { 9202 pw.println(":"); 9203 w.dump(pw, " ", true); 9204 } else { 9205 pw.println(); 9206 } 9207 } 9208 } 9209 if (mDestroySurface.size() > 0) { 9210 pw.println(); 9211 pw.println(" Windows waiting to destroy their surface:"); 9212 for (int i=mDestroySurface.size()-1; i>=0; i--) { 9213 WindowState w = mDestroySurface.get(i); 9214 if (windows == null || windows.contains(w)) { 9215 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 9216 pw.print(w); 9217 if (dumpAll) { 9218 pw.println(":"); 9219 w.dump(pw, " ", true); 9220 } else { 9221 pw.println(); 9222 } 9223 } 9224 } 9225 } 9226 if (mLosingFocus.size() > 0) { 9227 pw.println(); 9228 pw.println(" Windows losing focus:"); 9229 for (int i=mLosingFocus.size()-1; i>=0; i--) { 9230 WindowState w = mLosingFocus.get(i); 9231 if (windows == null || windows.contains(w)) { 9232 pw.print(" Losing #"); pw.print(i); pw.print(' '); 9233 pw.print(w); 9234 if (dumpAll) { 9235 pw.println(":"); 9236 w.dump(pw, " ", true); 9237 } else { 9238 pw.println(); 9239 } 9240 } 9241 } 9242 } 9243 if (mResizingWindows.size() > 0) { 9244 pw.println(); 9245 pw.println(" Windows waiting to resize:"); 9246 for (int i=mResizingWindows.size()-1; i>=0; i--) { 9247 WindowState w = mResizingWindows.get(i); 9248 if (windows == null || windows.contains(w)) { 9249 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 9250 pw.print(w); 9251 if (dumpAll) { 9252 pw.println(":"); 9253 w.dump(pw, " ", true); 9254 } else { 9255 pw.println(); 9256 } 9257 } 9258 } 9259 } 9260 if (mWaitingForDrawn.size() > 0) { 9261 pw.println(); 9262 pw.println(" Clients waiting for these windows to be drawn:"); 9263 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 9264 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i); 9265 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first); 9266 pw.print(": "); pw.println(pair.second); 9267 } 9268 } 9269 pw.println(); 9270 if (mDisplay != null) { 9271 pw.print(" Display: init="); pw.print(mInitialDisplayWidth); pw.print("x"); 9272 pw.print(mInitialDisplayHeight); pw.print(" base="); 9273 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); 9274 pw.print(" cur="); 9275 pw.print(mCurDisplayWidth); pw.print("x"); pw.print(mCurDisplayHeight); 9276 pw.print(" app="); 9277 pw.print(mAppDisplayWidth); pw.print("x"); pw.print(mAppDisplayHeight); 9278 pw.print(" raw="); pw.print(mDisplay.getRawWidth()); 9279 pw.print("x"); pw.println(mDisplay.getRawHeight()); 9280 } else { 9281 pw.println(" NO DISPLAY"); 9282 } 9283 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 9284 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 9285 if (mLastFocus != mCurrentFocus) { 9286 pw.print(" mLastFocus="); pw.println(mLastFocus); 9287 } 9288 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 9289 if (mInputMethodTarget != null) { 9290 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 9291 } 9292 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 9293 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 9294 if (dumpAll) { 9295 if (mLastStatusBarVisibility != 0) { 9296 pw.print(" mLastStatusBarVisibility=0x"); 9297 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 9298 } 9299 if (mInputMethodWindow != null) { 9300 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 9301 } 9302 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 9303 if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) { 9304 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 9305 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 9306 } 9307 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 9308 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 9309 if (mInputMethodAnimLayerAdjustment != 0 || 9310 mWallpaperAnimLayerAdjustment != 0) { 9311 pw.print(" mInputMethodAnimLayerAdjustment="); 9312 pw.print(mInputMethodAnimLayerAdjustment); 9313 pw.print(" mWallpaperAnimLayerAdjustment="); 9314 pw.println(mWallpaperAnimLayerAdjustment); 9315 } 9316 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 9317 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 9318 pw.print(" mLayoutNeeded="); pw.println(mLayoutNeeded); 9319 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 9320 pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen); 9321 pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen); 9322 pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig); 9323 pw.print(" mRotation="); pw.print(mRotation); 9324 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 9325 pw.print(" mLastWindowForcedOrientation"); pw.print(mLastWindowForcedOrientation); 9326 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 9327 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 9328 if (mAnimator.mScreenRotationAnimation != null) { 9329 pw.println(" mScreenRotationAnimation:"); 9330 mAnimator.mScreenRotationAnimation.printTo(" ", pw); 9331 } 9332 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); 9333 pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale); 9334 pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale); 9335 pw.print(" mTraversalScheduled="); pw.print(mTraversalScheduled); 9336 pw.print(" mNextAppTransition=0x"); 9337 pw.print(Integer.toHexString(mNextAppTransition)); 9338 pw.print(" mAppTransitionReady="); pw.println(mAppTransitionReady); 9339 pw.print(" mAppTransitionRunning="); pw.print(mAppTransitionRunning); 9340 pw.print(" mAppTransitionTimeout="); pw.println( mAppTransitionTimeout); 9341 if (mNextAppTransitionPackage != null) { 9342 pw.print(" mNextAppTransitionPackage="); 9343 pw.print(mNextAppTransitionPackage); 9344 pw.print(" mNextAppTransitionEnter=0x"); 9345 pw.print(Integer.toHexString(mNextAppTransitionEnter)); 9346 pw.print(" mNextAppTransitionExit=0x"); 9347 pw.print(Integer.toHexString(mNextAppTransitionExit)); 9348 } 9349 if (mNextAppTransitionThumbnail != null) { 9350 pw.print(" mNextAppTransitionThumbnail="); 9351 pw.print(mNextAppTransitionThumbnail); 9352 pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX); 9353 pw.print(" mNextAppTransitionStartY="); pw.println(mNextAppTransitionStartY); 9354 } 9355 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 9356 pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 9357 } 9358 } 9359 9360 boolean dumpWindows(FileDescriptor fd, PrintWriter pw, String name, String[] args, 9361 int opti, boolean dumpAll) { 9362 ArrayList<WindowState> windows = new ArrayList<WindowState>(); 9363 if ("visible".equals(name)) { 9364 synchronized(mWindowMap) { 9365 for (int i=mWindows.size()-1; i>=0; i--) { 9366 WindowState w = mWindows.get(i); 9367 if (w.mWinAnimator.mSurfaceShown) { 9368 windows.add(w); 9369 } 9370 } 9371 } 9372 } else { 9373 int objectId = 0; 9374 // See if this is an object ID. 9375 try { 9376 objectId = Integer.parseInt(name, 16); 9377 name = null; 9378 } catch (RuntimeException e) { 9379 } 9380 synchronized(mWindowMap) { 9381 for (int i=mWindows.size()-1; i>=0; i--) { 9382 WindowState w = mWindows.get(i); 9383 if (name != null) { 9384 if (w.mAttrs.getTitle().toString().contains(name)) { 9385 windows.add(w); 9386 } 9387 } else if (System.identityHashCode(w) == objectId) { 9388 windows.add(w); 9389 } 9390 } 9391 } 9392 } 9393 9394 if (windows.size() <= 0) { 9395 return false; 9396 } 9397 9398 synchronized(mWindowMap) { 9399 dumpWindowsLocked(fd, pw, dumpAll, windows); 9400 } 9401 return true; 9402 } 9403 9404 @Override 9405 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 9406 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 9407 != PackageManager.PERMISSION_GRANTED) { 9408 pw.println("Permission Denial: can't dump WindowManager from from pid=" 9409 + Binder.getCallingPid() 9410 + ", uid=" + Binder.getCallingUid()); 9411 return; 9412 } 9413 9414 boolean dumpAll = false; 9415 9416 int opti = 0; 9417 while (opti < args.length) { 9418 String opt = args[opti]; 9419 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 9420 break; 9421 } 9422 opti++; 9423 if ("-a".equals(opt)) { 9424 dumpAll = true; 9425 } else if ("-h".equals(opt)) { 9426 pw.println("Window manager dump options:"); 9427 pw.println(" [-a] [-h] [cmd] ..."); 9428 pw.println(" cmd may be one of:"); 9429 pw.println(" p[policy]: policy state"); 9430 pw.println(" s[essions]: active sessions"); 9431 pw.println(" t[okens]: token list"); 9432 pw.println(" w[indows]: window list"); 9433 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 9434 pw.println(" be a partial substring in a window name, a"); 9435 pw.println(" Window hex object identifier, or"); 9436 pw.println(" \"all\" for all windows, or"); 9437 pw.println(" \"visible\" for the visible windows."); 9438 pw.println(" -a: include all available server state."); 9439 return; 9440 } else { 9441 pw.println("Unknown argument: " + opt + "; use -h for help"); 9442 } 9443 } 9444 9445 // Is the caller requesting to dump a particular piece of data? 9446 if (opti < args.length) { 9447 String cmd = args[opti]; 9448 opti++; 9449 if ("policy".equals(cmd) || "p".equals(cmd)) { 9450 synchronized(mWindowMap) { 9451 dumpPolicyLocked(fd, pw, args, true); 9452 } 9453 return; 9454 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 9455 synchronized(mWindowMap) { 9456 dumpSessionsLocked(fd, pw, true); 9457 } 9458 return; 9459 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 9460 synchronized(mWindowMap) { 9461 dumpTokensLocked(fd, pw, true); 9462 } 9463 return; 9464 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 9465 synchronized(mWindowMap) { 9466 dumpWindowsLocked(fd, pw, true, null); 9467 } 9468 return; 9469 } else if ("all".equals(cmd) || "a".equals(cmd)) { 9470 synchronized(mWindowMap) { 9471 dumpWindowsLocked(fd, pw, true, null); 9472 } 9473 return; 9474 } else { 9475 // Dumping a single name? 9476 if (!dumpWindows(fd, pw, cmd, args, opti, dumpAll)) { 9477 pw.println("Bad window command, or no windows match: " + cmd); 9478 pw.println("Use -h for help."); 9479 } 9480 return; 9481 } 9482 } 9483 9484 synchronized(mWindowMap) { 9485 if (dumpAll) { 9486 pw.println("-------------------------------------------------------------------------------"); 9487 } 9488 dumpPolicyLocked(fd, pw, args, dumpAll); 9489 pw.println(); 9490 if (dumpAll) { 9491 pw.println("-------------------------------------------------------------------------------"); 9492 } 9493 dumpSessionsLocked(fd, pw, dumpAll); 9494 pw.println(); 9495 if (dumpAll) { 9496 pw.println("-------------------------------------------------------------------------------"); 9497 } 9498 dumpTokensLocked(fd, pw, dumpAll); 9499 pw.println(); 9500 if (dumpAll) { 9501 pw.println("-------------------------------------------------------------------------------"); 9502 } 9503 dumpWindowsLocked(fd, pw, dumpAll, null); 9504 } 9505 } 9506 9507 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 9508 public void monitor() { 9509 synchronized (mWindowMap) { } 9510 synchronized (mKeyguardTokenWatcher) { } 9511 } 9512 9513 public interface OnHardKeyboardStatusChangeListener { 9514 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 9515 } 9516 9517 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 9518 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 9519 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 9520 Integer.toHexString(pendingLayoutChanges)); 9521 } 9522 } 9523 9524 void bulkSetParameters(final int bulkUpdateParams) { 9525 mH.sendMessage(mH.obtainMessage(H.BULK_UPDATE_PARAMETERS, bulkUpdateParams, 0)); 9526 } 9527} 9528