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