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