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