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