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