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