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