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