WindowManagerService.java revision bc2a6dff1f0edfb2856377fbdb6378158621bd16
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.Iterator; 155import java.util.List; 156 157/** {@hide} */ 158public class WindowManagerService extends IWindowManager.Stub 159 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs { 160 static final String TAG = "WindowManager"; 161 static final boolean DEBUG = false; 162 static final boolean DEBUG_ADD_REMOVE = false; 163 static final boolean DEBUG_FOCUS = false; 164 static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false; 165 static final boolean DEBUG_ANIM = false; 166 static final boolean DEBUG_LAYOUT = false; 167 static final boolean DEBUG_RESIZE = false; 168 static final boolean DEBUG_LAYERS = false; 169 static final boolean DEBUG_INPUT = false; 170 static final boolean DEBUG_INPUT_METHOD = false; 171 static final boolean DEBUG_VISIBILITY = false; 172 static final boolean DEBUG_WINDOW_MOVEMENT = false; 173 static final boolean DEBUG_TOKEN_MOVEMENT = false; 174 static final boolean DEBUG_ORIENTATION = false; 175 static final boolean DEBUG_APP_ORIENTATION = false; 176 static final boolean DEBUG_CONFIGURATION = false; 177 static final boolean DEBUG_APP_TRANSITIONS = false; 178 static final boolean DEBUG_STARTING_WINDOW = false; 179 static final boolean DEBUG_REORDER = false; 180 static final boolean DEBUG_WALLPAPER = false; 181 static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER; 182 static final boolean DEBUG_DRAG = false; 183 static final boolean DEBUG_SCREEN_ON = false; 184 static final boolean DEBUG_SCREENSHOT = false; 185 static final boolean DEBUG_BOOT = false; 186 static final boolean DEBUG_LAYOUT_REPEATS = true; 187 static final boolean DEBUG_SURFACE_TRACE = false; 188 static final boolean DEBUG_WINDOW_TRACE = false; 189 static final boolean DEBUG_TASK_MOVEMENT = false; 190 static final boolean DEBUG_STACK = false; 191 static final boolean DEBUG_DISPLAY = false; 192 static final boolean SHOW_SURFACE_ALLOC = false; 193 static final boolean SHOW_TRANSACTIONS = false; 194 static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS; 195 static final boolean HIDE_STACK_CRAWLS = true; 196 static final int LAYOUT_REPEAT_THRESHOLD = 4; 197 198 static final boolean PROFILE_ORIENTATION = false; 199 static final boolean localLOGV = DEBUG; 200 201 /** How much to multiply the policy's type layer, to reserve room 202 * for multiple windows of the same type and Z-ordering adjustment 203 * with TYPE_LAYER_OFFSET. */ 204 static final int TYPE_LAYER_MULTIPLIER = 10000; 205 206 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above 207 * or below others in the same layer. */ 208 static final int TYPE_LAYER_OFFSET = 1000; 209 210 /** How much to increment the layer for each window, to reserve room 211 * for effect surfaces between them. 212 */ 213 static final int WINDOW_LAYER_MULTIPLIER = 5; 214 215 /** 216 * Dim surface layer is immediately below target window. 217 */ 218 static final int LAYER_OFFSET_DIM = 1; 219 220 /** 221 * Blur surface layer is immediately below dim layer. 222 */ 223 static final int LAYER_OFFSET_BLUR = 2; 224 225 /** 226 * FocusedStackFrame layer is immediately above focused window. 227 */ 228 static final int LAYER_OFFSET_FOCUSED_STACK = 1; 229 230 /** 231 * Animation thumbnail is as far as possible below the window above 232 * the thumbnail (or in other words as far as possible above the window 233 * below it). 234 */ 235 static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER-1; 236 237 /** 238 * Layer at which to put the rotation freeze snapshot. 239 */ 240 static final int FREEZE_LAYER = (TYPE_LAYER_MULTIPLIER * 200) + 1; 241 242 /** 243 * Layer at which to put the mask for emulated screen sizes. 244 */ 245 static final int MASK_LAYER = TYPE_LAYER_MULTIPLIER * 200; 246 247 /** The maximum length we will accept for a loaded animation duration: 248 * this is 10 seconds. 249 */ 250 static final int MAX_ANIMATION_DURATION = 10*1000; 251 252 /** Amount of time (in milliseconds) to animate the fade-in-out transition for 253 * compatible windows. 254 */ 255 static final int DEFAULT_FADE_IN_OUT_DURATION = 400; 256 257 /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */ 258 static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000; 259 260 /** 261 * If true, the window manager will do its own custom freezing and general 262 * management of the screen during rotation. 263 */ 264 static final boolean CUSTOM_SCREEN_ROTATION = true; 265 266 // Maximum number of milliseconds to wait for input devices to be enumerated before 267 // proceding with safe mode detection. 268 private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000; 269 270 // Default input dispatching timeout in nanoseconds. 271 static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L; 272 273 /** Minimum value for attachStack and resizeStack weight value */ 274 public static final float STACK_WEIGHT_MIN = 0.2f; 275 276 /** Maximum value for attachStack and resizeStack weight value */ 277 public static final float STACK_WEIGHT_MAX = 0.8f; 278 279 static final int UPDATE_FOCUS_NORMAL = 0; 280 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1; 281 static final int UPDATE_FOCUS_PLACING_SURFACES = 2; 282 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3; 283 284 private static final String SYSTEM_SECURE = "ro.secure"; 285 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; 286 287 private static final String DENSITY_OVERRIDE = "ro.config.density_override"; 288 private static final String SIZE_OVERRIDE = "ro.config.size_override"; 289 290 private static final int MAX_SCREENSHOT_RETRIES = 3; 291 292 // The flag describing a full screen app window (where the app takes care of drawing under the 293 // SystemUI bars) 294 private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN = 295 View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 296 297 final private KeyguardDisableHandler mKeyguardDisableHandler; 298 299 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 300 @Override 301 public void onReceive(Context context, Intent intent) { 302 final String action = intent.getAction(); 303 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) { 304 mKeyguardDisableHandler.sendEmptyMessage( 305 KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED); 306 } 307 } 308 }; 309 310 /** 311 * Current user when multi-user is enabled. Don't show windows of 312 * non-current user. Also see mCurrentProfileIds. 313 */ 314 int mCurrentUserId; 315 /** 316 * Users that are profiles of the current user. These are also allowed to show windows 317 * on the current user. 318 */ 319 int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER}; 320 321 final Context mContext; 322 323 final boolean mHaveInputMethods; 324 325 final boolean mAllowBootMessages; 326 327 final boolean mLimitedAlphaCompositing; 328 329 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager(); 330 331 final IActivityManager mActivityManager; 332 333 final IBatteryStats mBatteryStats; 334 335 final AppOpsManager mAppOps; 336 337 final DisplaySettings mDisplaySettings; 338 339 /** 340 * All currently active sessions with clients. 341 */ 342 final ArraySet<Session> mSessions = new ArraySet<Session>(); 343 344 /** 345 * Mapping from an IWindow IBinder to the server's Window object. 346 * This is also used as the lock for all of our state. 347 * NOTE: Never call into methods that lock ActivityManagerService while holding this object. 348 */ 349 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>(); 350 351 /** 352 * Mapping from a token IBinder to a WindowToken object. 353 */ 354 final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>(); 355 356 /** 357 * List of window tokens that have finished starting their application, 358 * and now need to have the policy remove their windows. 359 */ 360 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>(); 361 362 /** 363 * Fake windows added to the window manager. Note: ordered from top to 364 * bottom, opposite of mWindows. 365 */ 366 final ArrayList<FakeWindowImpl> mFakeWindows = new ArrayList<FakeWindowImpl>(); 367 368 /** 369 * Windows that are being resized. Used so we can tell the client about 370 * the resize after closing the transaction in which we resized the 371 * underlying surface. 372 */ 373 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>(); 374 375 /** 376 * Windows whose animations have ended and now must be removed. 377 */ 378 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>(); 379 380 /** 381 * Stacks whose animations have ended and whose tasks, apps, selves may now be removed. 382 */ 383 final ArraySet<TaskStack> mPendingStacksRemove = new ArraySet<TaskStack>(); 384 385 /** 386 * Used when processing mPendingRemove to avoid working on the original array. 387 */ 388 WindowState[] mPendingRemoveTmp = new WindowState[20]; 389 390 /** 391 * Windows whose surface should be destroyed. 392 */ 393 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>(); 394 395 /** 396 * Windows that have lost input focus and are waiting for the new 397 * focus window to be displayed before they are told about this. 398 */ 399 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>(); 400 401 /** 402 * This is set when we have run out of memory, and will either be an empty 403 * list or contain windows that need to be force removed. 404 */ 405 ArrayList<WindowState> mForceRemoves; 406 407 /** 408 * Windows that clients are waiting to have drawn. 409 */ 410 ArrayList<WindowState> mWaitingForDrawn = new ArrayList<WindowState>(); 411 /** 412 * And the callback to make when they've all been drawn. 413 */ 414 IRemoteCallback mWaitingForDrawnCallback; 415 416 /** 417 * Windows that have called relayout() while we were running animations, 418 * so we need to tell when the animation is done. 419 */ 420 final ArrayList<WindowState> mRelayoutWhileAnimating = new ArrayList<WindowState>(); 421 422 /** 423 * Used when rebuilding window list to keep track of windows that have 424 * been removed. 425 */ 426 WindowState[] mRebuildTmp = new WindowState[20]; 427 428 IInputMethodManager mInputMethodManager; 429 430 AccessibilityController mAccessibilityController; 431 432 final SurfaceSession mFxSession; 433 Watermark mWatermark; 434 StrictModeFlash mStrictModeFlash; 435 FocusedStackFrame mFocusedStackFrame; 436 437 int mFocusedStackLayer; 438 439 final float[] mTmpFloats = new float[9]; 440 final Rect mTmpContentRect = new Rect(); 441 442 boolean mDisplayReady; 443 boolean mSafeMode; 444 boolean mDisplayEnabled = false; 445 boolean mSystemBooted = false; 446 boolean mForceDisplayEnabled = false; 447 boolean mShowingBootMessages = false; 448 449 String mLastANRState; 450 451 /** All DisplayContents in the world, kept here */ 452 SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>(2); 453 454 int mRotation = 0; 455 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 456 boolean mAltOrientation = false; 457 class RotationWatcher { 458 IRotationWatcher watcher; 459 IBinder.DeathRecipient deathRecipient; 460 RotationWatcher(IRotationWatcher w, IBinder.DeathRecipient d) { 461 watcher = w; 462 deathRecipient = d; 463 } 464 } 465 ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<RotationWatcher>(); 466 int mDeferredRotationPauseCount; 467 468 int mSystemDecorLayer = 0; 469 final Rect mScreenRect = new Rect(); 470 471 boolean mTraversalScheduled = false; 472 boolean mDisplayFrozen = false; 473 long mDisplayFreezeTime = 0; 474 int mLastDisplayFreezeDuration = 0; 475 Object mLastFinishedFreezeSource = null; 476 boolean mWaitingForConfig = false; 477 boolean mWindowsFreezingScreen = false; 478 boolean mClientFreezingScreen = false; 479 int mAppsFreezingScreen = 0; 480 int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 481 482 int mLayoutSeq = 0; 483 484 int mLastStatusBarVisibility = 0; 485 486 // State while inside of layoutAndPlaceSurfacesLocked(). 487 boolean mFocusMayChange; 488 489 Configuration mCurConfiguration = new Configuration(); 490 491 // This is held as long as we have the screen frozen, to give us time to 492 // perform a rotation animation when turning off shows the lock screen which 493 // changes the orientation. 494 private final PowerManager.WakeLock mScreenFrozenLock; 495 496 final AppTransition mAppTransition; 497 boolean mStartingIconInTransition = false; 498 boolean mSkipAppTransitionAnimation = false; 499 500 final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>(); 501 final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>(); 502 503 boolean mIsTouchDevice; 504 505 final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 506 final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics(); 507 final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics(); 508 final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics(); 509 510 final H mH = new H(); 511 512 final Choreographer mChoreographer = Choreographer.getInstance(); 513 514 WindowState mCurrentFocus = null; 515 WindowState mLastFocus = null; 516 517 /** This just indicates the window the input method is on top of, not 518 * necessarily the window its input is going to. */ 519 WindowState mInputMethodTarget = null; 520 521 /** If true hold off on modifying the animation layer of mInputMethodTarget */ 522 boolean mInputMethodTargetWaitingAnim; 523 int mInputMethodAnimLayerAdjustment; 524 525 WindowState mInputMethodWindow = null; 526 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>(); 527 528 boolean mHardKeyboardAvailable; 529 boolean mHardKeyboardEnabled; 530 OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; 531 532 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>(); 533 534 // If non-null, this is the currently visible window that is associated 535 // with the wallpaper. 536 WindowState mWallpaperTarget = null; 537 // If non-null, we are in the middle of animating from one wallpaper target 538 // to another, and this is the lower one in Z-order. 539 WindowState mLowerWallpaperTarget = null; 540 // If non-null, we are in the middle of animating from one wallpaper target 541 // to another, and this is the higher one in Z-order. 542 WindowState mUpperWallpaperTarget = null; 543 int mWallpaperAnimLayerAdjustment; 544 float mLastWallpaperX = -1; 545 float mLastWallpaperY = -1; 546 float mLastWallpaperXStep = -1; 547 float mLastWallpaperYStep = -1; 548 // This is set when we are waiting for a wallpaper to tell us it is done 549 // changing its scroll position. 550 WindowState mWaitingOnWallpaper; 551 // The last time we had a timeout when waiting for a wallpaper. 552 long mLastWallpaperTimeoutTime; 553 // We give a wallpaper up to 150ms to finish scrolling. 554 static final long WALLPAPER_TIMEOUT = 150; 555 // Time we wait after a timeout before trying to wait again. 556 static final long WALLPAPER_TIMEOUT_RECOVERY = 10000; 557 boolean mAnimateWallpaperWithTarget; 558 559 AppWindowToken mFocusedApp = null; 560 561 PowerManager mPowerManager; 562 PowerManagerInternal mPowerManagerInternal; 563 564 float mWindowAnimationScaleSetting = 1.0f; 565 float mTransitionAnimationScaleSetting = 1.0f; 566 float mAnimatorDurationScaleSetting = 1.0f; 567 boolean mAnimationsDisabled = false; 568 569 final InputManagerService mInputManager; 570 final DisplayManagerInternal mDisplayManagerInternal; 571 final DisplayManager mDisplayManager; 572 573 // Who is holding the screen on. 574 Session mHoldingScreenOn; 575 PowerManager.WakeLock mHoldingScreenWakeLock; 576 577 boolean mTurnOnScreen; 578 579 DragState mDragState = null; 580 581 // For frozen screen animations. 582 int mExitAnimId, mEnterAnimId; 583 584 /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple 585 * methods. */ 586 class LayoutFields { 587 static final int SET_UPDATE_ROTATION = 1 << 0; 588 static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1; 589 static final int SET_FORCE_HIDING_CHANGED = 1 << 2; 590 static final int SET_ORIENTATION_CHANGE_COMPLETE = 1 << 3; 591 static final int SET_TURN_ON_SCREEN = 1 << 4; 592 static final int SET_WALLPAPER_ACTION_PENDING = 1 << 5; 593 594 boolean mWallpaperForceHidingChanged = false; 595 boolean mWallpaperMayChange = false; 596 boolean mOrientationChangeComplete = true; 597 Object mLastWindowFreezeSource = null; 598 private Session mHoldScreen = null; 599 private boolean mObscured = false; 600 private boolean mSyswin = false; 601 private float mScreenBrightness = -1; 602 private float mButtonBrightness = -1; 603 private long mUserActivityTimeout = -1; 604 private boolean mUpdateRotation = false; 605 boolean mWallpaperActionPending = false; 606 607 // Set to true when the display contains content to show the user. 608 // When false, the display manager may choose to mirror or blank the display. 609 boolean mDisplayHasContent = false; 610 611 // Only set while traversing the default display based on its content. 612 // Affects the behavior of mirroring on secondary displays. 613 boolean mObscureApplicationContentOnSecondaryDisplays = false; 614 } 615 final LayoutFields mInnerFields = new LayoutFields(); 616 617 boolean mAnimationScheduled; 618 619 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this 620 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */ 621 private int mTransactionSequence; 622 623 /** Only do a maximum of 6 repeated layouts. After that quit */ 624 private int mLayoutRepeatCount; 625 626 final WindowAnimator mAnimator; 627 628 SparseArray<Task> mTaskIdToTask = new SparseArray<Task>(); 629 630 /** All of the TaskStacks in the window manager, unordered. For an ordered list call 631 * DisplayContent.getStacks(). */ 632 SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>(); 633 634 private final PointerEventDispatcher mPointerEventDispatcher; 635 636 private WindowContentFrameStats mTempWindowRenderStats; 637 638 final class DragInputEventReceiver extends InputEventReceiver { 639 public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { 640 super(inputChannel, looper); 641 } 642 643 @Override 644 public void onInputEvent(InputEvent event) { 645 boolean handled = false; 646 try { 647 if (event instanceof MotionEvent 648 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0 649 && mDragState != null) { 650 final MotionEvent motionEvent = (MotionEvent)event; 651 boolean endDrag = false; 652 final float newX = motionEvent.getRawX(); 653 final float newY = motionEvent.getRawY(); 654 655 switch (motionEvent.getAction()) { 656 case MotionEvent.ACTION_DOWN: { 657 if (DEBUG_DRAG) { 658 Slog.w(TAG, "Unexpected ACTION_DOWN in drag layer"); 659 } 660 } break; 661 662 case MotionEvent.ACTION_MOVE: { 663 synchronized (mWindowMap) { 664 // move the surface and tell the involved window(s) where we are 665 mDragState.notifyMoveLw(newX, newY); 666 } 667 } break; 668 669 case MotionEvent.ACTION_UP: { 670 if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at " 671 + newX + "," + newY); 672 synchronized (mWindowMap) { 673 endDrag = mDragState.notifyDropLw(newX, newY); 674 } 675 } break; 676 677 case MotionEvent.ACTION_CANCEL: { 678 if (DEBUG_DRAG) Slog.d(TAG, "Drag cancelled!"); 679 endDrag = true; 680 } break; 681 } 682 683 if (endDrag) { 684 if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state"); 685 // tell all the windows that the drag has ended 686 synchronized (mWindowMap) { 687 mDragState.endDragLw(); 688 } 689 } 690 691 handled = true; 692 } 693 } catch (Exception e) { 694 Slog.e(TAG, "Exception caught by drag handleMotion", e); 695 } finally { 696 finishInputEvent(event, handled); 697 } 698 } 699 } 700 701 /** 702 * Whether the UI is currently running in touch mode (not showing 703 * navigational focus because the user is directly pressing the screen). 704 */ 705 boolean mInTouchMode = true; 706 707 private ViewServer mViewServer; 708 private final ArrayList<WindowChangeListener> mWindowChangeListeners = 709 new ArrayList<WindowChangeListener>(); 710 private boolean mWindowsChanged = false; 711 712 public interface WindowChangeListener { 713 public void windowsChanged(); 714 public void focusChanged(); 715 } 716 717 final Configuration mTempConfiguration = new Configuration(); 718 719 // The desired scaling factor for compatible apps. 720 float mCompatibleScreenScale; 721 722 // If true, only the core apps and services are being launched because the device 723 // is in a special boot mode, such as being encrypted or waiting for a decryption password. 724 // For example, when this flag is true, there will be no wallpaper service. 725 final boolean mOnlyCore; 726 727 public static WindowManagerService main(final Context context, 728 final InputManagerService im, 729 final boolean haveInputMethods, final boolean showBootMsgs, 730 final boolean onlyCore) { 731 final WindowManagerService[] holder = new WindowManagerService[1]; 732 DisplayThread.getHandler().runWithScissors(new Runnable() { 733 @Override 734 public void run() { 735 holder[0] = new WindowManagerService(context, im, 736 haveInputMethods, showBootMsgs, onlyCore); 737 } 738 }, 0); 739 return holder[0]; 740 } 741 742 private void initPolicy() { 743 UiThread.getHandler().runWithScissors(new Runnable() { 744 @Override 745 public void run() { 746 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper()); 747 748 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this); 749 mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer() 750 * TYPE_LAYER_MULTIPLIER 751 + TYPE_LAYER_OFFSET; 752 } 753 }, 0); 754 } 755 756 private WindowManagerService(Context context, InputManagerService inputManager, 757 boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) { 758 mContext = context; 759 mHaveInputMethods = haveInputMethods; 760 mAllowBootMessages = showBootMsgs; 761 mOnlyCore = onlyCore; 762 mLimitedAlphaCompositing = context.getResources().getBoolean( 763 com.android.internal.R.bool.config_sf_limitedAlpha); 764 mInputManager = inputManager; // Must be before createDisplayContentLocked. 765 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); 766 mDisplaySettings = new DisplaySettings(context); 767 mDisplaySettings.readSettingsLocked(); 768 769 mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG)); 770 771 mFxSession = new SurfaceSession(); 772 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); 773 Display[] displays = mDisplayManager.getDisplays(); 774 for (Display display : displays) { 775 createDisplayContentLocked(display); 776 } 777 778 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy); 779 780 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 781 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 782 mPowerManagerInternal.setPolicy(mPolicy); // TODO: register as local service instead 783 mPowerManagerInternal.registerLowPowerModeObserver( 784 new PowerManagerInternal.LowPowerModeListener() { 785 @Override 786 public void onLowPowerModeChanged(boolean enabled) { 787 synchronized (mWindowMap) { 788 if (mAnimationsDisabled != enabled) { 789 mAnimationsDisabled = enabled; 790 dispatchNewAnimatorScaleLocked(null); 791 } 792 } 793 } 794 }); 795 mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled(); 796 mScreenFrozenLock = mPowerManager.newWakeLock( 797 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN"); 798 mScreenFrozenLock.setReferenceCounted(false); 799 800 mAppTransition = new AppTransition(context, mH); 801 802 mActivityManager = ActivityManagerNative.getDefault(); 803 mBatteryStats = BatteryStatsService.getService(); 804 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 805 mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null, 806 new AppOpsManager.OnOpChangedInternalListener() { 807 @Override 808 public void onOpChanged(int op, String packageName) { 809 updateAppOpsState(); 810 } 811 } 812 ); 813 814 // Get persisted window scale setting 815 mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 816 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 817 mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 818 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting); 819 setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(), 820 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting)); 821 822 // Track changes to DevicePolicyManager state so we can enable/disable keyguard. 823 IntentFilter filter = new IntentFilter(); 824 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 825 mContext.registerReceiver(mBroadcastReceiver, filter); 826 827 mHoldingScreenWakeLock = mPowerManager.newWakeLock( 828 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG); 829 mHoldingScreenWakeLock.setReferenceCounted(false); 830 831 mAnimator = new WindowAnimator(this); 832 833 LocalServices.addService(WindowManagerInternal.class, new LocalService()); 834 initPolicy(); 835 836 // Add ourself to the Watchdog monitors. 837 Watchdog.getInstance().addMonitor(this); 838 839 SurfaceControl.openTransaction(); 840 try { 841 createWatermarkInTransaction(); 842 mFocusedStackFrame = new FocusedStackFrame( 843 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 844 } finally { 845 SurfaceControl.closeTransaction(); 846 } 847 } 848 849 public InputMonitor getInputMonitor() { 850 return mInputMonitor; 851 } 852 853 @Override 854 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 855 throws RemoteException { 856 try { 857 return super.onTransact(code, data, reply, flags); 858 } catch (RuntimeException e) { 859 // The window manager only throws security exceptions, so let's 860 // log all others. 861 if (!(e instanceof SecurityException)) { 862 Slog.wtf(TAG, "Window Manager Crash", e); 863 } 864 throw e; 865 } 866 } 867 868 private void placeWindowAfter(WindowState pos, WindowState window) { 869 final WindowList windows = pos.getWindowList(); 870 final int i = windows.indexOf(pos); 871 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 872 TAG, "Adding window " + window + " at " 873 + (i+1) + " of " + windows.size() + " (after " + pos + ")"); 874 windows.add(i+1, window); 875 mWindowsChanged = true; 876 } 877 878 private void placeWindowBefore(WindowState pos, WindowState window) { 879 final WindowList windows = pos.getWindowList(); 880 int i = windows.indexOf(pos); 881 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 882 TAG, "Adding window " + window + " at " 883 + i + " of " + windows.size() + " (before " + pos + ")"); 884 if (i < 0) { 885 Slog.w(TAG, "placeWindowBefore: Unable to find " + pos + " in " + windows); 886 i = 0; 887 } 888 windows.add(i, window); 889 mWindowsChanged = true; 890 } 891 892 //This method finds out the index of a window that has the same app token as 893 //win. used for z ordering the windows in mWindows 894 private int findIdxBasedOnAppTokens(WindowState win) { 895 WindowList windows = win.getWindowList(); 896 for(int j = windows.size() - 1; j >= 0; j--) { 897 WindowState wentry = windows.get(j); 898 if(wentry.mAppToken == win.mAppToken) { 899 return j; 900 } 901 } 902 return -1; 903 } 904 905 /** 906 * Return the list of Windows from the passed token on the given Display. 907 * @param token The token with all the windows. 908 * @param displayContent The display we are interested in. 909 * @return List of windows from token that are on displayContent. 910 */ 911 WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) { 912 final WindowList windowList = new WindowList(); 913 final int count = token.windows.size(); 914 for (int i = 0; i < count; i++) { 915 final WindowState win = token.windows.get(i); 916 if (win.getDisplayContent() == displayContent) { 917 windowList.add(win); 918 } 919 } 920 return windowList; 921 } 922 923 /** 924 * Recursive search through a WindowList and all of its windows' children. 925 * @param targetWin The window to search for. 926 * @param windows The list to search. 927 * @return The index of win in windows or of the window that is an ancestor of win. 928 */ 929 private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) { 930 for (int i = windows.size() - 1; i >= 0; i--) { 931 final WindowState w = windows.get(i); 932 if (w == targetWin) { 933 return i; 934 } 935 if (!w.mChildWindows.isEmpty()) { 936 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) { 937 return i; 938 } 939 } 940 } 941 return -1; 942 } 943 944 private int addAppWindowToListLocked(final WindowState win) { 945 final IWindow client = win.mClient; 946 final WindowToken token = win.mToken; 947 final DisplayContent displayContent = win.getDisplayContent(); 948 if (displayContent == null) { 949 // It doesn't matter this display is going away. 950 return 0; 951 } 952 953 final WindowList windows = win.getWindowList(); 954 final int N = windows.size(); 955 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 956 int tokenWindowsPos = 0; 957 int windowListPos = tokenWindowList.size(); 958 if (!tokenWindowList.isEmpty()) { 959 // If this application has existing windows, we 960 // simply place the new window on top of them... but 961 // keep the starting window on top. 962 if (win.mAttrs.type == TYPE_BASE_APPLICATION) { 963 // Base windows go behind everything else. 964 WindowState lowestWindow = tokenWindowList.get(0); 965 placeWindowBefore(lowestWindow, win); 966 tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows); 967 } else { 968 AppWindowToken atoken = win.mAppToken; 969 WindowState lastWindow = tokenWindowList.get(windowListPos - 1); 970 if (atoken != null && lastWindow == atoken.startingWindow) { 971 placeWindowBefore(lastWindow, win); 972 tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows); 973 } else { 974 int newIdx = findIdxBasedOnAppTokens(win); 975 //there is a window above this one associated with the same 976 //apptoken note that the window could be a floating window 977 //that was created later or a window at the top of the list of 978 //windows associated with this token. 979 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 980 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " + 981 N); 982 windows.add(newIdx + 1, win); 983 if (newIdx < 0) { 984 // No window from token found on win's display. 985 tokenWindowsPos = 0; 986 } else { 987 tokenWindowsPos = indexOfWinInWindowList( 988 windows.get(newIdx), token.windows) + 1; 989 } 990 mWindowsChanged = true; 991 } 992 } 993 return tokenWindowsPos; 994 } 995 996 // No windows from this token on this display 997 if (localLOGV) Slog.v(TAG, "Figuring out where to add app window " + client.asBinder() 998 + " (token=" + token + ")"); 999 // Figure out where the window should go, based on the 1000 // order of applications. 1001 WindowState pos = null; 1002 1003 final ArrayList<Task> tasks = displayContent.getTasks(); 1004 int taskNdx; 1005 int tokenNdx = -1; 1006 for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 1007 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1008 for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 1009 final AppWindowToken t = tokens.get(tokenNdx); 1010 if (t == token) { 1011 --tokenNdx; 1012 if (tokenNdx < 0) { 1013 --taskNdx; 1014 if (taskNdx >= 0) { 1015 tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1; 1016 } 1017 } 1018 break; 1019 } 1020 1021 // We haven't reached the token yet; if this token 1022 // is not going to the bottom and has windows on this display, we can 1023 // use it as an anchor for when we do reach the token. 1024 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1025 if (!t.sendingToBottom && tokenWindowList.size() > 0) { 1026 pos = tokenWindowList.get(0); 1027 } 1028 } 1029 if (tokenNdx >= 0) { 1030 // early exit 1031 break; 1032 } 1033 } 1034 1035 // We now know the index into the apps. If we found 1036 // an app window above, that gives us the position; else 1037 // we need to look some more. 1038 if (pos != null) { 1039 // Move behind any windows attached to this one. 1040 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1041 if (atoken != null) { 1042 tokenWindowList = 1043 getTokenWindowsOnDisplay(atoken, displayContent); 1044 final int NC = tokenWindowList.size(); 1045 if (NC > 0) { 1046 WindowState bottom = tokenWindowList.get(0); 1047 if (bottom.mSubLayer < 0) { 1048 pos = bottom; 1049 } 1050 } 1051 } 1052 placeWindowBefore(pos, win); 1053 return tokenWindowsPos; 1054 } 1055 1056 // Continue looking down until we find the first 1057 // token that has windows on this display. 1058 for ( ; taskNdx >= 0; --taskNdx) { 1059 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1060 for ( ; tokenNdx >= 0; --tokenNdx) { 1061 final AppWindowToken t = tokens.get(tokenNdx); 1062 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1063 final int NW = tokenWindowList.size(); 1064 if (NW > 0) { 1065 pos = tokenWindowList.get(NW-1); 1066 break; 1067 } 1068 } 1069 if (tokenNdx >= 0) { 1070 // found 1071 break; 1072 } 1073 } 1074 1075 if (pos != null) { 1076 // Move in front of any windows attached to this 1077 // one. 1078 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1079 if (atoken != null) { 1080 final int NC = atoken.windows.size(); 1081 if (NC > 0) { 1082 WindowState top = atoken.windows.get(NC-1); 1083 if (top.mSubLayer >= 0) { 1084 pos = top; 1085 } 1086 } 1087 } 1088 placeWindowAfter(pos, win); 1089 return tokenWindowsPos; 1090 } 1091 1092 // Just search for the start of this layer. 1093 final int myLayer = win.mBaseLayer; 1094 int i; 1095 for (i = 0; i < N; i++) { 1096 WindowState w = windows.get(i); 1097 if (w.mBaseLayer > myLayer) { 1098 break; 1099 } 1100 } 1101 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1102 "Based on layer: Adding window " + win + " at " + i + " of " + N); 1103 windows.add(i, win); 1104 mWindowsChanged = true; 1105 return tokenWindowsPos; 1106 } 1107 1108 private void addFreeWindowToListLocked(final WindowState win) { 1109 final WindowList windows = win.getWindowList(); 1110 1111 // Figure out where window should go, based on layer. 1112 final int myLayer = win.mBaseLayer; 1113 int i; 1114 for (i = windows.size() - 1; i >= 0; i--) { 1115 if (windows.get(i).mBaseLayer <= myLayer) { 1116 break; 1117 } 1118 } 1119 i++; 1120 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1121 "Free window: Adding window " + win + " at " + i + " of " + windows.size()); 1122 windows.add(i, win); 1123 mWindowsChanged = true; 1124 } 1125 1126 private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) { 1127 final WindowToken token = win.mToken; 1128 final DisplayContent displayContent = win.getDisplayContent(); 1129 if (displayContent == null) { 1130 return; 1131 } 1132 final WindowState attached = win.mAttachedWindow; 1133 1134 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 1135 1136 // Figure out this window's ordering relative to the window 1137 // it is attached to. 1138 final int NA = tokenWindowList.size(); 1139 final int sublayer = win.mSubLayer; 1140 int largestSublayer = Integer.MIN_VALUE; 1141 WindowState windowWithLargestSublayer = null; 1142 int i; 1143 for (i = 0; i < NA; i++) { 1144 WindowState w = tokenWindowList.get(i); 1145 final int wSublayer = w.mSubLayer; 1146 if (wSublayer >= largestSublayer) { 1147 largestSublayer = wSublayer; 1148 windowWithLargestSublayer = w; 1149 } 1150 if (sublayer < 0) { 1151 // For negative sublayers, we go below all windows 1152 // in the same sublayer. 1153 if (wSublayer >= sublayer) { 1154 if (addToToken) { 1155 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1156 token.windows.add(i, win); 1157 } 1158 placeWindowBefore(wSublayer >= 0 ? attached : w, win); 1159 break; 1160 } 1161 } else { 1162 // For positive sublayers, we go above all windows 1163 // in the same sublayer. 1164 if (wSublayer > sublayer) { 1165 if (addToToken) { 1166 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1167 token.windows.add(i, win); 1168 } 1169 placeWindowBefore(w, win); 1170 break; 1171 } 1172 } 1173 } 1174 if (i >= NA) { 1175 if (addToToken) { 1176 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1177 token.windows.add(win); 1178 } 1179 if (sublayer < 0) { 1180 placeWindowBefore(attached, win); 1181 } else { 1182 placeWindowAfter(largestSublayer >= 0 1183 ? windowWithLargestSublayer 1184 : attached, 1185 win); 1186 } 1187 } 1188 } 1189 1190 private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) { 1191 if (DEBUG_FOCUS_LIGHT) Slog.d(TAG, "addWindowToListInOrderLocked: win=" + win + 1192 " Callers=" + Debug.getCallers(4)); 1193 if (win.mAttachedWindow == null) { 1194 final WindowToken token = win.mToken; 1195 int tokenWindowsPos = 0; 1196 if (token.appWindowToken != null) { 1197 tokenWindowsPos = addAppWindowToListLocked(win); 1198 } else { 1199 addFreeWindowToListLocked(win); 1200 } 1201 if (addToToken) { 1202 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1203 token.windows.add(tokenWindowsPos, win); 1204 } 1205 } else { 1206 addAttachedWindowToListLocked(win, addToToken); 1207 } 1208 1209 if (win.mAppToken != null && addToToken) { 1210 win.mAppToken.allAppWindows.add(win); 1211 } 1212 } 1213 1214 static boolean canBeImeTarget(WindowState w) { 1215 final int fl = w.mAttrs.flags 1216 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); 1217 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM) 1218 || w.mAttrs.type == TYPE_APPLICATION_STARTING) { 1219 if (DEBUG_INPUT_METHOD) { 1220 Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding()); 1221 if (!w.isVisibleOrAdding()) { 1222 Slog.i(TAG, " mSurface=" + w.mWinAnimator.mSurfaceControl 1223 + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility 1224 + " policyVis=" + w.mPolicyVisibility 1225 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim 1226 + " attachHid=" + w.mAttachedHidden 1227 + " exiting=" + w.mExiting + " destroying=" + w.mDestroying); 1228 if (w.mAppToken != null) { 1229 Slog.i(TAG, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested); 1230 } 1231 } 1232 } 1233 return w.isVisibleOrAdding(); 1234 } 1235 return false; 1236 } 1237 1238 /** 1239 * Dig through the WindowStates and find the one that the Input Method will target. 1240 * @param willMove 1241 * @return The index+1 in mWindows of the discovered target. 1242 */ 1243 int findDesiredInputMethodWindowIndexLocked(boolean willMove) { 1244 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the 1245 // same display. Or even when the current IME/target are not on the same screen as the next 1246 // IME/target. For now only look for input windows on the main screen. 1247 WindowList windows = getDefaultWindowListLocked(); 1248 WindowState w = null; 1249 int i; 1250 for (i = windows.size() - 1; i >= 0; --i) { 1251 WindowState win = windows.get(i); 1252 1253 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i 1254 + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags)); 1255 if (canBeImeTarget(win)) { 1256 w = win; 1257 //Slog.i(TAG, "Putting input method here!"); 1258 1259 // Yet more tricksyness! If this window is a "starting" 1260 // window, we do actually want to be on top of it, but 1261 // it is not -really- where input will go. So if the caller 1262 // is not actually looking to move the IME, look down below 1263 // for a real window to target... 1264 if (!willMove 1265 && w.mAttrs.type == TYPE_APPLICATION_STARTING 1266 && i > 0) { 1267 WindowState wb = windows.get(i-1); 1268 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) { 1269 i--; 1270 w = wb; 1271 } 1272 } 1273 break; 1274 } 1275 } 1276 1277 // Now w is either mWindows[0] or an IME (or null if mWindows is empty). 1278 1279 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w); 1280 1281 // Now, a special case -- if the last target's window is in the 1282 // process of exiting, and is above the new target, keep on the 1283 // last target to avoid flicker. Consider for example a Dialog with 1284 // the IME shown: when the Dialog is dismissed, we want to keep 1285 // the IME above it until it is completely gone so it doesn't drop 1286 // behind the dialog or its full-screen scrim. 1287 final WindowState curTarget = mInputMethodTarget; 1288 if (curTarget != null 1289 && curTarget.isDisplayedLw() 1290 && curTarget.isClosing() 1291 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) { 1292 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing"); 1293 return windows.indexOf(curTarget) + 1; 1294 } 1295 1296 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target=" 1297 + w + " willMove=" + willMove); 1298 1299 if (willMove && w != null) { 1300 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken; 1301 if (token != null) { 1302 1303 // Now some fun for dealing with window animations that 1304 // modify the Z order. We need to look at all windows below 1305 // the current target that are in this app, finding the highest 1306 // visible one in layering. 1307 WindowState highestTarget = null; 1308 int highestPos = 0; 1309 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) { 1310 WindowList curWindows = curTarget.getWindowList(); 1311 int pos = curWindows.indexOf(curTarget); 1312 while (pos >= 0) { 1313 WindowState win = curWindows.get(pos); 1314 if (win.mAppToken != token) { 1315 break; 1316 } 1317 if (!win.mRemoved) { 1318 if (highestTarget == null || win.mWinAnimator.mAnimLayer > 1319 highestTarget.mWinAnimator.mAnimLayer) { 1320 highestTarget = win; 1321 highestPos = pos; 1322 } 1323 } 1324 pos--; 1325 } 1326 } 1327 1328 if (highestTarget != null) { 1329 if (DEBUG_INPUT_METHOD) Slog.v(TAG, mAppTransition + " " + highestTarget 1330 + " animating=" + highestTarget.mWinAnimator.isAnimating() 1331 + " layer=" + highestTarget.mWinAnimator.mAnimLayer 1332 + " new layer=" + w.mWinAnimator.mAnimLayer); 1333 1334 if (mAppTransition.isTransitionSet()) { 1335 // If we are currently setting up for an animation, 1336 // hold everything until we can find out what will happen. 1337 mInputMethodTargetWaitingAnim = true; 1338 mInputMethodTarget = highestTarget; 1339 return highestPos + 1; 1340 } else if (highestTarget.mWinAnimator.isAnimating() && 1341 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) { 1342 // If the window we are currently targeting is involved 1343 // with an animation, and it is on top of the next target 1344 // we will be over, then hold off on moving until 1345 // that is done. 1346 mInputMethodTargetWaitingAnim = true; 1347 mInputMethodTarget = highestTarget; 1348 return highestPos + 1; 1349 } 1350 } 1351 } 1352 } 1353 1354 //Slog.i(TAG, "Placing input method @" + (i+1)); 1355 if (w != null) { 1356 if (willMove) { 1357 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to " 1358 + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4))); 1359 mInputMethodTarget = w; 1360 mInputMethodTargetWaitingAnim = false; 1361 if (w.mAppToken != null) { 1362 setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment); 1363 } else { 1364 setInputMethodAnimLayerAdjustment(0); 1365 } 1366 } 1367 return i+1; 1368 } 1369 if (willMove) { 1370 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null." 1371 + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4))); 1372 mInputMethodTarget = null; 1373 setInputMethodAnimLayerAdjustment(0); 1374 } 1375 return -1; 1376 } 1377 1378 void addInputMethodWindowToListLocked(WindowState win) { 1379 int pos = findDesiredInputMethodWindowIndexLocked(true); 1380 if (pos >= 0) { 1381 win.mTargetAppToken = mInputMethodTarget.mAppToken; 1382 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 1383 TAG, "Adding input method window " + win + " at " + pos); 1384 // TODO(multidisplay): IMEs are only supported on the default display. 1385 getDefaultWindowListLocked().add(pos, win); 1386 mWindowsChanged = true; 1387 moveInputMethodDialogsLocked(pos+1); 1388 return; 1389 } 1390 win.mTargetAppToken = null; 1391 addWindowToListInOrderLocked(win, true); 1392 moveInputMethodDialogsLocked(pos); 1393 } 1394 1395 void setInputMethodAnimLayerAdjustment(int adj) { 1396 if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj); 1397 mInputMethodAnimLayerAdjustment = adj; 1398 WindowState imw = mInputMethodWindow; 1399 if (imw != null) { 1400 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj; 1401 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw 1402 + " anim layer: " + imw.mWinAnimator.mAnimLayer); 1403 int wi = imw.mChildWindows.size(); 1404 while (wi > 0) { 1405 wi--; 1406 WindowState cw = imw.mChildWindows.get(wi); 1407 cw.mWinAnimator.mAnimLayer = cw.mLayer + adj; 1408 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw 1409 + " anim layer: " + cw.mWinAnimator.mAnimLayer); 1410 } 1411 } 1412 int di = mInputMethodDialogs.size(); 1413 while (di > 0) { 1414 di --; 1415 imw = mInputMethodDialogs.get(di); 1416 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj; 1417 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw 1418 + " anim layer: " + imw.mWinAnimator.mAnimLayer); 1419 } 1420 } 1421 1422 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) { 1423 WindowList windows = win.getWindowList(); 1424 int wpos = windows.indexOf(win); 1425 if (wpos >= 0) { 1426 if (wpos < interestingPos) interestingPos--; 1427 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win); 1428 windows.remove(wpos); 1429 mWindowsChanged = true; 1430 int NC = win.mChildWindows.size(); 1431 while (NC > 0) { 1432 NC--; 1433 WindowState cw = win.mChildWindows.get(NC); 1434 int cpos = windows.indexOf(cw); 1435 if (cpos >= 0) { 1436 if (cpos < interestingPos) interestingPos--; 1437 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at " 1438 + cpos + ": " + cw); 1439 windows.remove(cpos); 1440 } 1441 } 1442 } 1443 return interestingPos; 1444 } 1445 1446 private void reAddWindowToListInOrderLocked(WindowState win) { 1447 addWindowToListInOrderLocked(win, false); 1448 // This is a hack to get all of the child windows added as well 1449 // at the right position. Child windows should be rare and 1450 // this case should be rare, so it shouldn't be that big a deal. 1451 WindowList windows = win.getWindowList(); 1452 int wpos = windows.indexOf(win); 1453 if (wpos >= 0) { 1454 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win); 1455 windows.remove(wpos); 1456 mWindowsChanged = true; 1457 reAddWindowLocked(wpos, win); 1458 } 1459 } 1460 1461 void logWindowList(final WindowList windows, String prefix) { 1462 int N = windows.size(); 1463 while (N > 0) { 1464 N--; 1465 Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N)); 1466 } 1467 } 1468 1469 void moveInputMethodDialogsLocked(int pos) { 1470 ArrayList<WindowState> dialogs = mInputMethodDialogs; 1471 1472 // TODO(multidisplay): IMEs are only supported on the default display. 1473 WindowList windows = getDefaultWindowListLocked(); 1474 final int N = dialogs.size(); 1475 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos); 1476 for (int i=0; i<N; i++) { 1477 pos = tmpRemoveWindowLocked(pos, dialogs.get(i)); 1478 } 1479 if (DEBUG_INPUT_METHOD) { 1480 Slog.v(TAG, "Window list w/pos=" + pos); 1481 logWindowList(windows, " "); 1482 } 1483 1484 if (pos >= 0) { 1485 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken; 1486 // Skip windows owned by the input method. 1487 if (mInputMethodWindow != null) { 1488 while (pos < windows.size()) { 1489 WindowState wp = windows.get(pos); 1490 if (wp == mInputMethodWindow || wp.mAttachedWindow == mInputMethodWindow) { 1491 pos++; 1492 continue; 1493 } 1494 break; 1495 } 1496 } 1497 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos); 1498 for (int i=0; i<N; i++) { 1499 WindowState win = dialogs.get(i); 1500 win.mTargetAppToken = targetAppToken; 1501 pos = reAddWindowLocked(pos, win); 1502 } 1503 if (DEBUG_INPUT_METHOD) { 1504 Slog.v(TAG, "Final window list:"); 1505 logWindowList(windows, " "); 1506 } 1507 return; 1508 } 1509 for (int i=0; i<N; i++) { 1510 WindowState win = dialogs.get(i); 1511 win.mTargetAppToken = null; 1512 reAddWindowToListInOrderLocked(win); 1513 if (DEBUG_INPUT_METHOD) { 1514 Slog.v(TAG, "No IM target, final list:"); 1515 logWindowList(windows, " "); 1516 } 1517 } 1518 } 1519 1520 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) { 1521 final WindowState imWin = mInputMethodWindow; 1522 final int DN = mInputMethodDialogs.size(); 1523 if (imWin == null && DN == 0) { 1524 return false; 1525 } 1526 1527 // TODO(multidisplay): IMEs are only supported on the default display. 1528 WindowList windows = getDefaultWindowListLocked(); 1529 1530 int imPos = findDesiredInputMethodWindowIndexLocked(true); 1531 if (imPos >= 0) { 1532 // In this case, the input method windows are to be placed 1533 // immediately above the window they are targeting. 1534 1535 // First check to see if the input method windows are already 1536 // located here, and contiguous. 1537 final int N = windows.size(); 1538 WindowState firstImWin = imPos < N 1539 ? windows.get(imPos) : null; 1540 1541 // Figure out the actual input method window that should be 1542 // at the bottom of their stack. 1543 WindowState baseImWin = imWin != null 1544 ? imWin : mInputMethodDialogs.get(0); 1545 if (baseImWin.mChildWindows.size() > 0) { 1546 WindowState cw = baseImWin.mChildWindows.get(0); 1547 if (cw.mSubLayer < 0) baseImWin = cw; 1548 } 1549 1550 if (firstImWin == baseImWin) { 1551 // The windows haven't moved... but are they still contiguous? 1552 // First find the top IM window. 1553 int pos = imPos+1; 1554 while (pos < N) { 1555 if (!(windows.get(pos)).mIsImWindow) { 1556 break; 1557 } 1558 pos++; 1559 } 1560 pos++; 1561 // Now there should be no more input method windows above. 1562 while (pos < N) { 1563 if ((windows.get(pos)).mIsImWindow) { 1564 break; 1565 } 1566 pos++; 1567 } 1568 if (pos >= N) { 1569 // Z order is good. 1570 // The IM target window may be changed, so update the mTargetAppToken. 1571 if (imWin != null) { 1572 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1573 } 1574 return false; 1575 } 1576 } 1577 1578 if (imWin != null) { 1579 if (DEBUG_INPUT_METHOD) { 1580 Slog.v(TAG, "Moving IM from " + imPos); 1581 logWindowList(windows, " "); 1582 } 1583 imPos = tmpRemoveWindowLocked(imPos, imWin); 1584 if (DEBUG_INPUT_METHOD) { 1585 Slog.v(TAG, "List after removing with new pos " + imPos + ":"); 1586 logWindowList(windows, " "); 1587 } 1588 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1589 reAddWindowLocked(imPos, imWin); 1590 if (DEBUG_INPUT_METHOD) { 1591 Slog.v(TAG, "List after moving IM to " + imPos + ":"); 1592 logWindowList(windows, " "); 1593 } 1594 if (DN > 0) moveInputMethodDialogsLocked(imPos+1); 1595 } else { 1596 moveInputMethodDialogsLocked(imPos); 1597 } 1598 1599 } else { 1600 // In this case, the input method windows go in a fixed layer, 1601 // because they aren't currently associated with a focus window. 1602 1603 if (imWin != null) { 1604 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos); 1605 tmpRemoveWindowLocked(0, imWin); 1606 imWin.mTargetAppToken = null; 1607 reAddWindowToListInOrderLocked(imWin); 1608 if (DEBUG_INPUT_METHOD) { 1609 Slog.v(TAG, "List with no IM target:"); 1610 logWindowList(windows, " "); 1611 } 1612 if (DN > 0) moveInputMethodDialogsLocked(-1); 1613 } else { 1614 moveInputMethodDialogsLocked(-1); 1615 } 1616 1617 } 1618 1619 if (needAssignLayers) { 1620 assignLayersLocked(windows); 1621 } 1622 1623 return true; 1624 } 1625 1626 final boolean isWallpaperVisible(WindowState wallpaperTarget) { 1627 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured=" 1628 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??") 1629 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null) 1630 ? wallpaperTarget.mAppToken.mAppAnimator.animation : null) 1631 + " upper=" + mUpperWallpaperTarget 1632 + " lower=" + mLowerWallpaperTarget); 1633 return (wallpaperTarget != null 1634 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null 1635 && wallpaperTarget.mAppToken.mAppAnimator.animation != null))) 1636 || mUpperWallpaperTarget != null 1637 || mLowerWallpaperTarget != null; 1638 } 1639 1640 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1; 1641 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2; 1642 1643 int adjustWallpaperWindowsLocked() { 1644 mInnerFields.mWallpaperMayChange = false; 1645 boolean targetChanged = false; 1646 1647 // TODO(multidisplay): Wallpapers on main screen only. 1648 final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo(); 1649 final int dw = displayInfo.logicalWidth; 1650 final int dh = displayInfo.logicalHeight; 1651 1652 // First find top-most window that has asked to be on top of the 1653 // wallpaper; all wallpapers go behind it. 1654 final WindowList windows = getDefaultWindowListLocked(); 1655 int N = windows.size(); 1656 WindowState w = null; 1657 WindowState foundW = null; 1658 int foundI = 0; 1659 WindowState topCurW = null; 1660 int topCurI = 0; 1661 int windowDetachedI = -1; 1662 int i = N; 1663 while (i > 0) { 1664 i--; 1665 w = windows.get(i); 1666 if ((w.mAttrs.type == TYPE_WALLPAPER)) { 1667 if (topCurW == null) { 1668 topCurW = w; 1669 topCurI = i; 1670 } 1671 continue; 1672 } 1673 topCurW = null; 1674 if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) { 1675 // If this window's app token is hidden and not animating, 1676 // it is of no interest to us. 1677 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) { 1678 if (DEBUG_WALLPAPER) Slog.v(TAG, 1679 "Skipping hidden and not animating token: " + w); 1680 continue; 1681 } 1682 } 1683 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen=" 1684 + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState); 1685 if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isOnScreen() 1686 && (mWallpaperTarget == w || w.isDrawFinishedLw())) { 1687 if (DEBUG_WALLPAPER) Slog.v(TAG, 1688 "Found wallpaper target: #" + i + "=" + w); 1689 foundW = w; 1690 foundI = i; 1691 if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) { 1692 // The current wallpaper target is animating, so we'll 1693 // look behind it for another possible target and figure 1694 // out what is going on below. 1695 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w 1696 + ": token animating, looking behind."); 1697 continue; 1698 } 1699 break; 1700 } else if (w == mAnimator.mWindowDetachedWallpaper) { 1701 windowDetachedI = i; 1702 } 1703 } 1704 1705 if (foundW == null && windowDetachedI >= 0) { 1706 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 1707 "Found animating detached wallpaper activity: #" + i + "=" + w); 1708 foundW = w; 1709 foundI = windowDetachedI; 1710 } 1711 1712 if (mWallpaperTarget != foundW 1713 && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) { 1714 if (DEBUG_WALLPAPER_LIGHT) { 1715 Slog.v(TAG, "New wallpaper target: " + foundW 1716 + " oldTarget: " + mWallpaperTarget); 1717 } 1718 1719 mLowerWallpaperTarget = null; 1720 mUpperWallpaperTarget = null; 1721 1722 WindowState oldW = mWallpaperTarget; 1723 mWallpaperTarget = foundW; 1724 targetChanged = true; 1725 1726 // Now what is happening... if the current and new targets are 1727 // animating, then we are in our super special mode! 1728 if (foundW != null && oldW != null) { 1729 boolean oldAnim = oldW.isAnimatingLw(); 1730 boolean foundAnim = foundW.isAnimatingLw(); 1731 if (DEBUG_WALLPAPER_LIGHT) { 1732 Slog.v(TAG, "New animation: " + foundAnim 1733 + " old animation: " + oldAnim); 1734 } 1735 if (foundAnim && oldAnim) { 1736 int oldI = windows.indexOf(oldW); 1737 if (DEBUG_WALLPAPER_LIGHT) { 1738 Slog.v(TAG, "New i: " + foundI + " old i: " + oldI); 1739 } 1740 if (oldI >= 0) { 1741 if (DEBUG_WALLPAPER_LIGHT) { 1742 Slog.v(TAG, "Animating wallpapers: old#" + oldI 1743 + "=" + oldW + "; new#" + foundI 1744 + "=" + foundW); 1745 } 1746 1747 // Set the new target correctly. 1748 if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) { 1749 if (DEBUG_WALLPAPER_LIGHT) { 1750 Slog.v(TAG, "Old wallpaper still the target."); 1751 } 1752 mWallpaperTarget = oldW; 1753 foundW = oldW; 1754 foundI = oldI; 1755 } 1756 // Now set the upper and lower wallpaper targets 1757 // correctly, and make sure that we are positioning 1758 // the wallpaper below the lower. 1759 else if (foundI > oldI) { 1760 // The new target is on top of the old one. 1761 if (DEBUG_WALLPAPER_LIGHT) { 1762 Slog.v(TAG, "Found target above old target."); 1763 } 1764 mUpperWallpaperTarget = foundW; 1765 mLowerWallpaperTarget = oldW; 1766 foundW = oldW; 1767 foundI = oldI; 1768 } else { 1769 // The new target is below the old one. 1770 if (DEBUG_WALLPAPER_LIGHT) { 1771 Slog.v(TAG, "Found target below old target."); 1772 } 1773 mUpperWallpaperTarget = oldW; 1774 mLowerWallpaperTarget = foundW; 1775 } 1776 } 1777 } 1778 } 1779 1780 } else if (mLowerWallpaperTarget != null) { 1781 // Is it time to stop animating? 1782 if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) { 1783 if (DEBUG_WALLPAPER_LIGHT) { 1784 Slog.v(TAG, "No longer animating wallpaper targets!"); 1785 } 1786 mLowerWallpaperTarget = null; 1787 mUpperWallpaperTarget = null; 1788 mWallpaperTarget = foundW; 1789 targetChanged = true; 1790 } 1791 } 1792 1793 boolean visible = foundW != null; 1794 if (visible) { 1795 // The window is visible to the compositor... but is it visible 1796 // to the user? That is what the wallpaper cares about. 1797 visible = isWallpaperVisible(foundW); 1798 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible); 1799 1800 // If the wallpaper target is animating, we may need to copy 1801 // its layer adjustment. Only do this if we are not transfering 1802 // between two wallpaper targets. 1803 mWallpaperAnimLayerAdjustment = 1804 (mLowerWallpaperTarget == null && foundW.mAppToken != null) 1805 ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0; 1806 1807 final int maxLayer = mPolicy.getMaxWallpaperLayer() 1808 * TYPE_LAYER_MULTIPLIER 1809 + TYPE_LAYER_OFFSET; 1810 1811 // Now w is the window we are supposed to be behind... but we 1812 // need to be sure to also be behind any of its attached windows, 1813 // AND any starting window associated with it, AND below the 1814 // maximum layer the policy allows for wallpapers. 1815 while (foundI > 0) { 1816 WindowState wb = windows.get(foundI-1); 1817 if (wb.mBaseLayer < maxLayer && 1818 wb.mAttachedWindow != foundW && 1819 (foundW.mAttachedWindow == null || 1820 wb.mAttachedWindow != foundW.mAttachedWindow) && 1821 (wb.mAttrs.type != TYPE_APPLICATION_STARTING || 1822 foundW.mToken == null || wb.mToken != foundW.mToken)) { 1823 // This window is not related to the previous one in any 1824 // interesting way, so stop here. 1825 break; 1826 } 1827 foundW = wb; 1828 foundI--; 1829 } 1830 } else { 1831 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target"); 1832 } 1833 1834 if (foundW == null && topCurW != null) { 1835 // There is no wallpaper target, so it goes at the bottom. 1836 // We will assume it is the same place as last time, if known. 1837 foundW = topCurW; 1838 foundI = topCurI+1; 1839 } else { 1840 // Okay i is the position immediately above the wallpaper. Look at 1841 // what is below it for later. 1842 foundW = foundI > 0 ? windows.get(foundI-1) : null; 1843 } 1844 1845 if (visible) { 1846 if (mWallpaperTarget.mWallpaperX >= 0) { 1847 mLastWallpaperX = mWallpaperTarget.mWallpaperX; 1848 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep; 1849 } 1850 if (mWallpaperTarget.mWallpaperY >= 0) { 1851 mLastWallpaperY = mWallpaperTarget.mWallpaperY; 1852 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep; 1853 } 1854 } 1855 1856 // Start stepping backwards from here, ensuring that our wallpaper windows 1857 // are correctly placed. 1858 int changed = 0; 1859 int curTokenIndex = mWallpaperTokens.size(); 1860 while (curTokenIndex > 0) { 1861 curTokenIndex--; 1862 WindowToken token = mWallpaperTokens.get(curTokenIndex); 1863 if (token.hidden == visible) { 1864 if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, 1865 "Wallpaper token " + token + " hidden=" + !visible); 1866 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED; 1867 token.hidden = !visible; 1868 // Need to do a layout to ensure the wallpaper now has the 1869 // correct size. 1870 getDefaultDisplayContentLocked().layoutNeeded = true; 1871 } 1872 1873 int curWallpaperIndex = token.windows.size(); 1874 while (curWallpaperIndex > 0) { 1875 curWallpaperIndex--; 1876 WindowState wallpaper = token.windows.get(curWallpaperIndex); 1877 1878 if (visible) { 1879 updateWallpaperOffsetLocked(wallpaper, dw, dh, false); 1880 } 1881 1882 // First, make sure the client has the current visibility 1883 // state. 1884 dispatchWallpaperVisibility(wallpaper, visible); 1885 1886 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment; 1887 if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win " 1888 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); 1889 1890 // First, if this window is at the current index, then all 1891 // is well. 1892 if (wallpaper == foundW) { 1893 foundI--; 1894 foundW = foundI > 0 1895 ? windows.get(foundI-1) : null; 1896 continue; 1897 } 1898 1899 // The window didn't match... the current wallpaper window, 1900 // wherever it is, is in the wrong place, so make sure it is 1901 // not in the list. 1902 int oldIndex = windows.indexOf(wallpaper); 1903 if (oldIndex >= 0) { 1904 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at " 1905 + oldIndex + ": " + wallpaper); 1906 windows.remove(oldIndex); 1907 mWindowsChanged = true; 1908 if (oldIndex < foundI) { 1909 foundI--; 1910 } 1911 } 1912 1913 // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost 1914 // layer. For keyguard over wallpaper put the wallpaper under the keyguard. 1915 int insertionIndex = 0; 1916 if (visible && foundW != null) { 1917 final int type = foundW.mAttrs.type; 1918 final int privateFlags = foundW.mAttrs.privateFlags; 1919 if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 1920 || type == TYPE_KEYGUARD_SCRIM) { 1921 insertionIndex = windows.indexOf(foundW); 1922 } 1923 } 1924 if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) { 1925 Slog.v(TAG, "Moving wallpaper " + wallpaper 1926 + " from " + oldIndex + " to " + insertionIndex); 1927 } 1928 1929 windows.add(insertionIndex, wallpaper); 1930 mWindowsChanged = true; 1931 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED; 1932 } 1933 } 1934 1935 /* 1936 final TaskStack targetStack = 1937 mWallpaperTarget == null ? null : mWallpaperTarget.getStack(); 1938 if ((changed & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0 && 1939 targetStack != null && !targetStack.isHomeStack()) { 1940 // If the wallpaper target is not on the home stack then make sure that all windows 1941 // from other non-home stacks are above the wallpaper. 1942 for (i = foundI - 1; i >= 0; --i) { 1943 WindowState win = windows.get(i); 1944 if (!win.isVisibleLw()) { 1945 continue; 1946 } 1947 final TaskStack winStack = win.getStack(); 1948 if (winStack != null && !winStack.isHomeStack() && winStack != targetStack) { 1949 windows.remove(i); 1950 windows.add(foundI + 1, win); 1951 } 1952 } 1953 } 1954 */ 1955 1956 if (targetChanged && DEBUG_WALLPAPER_LIGHT) { 1957 Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget 1958 + " lower=" + mLowerWallpaperTarget + " upper=" 1959 + mUpperWallpaperTarget); 1960 } 1961 1962 return changed; 1963 } 1964 1965 void setWallpaperAnimLayerAdjustmentLocked(int adj) { 1966 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, 1967 "Setting wallpaper layer adj to " + adj); 1968 mWallpaperAnimLayerAdjustment = adj; 1969 int curTokenIndex = mWallpaperTokens.size(); 1970 while (curTokenIndex > 0) { 1971 curTokenIndex--; 1972 WindowToken token = mWallpaperTokens.get(curTokenIndex); 1973 int curWallpaperIndex = token.windows.size(); 1974 while (curWallpaperIndex > 0) { 1975 curWallpaperIndex--; 1976 WindowState wallpaper = token.windows.get(curWallpaperIndex); 1977 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj; 1978 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win " 1979 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); 1980 } 1981 } 1982 } 1983 1984 boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh, 1985 boolean sync) { 1986 boolean changed = false; 1987 boolean rawChanged = false; 1988 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f; 1989 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f; 1990 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw; 1991 int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0; 1992 changed = wallpaperWin.mXOffset != offset; 1993 if (changed) { 1994 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " 1995 + wallpaperWin + " x: " + offset); 1996 wallpaperWin.mXOffset = offset; 1997 } 1998 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) { 1999 wallpaperWin.mWallpaperX = wpx; 2000 wallpaperWin.mWallpaperXStep = wpxs; 2001 rawChanged = true; 2002 } 2003 2004 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f; 2005 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f; 2006 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh; 2007 offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0; 2008 if (wallpaperWin.mYOffset != offset) { 2009 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " 2010 + wallpaperWin + " y: " + offset); 2011 changed = true; 2012 wallpaperWin.mYOffset = offset; 2013 } 2014 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) { 2015 wallpaperWin.mWallpaperY = wpy; 2016 wallpaperWin.mWallpaperYStep = wpys; 2017 rawChanged = true; 2018 } 2019 2020 if (rawChanged && (wallpaperWin.mAttrs.privateFlags & 2021 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) { 2022 try { 2023 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset " 2024 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX 2025 + " y=" + wallpaperWin.mWallpaperY); 2026 if (sync) { 2027 mWaitingOnWallpaper = wallpaperWin; 2028 } 2029 wallpaperWin.mClient.dispatchWallpaperOffsets( 2030 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY, 2031 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync); 2032 if (sync) { 2033 if (mWaitingOnWallpaper != null) { 2034 long start = SystemClock.uptimeMillis(); 2035 if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY) 2036 < start) { 2037 try { 2038 if (DEBUG_WALLPAPER) Slog.v(TAG, 2039 "Waiting for offset complete..."); 2040 mWindowMap.wait(WALLPAPER_TIMEOUT); 2041 } catch (InterruptedException e) { 2042 } 2043 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!"); 2044 if ((start+WALLPAPER_TIMEOUT) 2045 < SystemClock.uptimeMillis()) { 2046 Slog.i(TAG, "Timeout waiting for wallpaper to offset: " 2047 + wallpaperWin); 2048 mLastWallpaperTimeoutTime = start; 2049 } 2050 } 2051 mWaitingOnWallpaper = null; 2052 } 2053 } 2054 } catch (RemoteException e) { 2055 } 2056 } 2057 2058 return changed; 2059 } 2060 2061 void wallpaperOffsetsComplete(IBinder window) { 2062 synchronized (mWindowMap) { 2063 if (mWaitingOnWallpaper != null && 2064 mWaitingOnWallpaper.mClient.asBinder() == window) { 2065 mWaitingOnWallpaper = null; 2066 mWindowMap.notifyAll(); 2067 } 2068 } 2069 } 2070 2071 void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) { 2072 final DisplayContent displayContent = changingTarget.getDisplayContent(); 2073 if (displayContent == null) { 2074 return; 2075 } 2076 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2077 final int dw = displayInfo.logicalWidth; 2078 final int dh = displayInfo.logicalHeight; 2079 2080 WindowState target = mWallpaperTarget; 2081 if (target != null) { 2082 if (target.mWallpaperX >= 0) { 2083 mLastWallpaperX = target.mWallpaperX; 2084 } else if (changingTarget.mWallpaperX >= 0) { 2085 mLastWallpaperX = changingTarget.mWallpaperX; 2086 } 2087 if (target.mWallpaperY >= 0) { 2088 mLastWallpaperY = target.mWallpaperY; 2089 } else if (changingTarget.mWallpaperY >= 0) { 2090 mLastWallpaperY = changingTarget.mWallpaperY; 2091 } 2092 } 2093 2094 int curTokenIndex = mWallpaperTokens.size(); 2095 while (curTokenIndex > 0) { 2096 curTokenIndex--; 2097 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2098 int curWallpaperIndex = token.windows.size(); 2099 while (curWallpaperIndex > 0) { 2100 curWallpaperIndex--; 2101 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2102 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) { 2103 WindowStateAnimator winAnimator = wallpaper.mWinAnimator; 2104 winAnimator.computeShownFrameLocked(); 2105 // No need to lay out the windows - we can just set the wallpaper position 2106 // directly. 2107 winAnimator.setWallpaperOffset(wallpaper.mShownFrame); 2108 // We only want to be synchronous with one wallpaper. 2109 sync = false; 2110 } 2111 } 2112 } 2113 } 2114 2115 /** 2116 * Check wallpaper for visiblity change and notify window if so. 2117 * @param wallpaper The wallpaper to test and notify. 2118 * @param visible Current visibility. 2119 */ 2120 void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) { 2121 if (wallpaper.mWallpaperVisible != visible) { 2122 wallpaper.mWallpaperVisible = visible; 2123 try { 2124 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 2125 "Updating vis of wallpaper " + wallpaper 2126 + ": " + visible + " from:\n" + Debug.getCallers(4, " ")); 2127 wallpaper.mClient.dispatchAppVisibility(visible); 2128 } catch (RemoteException e) { 2129 } 2130 } 2131 } 2132 2133 void updateWallpaperVisibilityLocked() { 2134 final boolean visible = isWallpaperVisible(mWallpaperTarget); 2135 final DisplayContent displayContent = mWallpaperTarget.getDisplayContent(); 2136 if (displayContent == null) { 2137 return; 2138 } 2139 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2140 final int dw = displayInfo.logicalWidth; 2141 final int dh = displayInfo.logicalHeight; 2142 2143 int curTokenIndex = mWallpaperTokens.size(); 2144 while (curTokenIndex > 0) { 2145 curTokenIndex--; 2146 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2147 if (token.hidden == visible) { 2148 token.hidden = !visible; 2149 // Need to do a layout to ensure the wallpaper now has the 2150 // correct size. 2151 getDefaultDisplayContentLocked().layoutNeeded = true; 2152 } 2153 2154 int curWallpaperIndex = token.windows.size(); 2155 while (curWallpaperIndex > 0) { 2156 curWallpaperIndex--; 2157 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2158 if (visible) { 2159 updateWallpaperOffsetLocked(wallpaper, dw, dh, false); 2160 } 2161 2162 dispatchWallpaperVisibility(wallpaper, visible); 2163 } 2164 } 2165 } 2166 2167 public int addWindow(Session session, IWindow client, int seq, 2168 WindowManager.LayoutParams attrs, int viewVisibility, int displayId, 2169 Rect outContentInsets, InputChannel outInputChannel) { 2170 int[] appOp = new int[1]; 2171 int res = mPolicy.checkAddPermission(attrs, appOp); 2172 if (res != WindowManagerGlobal.ADD_OKAY) { 2173 return res; 2174 } 2175 2176 boolean reportNewConfig = false; 2177 WindowState attachedWindow = null; 2178 WindowState win = null; 2179 long origId; 2180 final int type = attrs.type; 2181 2182 synchronized(mWindowMap) { 2183 if (!mDisplayReady) { 2184 throw new IllegalStateException("Display has not been initialialized"); 2185 } 2186 2187 final DisplayContent displayContent = getDisplayContentLocked(displayId); 2188 if (displayContent == null) { 2189 Slog.w(TAG, "Attempted to add window to a display that does not exist: " 2190 + displayId + ". Aborting."); 2191 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2192 } 2193 if (!displayContent.hasAccess(session.mUid)) { 2194 Slog.w(TAG, "Attempted to add window to a display for which the application " 2195 + "does not have access: " + displayId + ". Aborting."); 2196 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2197 } 2198 2199 if (mWindowMap.containsKey(client.asBinder())) { 2200 Slog.w(TAG, "Window " + client + " is already added"); 2201 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 2202 } 2203 2204 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) { 2205 attachedWindow = windowForClientLocked(null, attrs.token, false); 2206 if (attachedWindow == null) { 2207 Slog.w(TAG, "Attempted to add window with token that is not a window: " 2208 + attrs.token + ". Aborting."); 2209 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 2210 } 2211 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW 2212 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) { 2213 Slog.w(TAG, "Attempted to add window with token that is a sub-window: " 2214 + attrs.token + ". Aborting."); 2215 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 2216 } 2217 } 2218 2219 if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) { 2220 Slog.w(TAG, "Attempted to add private presentation window to a non-private display. Aborting."); 2221 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 2222 } 2223 2224 boolean addToken = false; 2225 WindowToken token = mTokenMap.get(attrs.token); 2226 if (token == null) { 2227 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2228 Slog.w(TAG, "Attempted to add application window with unknown token " 2229 + attrs.token + ". Aborting."); 2230 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2231 } 2232 if (type == TYPE_INPUT_METHOD) { 2233 Slog.w(TAG, "Attempted to add input method window with unknown token " 2234 + attrs.token + ". Aborting."); 2235 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2236 } 2237 if (type == TYPE_VOICE_INTERACTION) { 2238 Slog.w(TAG, "Attempted to add voice interaction window with unknown token " 2239 + attrs.token + ". Aborting."); 2240 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2241 } 2242 if (type == TYPE_WALLPAPER) { 2243 Slog.w(TAG, "Attempted to add wallpaper window with unknown token " 2244 + attrs.token + ". Aborting."); 2245 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2246 } 2247 if (type == TYPE_DREAM) { 2248 Slog.w(TAG, "Attempted to add Dream window with unknown token " 2249 + attrs.token + ". Aborting."); 2250 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2251 } 2252 token = new WindowToken(this, attrs.token, -1, false); 2253 addToken = true; 2254 } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2255 AppWindowToken atoken = token.appWindowToken; 2256 if (atoken == null) { 2257 Slog.w(TAG, "Attempted to add window with non-application token " 2258 + token + ". Aborting."); 2259 return WindowManagerGlobal.ADD_NOT_APP_TOKEN; 2260 } else if (atoken.removed) { 2261 Slog.w(TAG, "Attempted to add window with exiting application token " 2262 + token + ". Aborting."); 2263 return WindowManagerGlobal.ADD_APP_EXITING; 2264 } 2265 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) { 2266 // No need for this guy! 2267 if (localLOGV) Slog.v( 2268 TAG, "**** NO NEED TO START: " + attrs.getTitle()); 2269 return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED; 2270 } 2271 } else if (type == TYPE_INPUT_METHOD) { 2272 if (token.windowType != TYPE_INPUT_METHOD) { 2273 Slog.w(TAG, "Attempted to add input method window with bad token " 2274 + attrs.token + ". Aborting."); 2275 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2276 } 2277 } else if (type == TYPE_VOICE_INTERACTION) { 2278 if (token.windowType != TYPE_VOICE_INTERACTION) { 2279 Slog.w(TAG, "Attempted to add voice interaction window with bad token " 2280 + attrs.token + ". Aborting."); 2281 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2282 } 2283 } else if (type == TYPE_WALLPAPER) { 2284 if (token.windowType != TYPE_WALLPAPER) { 2285 Slog.w(TAG, "Attempted to add wallpaper window with bad token " 2286 + attrs.token + ". Aborting."); 2287 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2288 } 2289 } else if (type == TYPE_DREAM) { 2290 if (token.windowType != TYPE_DREAM) { 2291 Slog.w(TAG, "Attempted to add Dream window with bad token " 2292 + attrs.token + ". Aborting."); 2293 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2294 } 2295 } 2296 2297 win = new WindowState(this, session, client, token, 2298 attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent); 2299 if (win.mDeathRecipient == null) { 2300 // Client has apparently died, so there is no reason to 2301 // continue. 2302 Slog.w(TAG, "Adding window client " + client.asBinder() 2303 + " that is dead, aborting."); 2304 return WindowManagerGlobal.ADD_APP_EXITING; 2305 } 2306 2307 if (win.getDisplayContent() == null) { 2308 Slog.w(TAG, "Adding window to Display that has been removed."); 2309 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2310 } 2311 2312 mPolicy.adjustWindowParamsLw(win.mAttrs); 2313 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs)); 2314 2315 res = mPolicy.prepareAddWindowLw(win, attrs); 2316 if (res != WindowManagerGlobal.ADD_OKAY) { 2317 return res; 2318 } 2319 2320 if (outInputChannel != null && (attrs.inputFeatures 2321 & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) { 2322 String name = win.makeInputChannelName(); 2323 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); 2324 win.setInputChannel(inputChannels[0]); 2325 inputChannels[1].transferTo(outInputChannel); 2326 2327 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle); 2328 } 2329 2330 // From now on, no exceptions or errors allowed! 2331 2332 res = WindowManagerGlobal.ADD_OKAY; 2333 2334 origId = Binder.clearCallingIdentity(); 2335 2336 if (addToken) { 2337 mTokenMap.put(attrs.token, token); 2338 } 2339 win.attach(); 2340 mWindowMap.put(client.asBinder(), win); 2341 if (win.mAppOp != AppOpsManager.OP_NONE) { 2342 if (mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage()) 2343 != AppOpsManager.MODE_ALLOWED) { 2344 win.setAppOpVisibilityLw(false); 2345 } 2346 } 2347 2348 if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) { 2349 token.appWindowToken.startingWindow = win; 2350 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken 2351 + " startingWindow=" + win); 2352 } 2353 2354 boolean imMayMove = true; 2355 2356 if (type == TYPE_INPUT_METHOD) { 2357 win.mGivenInsetsPending = true; 2358 mInputMethodWindow = win; 2359 addInputMethodWindowToListLocked(win); 2360 imMayMove = false; 2361 } else if (type == TYPE_INPUT_METHOD_DIALOG) { 2362 mInputMethodDialogs.add(win); 2363 addWindowToListInOrderLocked(win, true); 2364 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true)); 2365 imMayMove = false; 2366 } else { 2367 addWindowToListInOrderLocked(win, true); 2368 if (type == TYPE_WALLPAPER) { 2369 mLastWallpaperTimeoutTime = 0; 2370 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2371 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2372 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2373 } else if (mWallpaperTarget != null 2374 && mWallpaperTarget.mLayer >= win.mBaseLayer) { 2375 // If there is currently a wallpaper being shown, and 2376 // the base layer of the new window is below the current 2377 // layer of the target window, then adjust the wallpaper. 2378 // This is to avoid a new window being placed between the 2379 // wallpaper and its target. 2380 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2381 } 2382 } 2383 2384 win.mWinAnimator.mEnterAnimationPending = true; 2385 2386 if (displayContent.isDefaultDisplay) { 2387 mPolicy.getContentInsetHintLw(attrs, outContentInsets); 2388 } else { 2389 outContentInsets.setEmpty(); 2390 } 2391 2392 if (mInTouchMode) { 2393 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE; 2394 } 2395 if (win.mAppToken == null || !win.mAppToken.clientHidden) { 2396 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE; 2397 } 2398 2399 mInputMonitor.setUpdateInputWindowsNeededLw(); 2400 2401 boolean focusChanged = false; 2402 if (win.canReceiveKeys()) { 2403 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, 2404 false /*updateInputWindows*/); 2405 if (focusChanged) { 2406 imMayMove = false; 2407 } 2408 } 2409 2410 if (imMayMove) { 2411 moveInputMethodWindowsIfNeededLocked(false); 2412 } 2413 2414 assignLayersLocked(displayContent.getWindowList()); 2415 // Don't do layout here, the window must call 2416 // relayout to be displayed, so we'll do it there. 2417 2418 if (focusChanged) { 2419 finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/); 2420 } 2421 mInputMonitor.updateInputWindowsLw(false /*force*/); 2422 2423 if (localLOGV) Slog.v( 2424 TAG, "New client " + client.asBinder() 2425 + ": window=" + win); 2426 2427 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) { 2428 reportNewConfig = true; 2429 } 2430 } 2431 2432 if (reportNewConfig) { 2433 sendNewConfiguration(); 2434 } 2435 2436 Binder.restoreCallingIdentity(origId); 2437 2438 return res; 2439 } 2440 2441 public void removeWindow(Session session, IWindow client) { 2442 synchronized(mWindowMap) { 2443 WindowState win = windowForClientLocked(session, client, false); 2444 if (win == null) { 2445 return; 2446 } 2447 removeWindowLocked(session, win); 2448 } 2449 } 2450 2451 public void removeWindowLocked(Session session, WindowState win) { 2452 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2453 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Starting window removed " + win); 2454 } 2455 2456 if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v( 2457 TAG, "Remove " + win + " client=" 2458 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder())) 2459 + ", surface=" + win.mWinAnimator.mSurfaceControl + " Callers=" 2460 + Debug.getCallers(4)); 2461 2462 final long origId = Binder.clearCallingIdentity(); 2463 2464 win.disposeInputChannel(); 2465 2466 if (DEBUG_APP_TRANSITIONS) Slog.v( 2467 TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurfaceControl 2468 + " mExiting=" + win.mExiting 2469 + " isAnimating=" + win.mWinAnimator.isAnimating() 2470 + " app-animation=" 2471 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null) 2472 + " inPendingTransaction=" 2473 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false) 2474 + " mDisplayFrozen=" + mDisplayFrozen); 2475 // Visibility of the removed window. Will be used later to update orientation later on. 2476 boolean wasVisible = false; 2477 // First, see if we need to run an animation. If we do, we have 2478 // to hold off on removing the window until the animation is done. 2479 // If the display is frozen, just remove immediately, since the 2480 // animation wouldn't be seen. 2481 if (win.mHasSurface && okToDisplay()) { 2482 // If we are not currently running the exit animation, we 2483 // need to see about starting one. 2484 wasVisible = win.isWinVisibleLw(); 2485 if (wasVisible) { 2486 2487 int transit = WindowManagerPolicy.TRANSIT_EXIT; 2488 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2489 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 2490 } 2491 // Try starting an animation. 2492 if (win.mWinAnimator.applyAnimationLocked(transit, false)) { 2493 win.mExiting = true; 2494 } 2495 //TODO (multidisplay): Magnification is supported only for the default display. 2496 if (mAccessibilityController != null 2497 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 2498 mAccessibilityController.onWindowTransitionLocked(win, transit); 2499 } 2500 } 2501 if (win.mExiting || win.mWinAnimator.isAnimating()) { 2502 // The exit animation is running... wait for it! 2503 //Slog.i(TAG, "*** Running exit animation..."); 2504 win.mExiting = true; 2505 win.mRemoveOnExit = true; 2506 final DisplayContent displayContent = win.getDisplayContent(); 2507 if (displayContent != null) { 2508 displayContent.layoutNeeded = true; 2509 } 2510 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 2511 false /*updateInputWindows*/); 2512 performLayoutAndPlaceSurfacesLocked(); 2513 if (win.mAppToken != null) { 2514 win.mAppToken.updateReportedVisibilityLocked(); 2515 } 2516 //dump(); 2517 Binder.restoreCallingIdentity(origId); 2518 return; 2519 } 2520 } 2521 2522 removeWindowInnerLocked(session, win); 2523 // Removing a visible window will effect the computed orientation 2524 // So just update orientation if needed. 2525 if (wasVisible && updateOrientationFromAppTokensLocked(false)) { 2526 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 2527 } 2528 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 2529 Binder.restoreCallingIdentity(origId); 2530 } 2531 2532 void removeWindowInnerLocked(Session session, WindowState win) { 2533 if (win.mRemoved) { 2534 // Nothing to do. 2535 return; 2536 } 2537 2538 for (int i=win.mChildWindows.size()-1; i>=0; i--) { 2539 WindowState cwin = win.mChildWindows.get(i); 2540 Slog.w(TAG, "Force-removing child win " + cwin + " from container " 2541 + win); 2542 removeWindowInnerLocked(cwin.mSession, cwin); 2543 } 2544 2545 win.mRemoved = true; 2546 2547 if (mInputMethodTarget == win) { 2548 moveInputMethodWindowsIfNeededLocked(false); 2549 } 2550 2551 if (false) { 2552 RuntimeException e = new RuntimeException("here"); 2553 e.fillInStackTrace(); 2554 Slog.w(TAG, "Removing window " + win, e); 2555 } 2556 2557 mPolicy.removeWindowLw(win); 2558 win.removeLocked(); 2559 2560 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win); 2561 mWindowMap.remove(win.mClient.asBinder()); 2562 if (win.mAppOp != AppOpsManager.OP_NONE) { 2563 mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage()); 2564 } 2565 2566 mPendingRemove.remove(win); 2567 mResizingWindows.remove(win); 2568 mWindowsChanged = true; 2569 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win); 2570 2571 if (mInputMethodWindow == win) { 2572 mInputMethodWindow = null; 2573 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) { 2574 mInputMethodDialogs.remove(win); 2575 } 2576 2577 final WindowToken token = win.mToken; 2578 final AppWindowToken atoken = win.mAppToken; 2579 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token); 2580 token.windows.remove(win); 2581 if (atoken != null) { 2582 atoken.allAppWindows.remove(win); 2583 } 2584 if (localLOGV) Slog.v( 2585 TAG, "**** Removing window " + win + ": count=" 2586 + token.windows.size()); 2587 if (token.windows.size() == 0) { 2588 if (!token.explicit) { 2589 mTokenMap.remove(token.token); 2590 } else if (atoken != null) { 2591 atoken.firstWindowDrawn = false; 2592 } 2593 } 2594 2595 if (atoken != null) { 2596 if (atoken.startingWindow == win) { 2597 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling startingWindow " + win); 2598 atoken.startingWindow = null; 2599 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) { 2600 // If this is the last window and we had requested a starting 2601 // transition window, well there is no point now. 2602 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling last startingWindow"); 2603 atoken.startingData = null; 2604 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) { 2605 // If this is the last window except for a starting transition 2606 // window, we need to get rid of the starting transition. 2607 scheduleRemoveStartingWindow(atoken); 2608 } 2609 } 2610 2611 if (win.mAttrs.type == TYPE_WALLPAPER) { 2612 mLastWallpaperTimeoutTime = 0; 2613 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2614 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2615 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2616 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2617 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2618 } 2619 2620 final WindowList windows = win.getWindowList(); 2621 if (windows != null) { 2622 windows.remove(win); 2623 if (!mInLayout) { 2624 assignLayersLocked(windows); 2625 final DisplayContent displayContent = win.getDisplayContent(); 2626 if (displayContent != null) { 2627 displayContent.layoutNeeded = true; 2628 } 2629 performLayoutAndPlaceSurfacesLocked(); 2630 if (win.mAppToken != null) { 2631 win.mAppToken.updateReportedVisibilityLocked(); 2632 } 2633 } 2634 } 2635 2636 mInputMonitor.updateInputWindowsLw(true /*force*/); 2637 } 2638 2639 public void updateAppOpsState() { 2640 synchronized(mWindowMap) { 2641 final int numDisplays = mDisplayContents.size(); 2642 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 2643 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 2644 final int numWindows = windows.size(); 2645 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 2646 final WindowState win = windows.get(winNdx); 2647 if (win.mAppOp != AppOpsManager.OP_NONE) { 2648 final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(), 2649 win.getOwningPackage()); 2650 win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED); 2651 } 2652 } 2653 } 2654 } 2655 } 2656 2657 static void logSurface(WindowState w, String msg, RuntimeException where) { 2658 String str = " SURFACE " + msg + ": " + w; 2659 if (where != null) { 2660 Slog.i(TAG, str, where); 2661 } else { 2662 Slog.i(TAG, str); 2663 } 2664 } 2665 2666 static void logSurface(SurfaceControl s, String title, String msg, RuntimeException where) { 2667 String str = " SURFACE " + s + ": " + msg + " / " + title; 2668 if (where != null) { 2669 Slog.i(TAG, str, where); 2670 } else { 2671 Slog.i(TAG, str); 2672 } 2673 } 2674 2675 void setTransparentRegionWindow(Session session, IWindow client, Region region) { 2676 long origId = Binder.clearCallingIdentity(); 2677 try { 2678 synchronized (mWindowMap) { 2679 WindowState w = windowForClientLocked(session, client, false); 2680 if ((w != null) && w.mHasSurface) { 2681 w.mWinAnimator.setTransparentRegionHintLocked(region); 2682 } 2683 } 2684 } finally { 2685 Binder.restoreCallingIdentity(origId); 2686 } 2687 } 2688 2689 void setInsetsWindow(Session session, IWindow client, 2690 int touchableInsets, Rect contentInsets, 2691 Rect visibleInsets, Region touchableRegion) { 2692 long origId = Binder.clearCallingIdentity(); 2693 try { 2694 synchronized (mWindowMap) { 2695 WindowState w = windowForClientLocked(session, client, false); 2696 if (w != null) { 2697 w.mGivenInsetsPending = false; 2698 w.mGivenContentInsets.set(contentInsets); 2699 w.mGivenVisibleInsets.set(visibleInsets); 2700 w.mGivenTouchableRegion.set(touchableRegion); 2701 w.mTouchableInsets = touchableInsets; 2702 if (w.mGlobalScale != 1) { 2703 w.mGivenContentInsets.scale(w.mGlobalScale); 2704 w.mGivenVisibleInsets.scale(w.mGlobalScale); 2705 w.mGivenTouchableRegion.scale(w.mGlobalScale); 2706 } 2707 final DisplayContent displayContent = w.getDisplayContent(); 2708 if (displayContent != null) { 2709 displayContent.layoutNeeded = true; 2710 } 2711 performLayoutAndPlaceSurfacesLocked(); 2712 } 2713 } 2714 } finally { 2715 Binder.restoreCallingIdentity(origId); 2716 } 2717 } 2718 2719 public void getWindowDisplayFrame(Session session, IWindow client, 2720 Rect outDisplayFrame) { 2721 synchronized(mWindowMap) { 2722 WindowState win = windowForClientLocked(session, client, false); 2723 if (win == null) { 2724 outDisplayFrame.setEmpty(); 2725 return; 2726 } 2727 outDisplayFrame.set(win.mDisplayFrame); 2728 } 2729 } 2730 2731 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y, 2732 float xStep, float yStep) { 2733 if (window.mWallpaperX != x || window.mWallpaperY != y) { 2734 window.mWallpaperX = x; 2735 window.mWallpaperY = y; 2736 window.mWallpaperXStep = xStep; 2737 window.mWallpaperYStep = yStep; 2738 updateWallpaperOffsetLocked(window, true); 2739 } 2740 } 2741 2742 void wallpaperCommandComplete(IBinder window, Bundle result) { 2743 synchronized (mWindowMap) { 2744 if (mWaitingOnWallpaper != null && 2745 mWaitingOnWallpaper.mClient.asBinder() == window) { 2746 mWaitingOnWallpaper = null; 2747 mWindowMap.notifyAll(); 2748 } 2749 } 2750 } 2751 2752 public Bundle sendWindowWallpaperCommandLocked(WindowState window, 2753 String action, int x, int y, int z, Bundle extras, boolean sync) { 2754 if (window == mWallpaperTarget || window == mLowerWallpaperTarget 2755 || window == mUpperWallpaperTarget) { 2756 boolean doWait = sync; 2757 int curTokenIndex = mWallpaperTokens.size(); 2758 while (curTokenIndex > 0) { 2759 curTokenIndex--; 2760 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2761 int curWallpaperIndex = token.windows.size(); 2762 while (curWallpaperIndex > 0) { 2763 curWallpaperIndex--; 2764 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2765 try { 2766 wallpaper.mClient.dispatchWallpaperCommand(action, 2767 x, y, z, extras, sync); 2768 // We only want to be synchronous with one wallpaper. 2769 sync = false; 2770 } catch (RemoteException e) { 2771 } 2772 } 2773 } 2774 2775 if (doWait) { 2776 // XXX Need to wait for result. 2777 } 2778 } 2779 2780 return null; 2781 } 2782 2783 public void setUniverseTransformLocked(WindowState window, float alpha, 2784 float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) { 2785 Transformation transform = window.mWinAnimator.mUniverseTransform; 2786 transform.setAlpha(alpha); 2787 Matrix matrix = transform.getMatrix(); 2788 matrix.getValues(mTmpFloats); 2789 mTmpFloats[Matrix.MTRANS_X] = offx; 2790 mTmpFloats[Matrix.MTRANS_Y] = offy; 2791 mTmpFloats[Matrix.MSCALE_X] = dsdx; 2792 mTmpFloats[Matrix.MSKEW_Y] = dtdx; 2793 mTmpFloats[Matrix.MSKEW_X] = dsdy; 2794 mTmpFloats[Matrix.MSCALE_Y] = dtdy; 2795 matrix.setValues(mTmpFloats); 2796 final DisplayContent displayContent = window.getDisplayContent(); 2797 if (displayContent == null) { 2798 return; 2799 } 2800 2801 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2802 final RectF dispRect = new RectF(0, 0, 2803 displayInfo.logicalWidth, displayInfo.logicalHeight); 2804 matrix.mapRect(dispRect); 2805 window.mGivenTouchableRegion.set(0, 0, 2806 displayInfo.logicalWidth, displayInfo.logicalHeight); 2807 window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top, 2808 (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE); 2809 window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; 2810 displayContent.layoutNeeded = true; 2811 performLayoutAndPlaceSurfacesLocked(); 2812 } 2813 2814 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) { 2815 synchronized (mWindowMap) { 2816 if (mAccessibilityController != null) { 2817 WindowState window = mWindowMap.get(token); 2818 //TODO (multidisplay): Magnification is supported only for the default display. 2819 if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 2820 mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle); 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 // TODO: more accounting of which pid(s) turned it on, keep count, 5578 // only allow disables from pids which have count on, etc. 5579 @Override 5580 public void showStrictModeViolation(boolean on) { 5581 int pid = Binder.getCallingPid(); 5582 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid)); 5583 } 5584 5585 private void showStrictModeViolation(int arg, int pid) { 5586 final boolean on = arg != 0; 5587 synchronized(mWindowMap) { 5588 // Ignoring requests to enable the red border from clients 5589 // which aren't on screen. (e.g. Broadcast Receivers in 5590 // the background..) 5591 if (on) { 5592 boolean isVisible = false; 5593 final int numDisplays = mDisplayContents.size(); 5594 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5595 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5596 final int numWindows = windows.size(); 5597 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5598 final WindowState ws = windows.get(winNdx); 5599 if (ws.mSession.mPid == pid && ws.isVisibleLw()) { 5600 isVisible = true; 5601 break; 5602 } 5603 } 5604 } 5605 if (!isVisible) { 5606 return; 5607 } 5608 } 5609 5610 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5611 ">>> OPEN TRANSACTION showStrictModeViolation"); 5612 SurfaceControl.openTransaction(); 5613 try { 5614 // TODO(multi-display): support multiple displays 5615 if (mStrictModeFlash == null) { 5616 mStrictModeFlash = new StrictModeFlash( 5617 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 5618 } 5619 mStrictModeFlash.setVisibility(on); 5620 } finally { 5621 SurfaceControl.closeTransaction(); 5622 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5623 "<<< CLOSE TRANSACTION showStrictModeViolation"); 5624 } 5625 } 5626 } 5627 5628 @Override 5629 public void setStrictModeVisualIndicatorPreference(String value) { 5630 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 5631 } 5632 5633 /** 5634 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 5635 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 5636 * of the target image. 5637 * 5638 * @param displayId the Display to take a screenshot of. 5639 * @param width the width of the target bitmap 5640 * @param height the height of the target bitmap 5641 * @param force565 if true the returned bitmap will be RGB_565, otherwise it 5642 * will be the same config as the surface 5643 */ 5644 @Override 5645 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, 5646 int height, boolean force565) { 5647 if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, 5648 "screenshotApplications()")) { 5649 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 5650 } 5651 5652 Bitmap rawss = null; 5653 5654 int maxLayer = 0; 5655 final Rect frame = new Rect(); 5656 5657 float scale = 0; 5658 int dw, dh; 5659 int rot = Surface.ROTATION_0; 5660 5661 boolean screenshotReady; 5662 int minLayer; 5663 if (appToken == null) { 5664 screenshotReady = true; 5665 minLayer = 0; 5666 } else { 5667 screenshotReady = false; 5668 minLayer = Integer.MAX_VALUE; 5669 } 5670 5671 int retryCount = 0; 5672 WindowState appWin = null; 5673 5674 do { 5675 if (retryCount++ > 0) { 5676 try { 5677 Thread.sleep(100); 5678 } catch (InterruptedException e) { 5679 } 5680 } 5681 synchronized(mWindowMap) { 5682 final DisplayContent displayContent = getDisplayContentLocked(displayId); 5683 if (displayContent == null) { 5684 return null; 5685 } 5686 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 5687 dw = displayInfo.logicalWidth; 5688 dh = displayInfo.logicalHeight; 5689 5690 int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) 5691 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 5692 aboveAppLayer += TYPE_LAYER_MULTIPLIER; 5693 5694 boolean isImeTarget = mInputMethodTarget != null 5695 && mInputMethodTarget.mAppToken != null 5696 && mInputMethodTarget.mAppToken.appToken != null 5697 && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken; 5698 5699 // Figure out the part of the screen that is actually the app. 5700 boolean including = false; 5701 appWin = null; 5702 final WindowList windows = displayContent.getWindowList(); 5703 final Rect stackBounds = new Rect(); 5704 for (int i = windows.size() - 1; i >= 0; i--) { 5705 WindowState ws = windows.get(i); 5706 if (!ws.mHasSurface) { 5707 continue; 5708 } 5709 if (ws.mLayer >= aboveAppLayer) { 5710 continue; 5711 } 5712 // When we will skip windows: when we are not including 5713 // ones behind a window we didn't skip, and we are actually 5714 // taking a screenshot of a specific app. 5715 if (!including && appToken != null) { 5716 // Also, we can possibly skip this window if it is not 5717 // an IME target or the application for the screenshot 5718 // is not the current IME target. 5719 if (!ws.mIsImWindow || !isImeTarget) { 5720 // And finally, this window is of no interest if it 5721 // is not associated with the screenshot app. 5722 if (ws.mAppToken == null || ws.mAppToken.token != appToken) { 5723 continue; 5724 } 5725 appWin = ws; 5726 ws.getStackBounds(stackBounds); 5727 } 5728 } 5729 5730 // We keep on including windows until we go past a full-screen 5731 // window. 5732 including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh); 5733 5734 final WindowStateAnimator winAnim = ws.mWinAnimator; 5735 if (maxLayer < winAnim.mSurfaceLayer) { 5736 maxLayer = winAnim.mSurfaceLayer; 5737 } 5738 if (minLayer > winAnim.mSurfaceLayer) { 5739 minLayer = winAnim.mSurfaceLayer; 5740 } 5741 5742 // Don't include wallpaper in bounds calculation 5743 if (!ws.mIsWallpaper) { 5744 final Rect wf = ws.mFrame; 5745 final Rect cr = ws.mContentInsets; 5746 int left = wf.left + cr.left; 5747 int top = wf.top + cr.top; 5748 int right = wf.right - cr.right; 5749 int bottom = wf.bottom - cr.bottom; 5750 frame.union(left, top, right, bottom); 5751 frame.intersect(stackBounds); 5752 } 5753 5754 if (ws.mAppToken != null && ws.mAppToken.token == appToken && 5755 ws.isDisplayedLw()) { 5756 screenshotReady = true; 5757 } 5758 } 5759 5760 if (appToken != null && appWin == null) { 5761 // Can't find a window to snapshot. 5762 if (DEBUG_SCREENSHOT) Slog.i(TAG, 5763 "Screenshot: Couldn't find a surface matching " + appToken); 5764 return null; 5765 } 5766 if (!screenshotReady) { 5767 // Delay and hope that window gets drawn. 5768 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken 5769 + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState); 5770 continue; 5771 } 5772 5773 // Constrain frame to the screen size. 5774 frame.intersect(0, 0, dw, dh); 5775 5776 if (frame.isEmpty() || maxLayer == 0) { 5777 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 5778 + ": returning null frame=" + frame.toShortString() + " maxLayer=" 5779 + maxLayer); 5780 return null; 5781 } 5782 5783 // The screenshot API does not apply the current screen rotation. 5784 rot = getDefaultDisplayContentLocked().getDisplay().getRotation(); 5785 int fw = frame.width(); 5786 int fh = frame.height(); 5787 5788 // Constrain thumbnail to smaller of screen width or height. Assumes aspect 5789 // of thumbnail is the same as the screen (in landscape) or square. 5790 scale = Math.max(width / (float) fw, height / (float) fh); 5791 /* 5792 float targetWidthScale = width / (float) fw; 5793 float targetHeightScale = height / (float) fh; 5794 if (fw <= fh) { 5795 scale = targetWidthScale; 5796 // If aspect of thumbnail is the same as the screen (in landscape), 5797 // select the slightly larger value so we fill the entire bitmap 5798 if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) { 5799 scale = targetHeightScale; 5800 } 5801 } else { 5802 scale = targetHeightScale; 5803 // If aspect of thumbnail is the same as the screen (in landscape), 5804 // select the slightly larger value so we fill the entire bitmap 5805 if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) { 5806 scale = targetWidthScale; 5807 } 5808 } 5809 */ 5810 5811 // The screen shot will contain the entire screen. 5812 dw = (int)(dw*scale); 5813 dh = (int)(dh*scale); 5814 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 5815 int tmp = dw; 5816 dw = dh; 5817 dh = tmp; 5818 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; 5819 } 5820 if (DEBUG_SCREENSHOT) { 5821 Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 5822 + maxLayer + " appToken=" + appToken); 5823 for (int i = 0; i < windows.size(); i++) { 5824 WindowState win = windows.get(i); 5825 Slog.i(TAG, win + ": " + win.mLayer 5826 + " animLayer=" + win.mWinAnimator.mAnimLayer 5827 + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer); 5828 } 5829 } 5830 // TODO: Replace 'false' in the following line with a variable that indicates 5831 // whether the screenshot should use the identity transformation matrix 5832 // (e.g., enable it when taking a screenshot for recents, since we might be in 5833 // the middle of the rotation animation, but don't want a rotated recent image). 5834 // TODO: Replace 'new Rect()' with the portion of the screen to capture for the 5835 // screenshot. 5836 rawss = SurfaceControl.screenshot(new Rect(), dw, dh, minLayer, maxLayer, false); 5837 } 5838 } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES); 5839 if (retryCount > MAX_SCREENSHOT_RETRIES) Slog.i(TAG, "Screenshot max retries " + 5840 retryCount + " of " + appToken + " appWin=" + (appWin == null ? 5841 "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState))); 5842 5843 if (rawss == null) { 5844 Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh 5845 + ") to layer " + maxLayer); 5846 return null; 5847 } 5848 5849 Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig()); 5850 bm.eraseColor(0xFF000000); 5851 frame.scale(scale); 5852 Matrix matrix = new Matrix(); 5853 ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix); 5854 // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left 5855 matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top)); 5856 Canvas canvas = new Canvas(bm); 5857 canvas.drawBitmap(rawss, matrix, null); 5858 canvas.setBitmap(null); 5859 5860 if (DEBUG_SCREENSHOT) { 5861 // TEST IF IT's ALL BLACK 5862 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 5863 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 5864 boolean allBlack = true; 5865 final int firstColor = buffer[0]; 5866 for (int i = 0; i < buffer.length; i++) { 5867 if (buffer[i] != firstColor) { 5868 allBlack = false; 5869 break; 5870 } 5871 } 5872 if (allBlack) { 5873 Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" + 5874 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 5875 (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") + 5876 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 5877 } 5878 } 5879 5880 rawss.recycle(); 5881 return bm; 5882 } 5883 5884 /** 5885 * Freeze rotation changes. (Enable "rotation lock".) 5886 * Persists across reboots. 5887 * @param rotation The desired rotation to freeze to, or -1 to use the 5888 * current rotation. 5889 */ 5890 @Override 5891 public void freezeRotation(int rotation) { 5892 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5893 "freezeRotation()")) { 5894 throw new SecurityException("Requires SET_ORIENTATION permission"); 5895 } 5896 if (rotation < -1 || rotation > Surface.ROTATION_270) { 5897 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 5898 + "rotation constant."); 5899 } 5900 5901 if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); 5902 5903 long origId = Binder.clearCallingIdentity(); 5904 try { 5905 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, 5906 rotation == -1 ? mRotation : rotation); 5907 } finally { 5908 Binder.restoreCallingIdentity(origId); 5909 } 5910 5911 updateRotationUnchecked(false, false); 5912 } 5913 5914 /** 5915 * Thaw rotation changes. (Disable "rotation lock".) 5916 * Persists across reboots. 5917 */ 5918 @Override 5919 public void thawRotation() { 5920 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5921 "thawRotation()")) { 5922 throw new SecurityException("Requires SET_ORIENTATION permission"); 5923 } 5924 5925 if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); 5926 5927 long origId = Binder.clearCallingIdentity(); 5928 try { 5929 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 5930 777); // rot not used 5931 } finally { 5932 Binder.restoreCallingIdentity(origId); 5933 } 5934 5935 updateRotationUnchecked(false, false); 5936 } 5937 5938 /** 5939 * Recalculate the current rotation. 5940 * 5941 * Called by the window manager policy whenever the state of the system changes 5942 * such that the current rotation might need to be updated, such as when the 5943 * device is docked or rotated into a new posture. 5944 */ 5945 @Override 5946 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 5947 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 5948 } 5949 5950 /** 5951 * Temporarily pauses rotation changes until resumed. 5952 * 5953 * This can be used to prevent rotation changes from occurring while the user is 5954 * performing certain operations, such as drag and drop. 5955 * 5956 * This call nests and must be matched by an equal number of calls to 5957 * {@link #resumeRotationLocked}. 5958 */ 5959 void pauseRotationLocked() { 5960 mDeferredRotationPauseCount += 1; 5961 } 5962 5963 /** 5964 * Resumes normal rotation changes after being paused. 5965 */ 5966 void resumeRotationLocked() { 5967 if (mDeferredRotationPauseCount > 0) { 5968 mDeferredRotationPauseCount -= 1; 5969 if (mDeferredRotationPauseCount == 0) { 5970 boolean changed = updateRotationUncheckedLocked(false); 5971 if (changed) { 5972 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 5973 } 5974 } 5975 } 5976 } 5977 5978 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 5979 if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" 5980 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); 5981 5982 long origId = Binder.clearCallingIdentity(); 5983 boolean changed; 5984 synchronized(mWindowMap) { 5985 changed = updateRotationUncheckedLocked(false); 5986 if (!changed || forceRelayout) { 5987 getDefaultDisplayContentLocked().layoutNeeded = true; 5988 performLayoutAndPlaceSurfacesLocked(); 5989 } 5990 } 5991 5992 if (changed || alwaysSendConfiguration) { 5993 sendNewConfiguration(); 5994 } 5995 5996 Binder.restoreCallingIdentity(origId); 5997 } 5998 5999 // TODO(multidisplay): Rotate any display? 6000 /** 6001 * Updates the current rotation. 6002 * 6003 * Returns true if the rotation has been changed. In this case YOU 6004 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. 6005 */ 6006 public boolean updateRotationUncheckedLocked(boolean inTransaction) { 6007 if (mDeferredRotationPauseCount > 0) { 6008 // Rotation updates have been paused temporarily. Defer the update until 6009 // updates have been resumed. 6010 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused."); 6011 return false; 6012 } 6013 6014 ScreenRotationAnimation screenRotationAnimation = 6015 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6016 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 6017 // Rotation updates cannot be performed while the previous rotation change 6018 // animation is still in progress. Skip this update. We will try updating 6019 // again after the animation is finished and the display is unfrozen. 6020 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress."); 6021 return false; 6022 } 6023 6024 if (!mDisplayEnabled) { 6025 // No point choosing a rotation if the display is not enabled. 6026 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled."); 6027 return false; 6028 } 6029 6030 // TODO: Implement forced rotation changes. 6031 // Set mAltOrientation to indicate that the application is receiving 6032 // an orientation that has different metrics than it expected. 6033 // eg. Portrait instead of Landscape. 6034 6035 int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation); 6036 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 6037 mForcedAppOrientation, rotation); 6038 6039 if (DEBUG_ORIENTATION) { 6040 Slog.v(TAG, "Application requested orientation " 6041 + mForcedAppOrientation + ", got rotation " + rotation 6042 + " which has " + (altOrientation ? "incompatible" : "compatible") 6043 + " metrics"); 6044 } 6045 6046 if (mRotation == rotation && mAltOrientation == altOrientation) { 6047 // No change. 6048 return false; 6049 } 6050 6051 if (DEBUG_ORIENTATION) { 6052 Slog.v(TAG, 6053 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") 6054 + " from " + mRotation + (mAltOrientation ? " (alt)" : "") 6055 + ", forceApp=" + mForcedAppOrientation); 6056 } 6057 6058 mRotation = rotation; 6059 mAltOrientation = altOrientation; 6060 mPolicy.setRotationLw(mRotation); 6061 6062 mWindowsFreezingScreen = true; 6063 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 6064 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION); 6065 mWaitingForConfig = true; 6066 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6067 displayContent.layoutNeeded = true; 6068 final int[] anim = new int[2]; 6069 if (displayContent.isDimming()) { 6070 anim[0] = anim[1] = 0; 6071 } else { 6072 mPolicy.selectRotationAnimationLw(anim); 6073 } 6074 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]); 6075 // startFreezingDisplayLocked can reset the ScreenRotationAnimation. 6076 screenRotationAnimation = 6077 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6078 6079 // We need to update our screen size information to match the new 6080 // rotation. Note that this is redundant with the later call to 6081 // sendNewConfiguration() that must be called after this function 6082 // returns... however we need to do the screen size part of that 6083 // before then so we have the correct size to use when initializing 6084 // the rotation animation for the new rotation. 6085 computeScreenConfigurationLocked(null); 6086 6087 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6088 if (!inTransaction) { 6089 if (SHOW_TRANSACTIONS) { 6090 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked"); 6091 } 6092 SurfaceControl.openTransaction(); 6093 } 6094 try { 6095 // NOTE: We disable the rotation in the emulator because 6096 // it doesn't support hardware OpenGL emulation yet. 6097 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 6098 && screenRotationAnimation.hasScreenshot()) { 6099 if (screenRotationAnimation.setRotationInTransaction( 6100 rotation, mFxSession, 6101 MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(), 6102 displayInfo.logicalWidth, displayInfo.logicalHeight)) { 6103 scheduleAnimationLocked(); 6104 } 6105 } 6106 6107 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 6108 } finally { 6109 if (!inTransaction) { 6110 SurfaceControl.closeTransaction(); 6111 if (SHOW_LIGHT_TRANSACTIONS) { 6112 Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked"); 6113 } 6114 } 6115 } 6116 6117 final WindowList windows = displayContent.getWindowList(); 6118 for (int i = windows.size() - 1; i >= 0; i--) { 6119 WindowState w = windows.get(i); 6120 if (w.mHasSurface) { 6121 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w); 6122 w.mOrientationChanging = true; 6123 mInnerFields.mOrientationChangeComplete = false; 6124 } 6125 w.mLastFreezeDuration = 0; 6126 } 6127 6128 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 6129 try { 6130 mRotationWatchers.get(i).watcher.onRotationChanged(rotation); 6131 } catch (RemoteException e) { 6132 } 6133 } 6134 6135 //TODO (multidisplay): Magnification is supported only for the default display. 6136 if (mAccessibilityController != null 6137 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 6138 mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation); 6139 } 6140 6141 return true; 6142 } 6143 6144 @Override 6145 public int getRotation() { 6146 return mRotation; 6147 } 6148 6149 @Override 6150 public boolean isRotationFrozen() { 6151 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED; 6152 } 6153 6154 @Override 6155 public int watchRotation(IRotationWatcher watcher) { 6156 final IBinder watcherBinder = watcher.asBinder(); 6157 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 6158 @Override 6159 public void binderDied() { 6160 synchronized (mWindowMap) { 6161 for (int i=0; i<mRotationWatchers.size(); i++) { 6162 if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) { 6163 RotationWatcher removed = mRotationWatchers.remove(i); 6164 IBinder binder = removed.watcher.asBinder(); 6165 if (binder != null) { 6166 binder.unlinkToDeath(this, 0); 6167 } 6168 i--; 6169 } 6170 } 6171 } 6172 } 6173 }; 6174 6175 synchronized (mWindowMap) { 6176 try { 6177 watcher.asBinder().linkToDeath(dr, 0); 6178 mRotationWatchers.add(new RotationWatcher(watcher, dr)); 6179 } catch (RemoteException e) { 6180 // Client died, no cleanup needed. 6181 } 6182 6183 return mRotation; 6184 } 6185 } 6186 6187 @Override 6188 public void removeRotationWatcher(IRotationWatcher watcher) { 6189 final IBinder watcherBinder = watcher.asBinder(); 6190 synchronized (mWindowMap) { 6191 for (int i=0; i<mRotationWatchers.size(); i++) { 6192 RotationWatcher rotationWatcher = mRotationWatchers.get(i); 6193 if (watcherBinder == rotationWatcher.watcher.asBinder()) { 6194 RotationWatcher removed = mRotationWatchers.remove(i); 6195 IBinder binder = removed.watcher.asBinder(); 6196 if (binder != null) { 6197 binder.unlinkToDeath(removed.deathRecipient, 0); 6198 } 6199 i--; 6200 } 6201 } 6202 } 6203 } 6204 6205 /** 6206 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 6207 * theme attribute) on devices that feature a physical options menu key attempt to position 6208 * their menu panel window along the edge of the screen nearest the physical menu key. 6209 * This lowers the travel distance between invoking the menu panel and selecting 6210 * a menu option. 6211 * 6212 * This method helps control where that menu is placed. Its current implementation makes 6213 * assumptions about the menu key and its relationship to the screen based on whether 6214 * the device's natural orientation is portrait (width < height) or landscape. 6215 * 6216 * The menu key is assumed to be located along the bottom edge of natural-portrait 6217 * devices and along the right edge of natural-landscape devices. If these assumptions 6218 * do not hold for the target device, this method should be changed to reflect that. 6219 * 6220 * @return A {@link Gravity} value for placing the options menu window 6221 */ 6222 @Override 6223 public int getPreferredOptionsPanelGravity() { 6224 synchronized (mWindowMap) { 6225 final int rotation = getRotation(); 6226 6227 // TODO(multidisplay): Assume that such devices physical keys are on the main screen. 6228 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6229 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) { 6230 // On devices with a natural orientation of portrait 6231 switch (rotation) { 6232 default: 6233 case Surface.ROTATION_0: 6234 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6235 case Surface.ROTATION_90: 6236 return Gravity.RIGHT | Gravity.BOTTOM; 6237 case Surface.ROTATION_180: 6238 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6239 case Surface.ROTATION_270: 6240 return Gravity.START | Gravity.BOTTOM; 6241 } 6242 } 6243 6244 // On devices with a natural orientation of landscape 6245 switch (rotation) { 6246 default: 6247 case Surface.ROTATION_0: 6248 return Gravity.RIGHT | Gravity.BOTTOM; 6249 case Surface.ROTATION_90: 6250 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6251 case Surface.ROTATION_180: 6252 return Gravity.START | Gravity.BOTTOM; 6253 case Surface.ROTATION_270: 6254 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6255 } 6256 } 6257 } 6258 6259 /** 6260 * Starts the view server on the specified port. 6261 * 6262 * @param port The port to listener to. 6263 * 6264 * @return True if the server was successfully started, false otherwise. 6265 * 6266 * @see com.android.server.wm.ViewServer 6267 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 6268 */ 6269 @Override 6270 public boolean startViewServer(int port) { 6271 if (isSystemSecure()) { 6272 return false; 6273 } 6274 6275 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 6276 return false; 6277 } 6278 6279 if (port < 1024) { 6280 return false; 6281 } 6282 6283 if (mViewServer != null) { 6284 if (!mViewServer.isRunning()) { 6285 try { 6286 return mViewServer.start(); 6287 } catch (IOException e) { 6288 Slog.w(TAG, "View server did not start"); 6289 } 6290 } 6291 return false; 6292 } 6293 6294 try { 6295 mViewServer = new ViewServer(this, port); 6296 return mViewServer.start(); 6297 } catch (IOException e) { 6298 Slog.w(TAG, "View server did not start"); 6299 } 6300 return false; 6301 } 6302 6303 private boolean isSystemSecure() { 6304 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 6305 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 6306 } 6307 6308 /** 6309 * Stops the view server if it exists. 6310 * 6311 * @return True if the server stopped, false if it wasn't started or 6312 * couldn't be stopped. 6313 * 6314 * @see com.android.server.wm.ViewServer 6315 */ 6316 @Override 6317 public boolean stopViewServer() { 6318 if (isSystemSecure()) { 6319 return false; 6320 } 6321 6322 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 6323 return false; 6324 } 6325 6326 if (mViewServer != null) { 6327 return mViewServer.stop(); 6328 } 6329 return false; 6330 } 6331 6332 /** 6333 * Indicates whether the view server is running. 6334 * 6335 * @return True if the server is running, false otherwise. 6336 * 6337 * @see com.android.server.wm.ViewServer 6338 */ 6339 @Override 6340 public boolean isViewServerRunning() { 6341 if (isSystemSecure()) { 6342 return false; 6343 } 6344 6345 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 6346 return false; 6347 } 6348 6349 return mViewServer != null && mViewServer.isRunning(); 6350 } 6351 6352 /** 6353 * Lists all availble windows in the system. The listing is written in the 6354 * specified Socket's output stream with the following syntax: 6355 * windowHashCodeInHexadecimal windowName 6356 * Each line of the ouput represents a different window. 6357 * 6358 * @param client The remote client to send the listing to. 6359 * @return False if an error occured, true otherwise. 6360 */ 6361 boolean viewServerListWindows(Socket client) { 6362 if (isSystemSecure()) { 6363 return false; 6364 } 6365 6366 boolean result = true; 6367 6368 WindowList windows = new WindowList(); 6369 synchronized (mWindowMap) { 6370 //noinspection unchecked 6371 final int numDisplays = mDisplayContents.size(); 6372 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6373 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 6374 windows.addAll(displayContent.getWindowList()); 6375 } 6376 } 6377 6378 BufferedWriter out = null; 6379 6380 // Any uncaught exception will crash the system process 6381 try { 6382 OutputStream clientStream = client.getOutputStream(); 6383 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6384 6385 final int count = windows.size(); 6386 for (int i = 0; i < count; i++) { 6387 final WindowState w = windows.get(i); 6388 out.write(Integer.toHexString(System.identityHashCode(w))); 6389 out.write(' '); 6390 out.append(w.mAttrs.getTitle()); 6391 out.write('\n'); 6392 } 6393 6394 out.write("DONE.\n"); 6395 out.flush(); 6396 } catch (Exception e) { 6397 result = false; 6398 } finally { 6399 if (out != null) { 6400 try { 6401 out.close(); 6402 } catch (IOException e) { 6403 result = false; 6404 } 6405 } 6406 } 6407 6408 return result; 6409 } 6410 6411 // TODO(multidisplay): Extend to multiple displays. 6412 /** 6413 * Returns the focused window in the following format: 6414 * windowHashCodeInHexadecimal windowName 6415 * 6416 * @param client The remote client to send the listing to. 6417 * @return False if an error occurred, true otherwise. 6418 */ 6419 boolean viewServerGetFocusedWindow(Socket client) { 6420 if (isSystemSecure()) { 6421 return false; 6422 } 6423 6424 boolean result = true; 6425 6426 WindowState focusedWindow = getFocusedWindow(); 6427 6428 BufferedWriter out = null; 6429 6430 // Any uncaught exception will crash the system process 6431 try { 6432 OutputStream clientStream = client.getOutputStream(); 6433 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6434 6435 if(focusedWindow != null) { 6436 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 6437 out.write(' '); 6438 out.append(focusedWindow.mAttrs.getTitle()); 6439 } 6440 out.write('\n'); 6441 out.flush(); 6442 } catch (Exception e) { 6443 result = false; 6444 } finally { 6445 if (out != null) { 6446 try { 6447 out.close(); 6448 } catch (IOException e) { 6449 result = false; 6450 } 6451 } 6452 } 6453 6454 return result; 6455 } 6456 6457 /** 6458 * Sends a command to a target window. The result of the command, if any, will be 6459 * written in the output stream of the specified socket. 6460 * 6461 * The parameters must follow this syntax: 6462 * windowHashcode extra 6463 * 6464 * Where XX is the length in characeters of the windowTitle. 6465 * 6466 * The first parameter is the target window. The window with the specified hashcode 6467 * will be the target. If no target can be found, nothing happens. The extra parameters 6468 * will be delivered to the target window and as parameters to the command itself. 6469 * 6470 * @param client The remote client to sent the result, if any, to. 6471 * @param command The command to execute. 6472 * @param parameters The command parameters. 6473 * 6474 * @return True if the command was successfully delivered, false otherwise. This does 6475 * not indicate whether the command itself was successful. 6476 */ 6477 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 6478 if (isSystemSecure()) { 6479 return false; 6480 } 6481 6482 boolean success = true; 6483 Parcel data = null; 6484 Parcel reply = null; 6485 6486 BufferedWriter out = null; 6487 6488 // Any uncaught exception will crash the system process 6489 try { 6490 // Find the hashcode of the window 6491 int index = parameters.indexOf(' '); 6492 if (index == -1) { 6493 index = parameters.length(); 6494 } 6495 final String code = parameters.substring(0, index); 6496 int hashCode = (int) Long.parseLong(code, 16); 6497 6498 // Extract the command's parameter after the window description 6499 if (index < parameters.length()) { 6500 parameters = parameters.substring(index + 1); 6501 } else { 6502 parameters = ""; 6503 } 6504 6505 final WindowState window = findWindow(hashCode); 6506 if (window == null) { 6507 return false; 6508 } 6509 6510 data = Parcel.obtain(); 6511 data.writeInterfaceToken("android.view.IWindow"); 6512 data.writeString(command); 6513 data.writeString(parameters); 6514 data.writeInt(1); 6515 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 6516 6517 reply = Parcel.obtain(); 6518 6519 final IBinder binder = window.mClient.asBinder(); 6520 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 6521 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 6522 6523 reply.readException(); 6524 6525 if (!client.isOutputShutdown()) { 6526 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 6527 out.write("DONE\n"); 6528 out.flush(); 6529 } 6530 6531 } catch (Exception e) { 6532 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); 6533 success = false; 6534 } finally { 6535 if (data != null) { 6536 data.recycle(); 6537 } 6538 if (reply != null) { 6539 reply.recycle(); 6540 } 6541 if (out != null) { 6542 try { 6543 out.close(); 6544 } catch (IOException e) { 6545 6546 } 6547 } 6548 } 6549 6550 return success; 6551 } 6552 6553 public void addWindowChangeListener(WindowChangeListener listener) { 6554 synchronized(mWindowMap) { 6555 mWindowChangeListeners.add(listener); 6556 } 6557 } 6558 6559 public void removeWindowChangeListener(WindowChangeListener listener) { 6560 synchronized(mWindowMap) { 6561 mWindowChangeListeners.remove(listener); 6562 } 6563 } 6564 6565 private void notifyWindowsChanged() { 6566 WindowChangeListener[] windowChangeListeners; 6567 synchronized(mWindowMap) { 6568 if(mWindowChangeListeners.isEmpty()) { 6569 return; 6570 } 6571 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6572 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6573 } 6574 int N = windowChangeListeners.length; 6575 for(int i = 0; i < N; i++) { 6576 windowChangeListeners[i].windowsChanged(); 6577 } 6578 } 6579 6580 private void notifyFocusChanged() { 6581 WindowChangeListener[] windowChangeListeners; 6582 synchronized(mWindowMap) { 6583 if(mWindowChangeListeners.isEmpty()) { 6584 return; 6585 } 6586 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6587 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6588 } 6589 int N = windowChangeListeners.length; 6590 for(int i = 0; i < N; i++) { 6591 windowChangeListeners[i].focusChanged(); 6592 } 6593 } 6594 6595 private WindowState findWindow(int hashCode) { 6596 if (hashCode == -1) { 6597 // TODO(multidisplay): Extend to multiple displays. 6598 return getFocusedWindow(); 6599 } 6600 6601 synchronized (mWindowMap) { 6602 final int numDisplays = mDisplayContents.size(); 6603 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6604 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 6605 final int numWindows = windows.size(); 6606 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 6607 final WindowState w = windows.get(winNdx); 6608 if (System.identityHashCode(w) == hashCode) { 6609 return w; 6610 } 6611 } 6612 } 6613 } 6614 6615 return null; 6616 } 6617 6618 /* 6619 * Instruct the Activity Manager to fetch the current configuration and broadcast 6620 * that to config-changed listeners if appropriate. 6621 */ 6622 void sendNewConfiguration() { 6623 try { 6624 mActivityManager.updateConfiguration(null); 6625 } catch (RemoteException e) { 6626 } 6627 } 6628 6629 public Configuration computeNewConfiguration() { 6630 synchronized (mWindowMap) { 6631 Configuration config = computeNewConfigurationLocked(); 6632 if (config == null && mWaitingForConfig) { 6633 // Nothing changed but we are waiting for something... stop that! 6634 mWaitingForConfig = false; 6635 mLastFinishedFreezeSource = "new-config"; 6636 performLayoutAndPlaceSurfacesLocked(); 6637 } 6638 return config; 6639 } 6640 } 6641 6642 Configuration computeNewConfigurationLocked() { 6643 Configuration config = new Configuration(); 6644 config.fontScale = 0; 6645 if (!computeScreenConfigurationLocked(config)) { 6646 return null; 6647 } 6648 return config; 6649 } 6650 6651 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) { 6652 // TODO: Multidisplay: for now only use with default display. 6653 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation); 6654 if (width < displayInfo.smallestNominalAppWidth) { 6655 displayInfo.smallestNominalAppWidth = width; 6656 } 6657 if (width > displayInfo.largestNominalAppWidth) { 6658 displayInfo.largestNominalAppWidth = width; 6659 } 6660 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation); 6661 if (height < displayInfo.smallestNominalAppHeight) { 6662 displayInfo.smallestNominalAppHeight = height; 6663 } 6664 if (height > displayInfo.largestNominalAppHeight) { 6665 displayInfo.largestNominalAppHeight = height; 6666 } 6667 } 6668 6669 private int reduceConfigLayout(int curLayout, int rotation, float density, 6670 int dw, int dh) { 6671 // TODO: Multidisplay: for now only use with default display. 6672 // Get the app screen size at this rotation. 6673 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6674 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6675 6676 // Compute the screen layout size class for this rotation. 6677 int longSize = w; 6678 int shortSize = h; 6679 if (longSize < shortSize) { 6680 int tmp = longSize; 6681 longSize = shortSize; 6682 shortSize = tmp; 6683 } 6684 longSize = (int)(longSize/density); 6685 shortSize = (int)(shortSize/density); 6686 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 6687 } 6688 6689 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 6690 int dw, int dh, float density, Configuration outConfig) { 6691 // TODO: Multidisplay: for now only use with default display. 6692 6693 // We need to determine the smallest width that will occur under normal 6694 // operation. To this, start with the base screen size and compute the 6695 // width under the different possible rotations. We need to un-rotate 6696 // the current screen dimensions before doing this. 6697 int unrotDw, unrotDh; 6698 if (rotated) { 6699 unrotDw = dh; 6700 unrotDh = dw; 6701 } else { 6702 unrotDw = dw; 6703 unrotDh = dh; 6704 } 6705 displayInfo.smallestNominalAppWidth = 1<<30; 6706 displayInfo.smallestNominalAppHeight = 1<<30; 6707 displayInfo.largestNominalAppWidth = 0; 6708 displayInfo.largestNominalAppHeight = 0; 6709 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh); 6710 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw); 6711 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh); 6712 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw); 6713 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 6714 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh); 6715 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw); 6716 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); 6717 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); 6718 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 6719 outConfig.screenLayout = sl; 6720 } 6721 6722 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, 6723 int dw, int dh) { 6724 // TODO: Multidisplay: for now only use with default display. 6725 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6726 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6727 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 6728 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 6729 if (curSize == 0 || size < curSize) { 6730 curSize = size; 6731 } 6732 return curSize; 6733 } 6734 6735 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) { 6736 // TODO: Multidisplay: for now only use with default display. 6737 mTmpDisplayMetrics.setTo(dm); 6738 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 6739 final int unrotDw, unrotDh; 6740 if (rotated) { 6741 unrotDw = dh; 6742 unrotDh = dw; 6743 } else { 6744 unrotDw = dw; 6745 unrotDh = dh; 6746 } 6747 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh); 6748 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw); 6749 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh); 6750 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw); 6751 return sw; 6752 } 6753 6754 boolean computeScreenConfigurationLocked(Configuration config) { 6755 if (!mDisplayReady) { 6756 return false; 6757 } 6758 6759 // TODO(multidisplay): For now, apply Configuration to main screen only. 6760 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6761 6762 // Use the effective "visual" dimensions based on current rotation 6763 final boolean rotated = (mRotation == Surface.ROTATION_90 6764 || mRotation == Surface.ROTATION_270); 6765 final int realdw = rotated ? 6766 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; 6767 final int realdh = rotated ? 6768 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; 6769 int dw = realdw; 6770 int dh = realdh; 6771 6772 if (mAltOrientation) { 6773 if (realdw > realdh) { 6774 // Turn landscape into portrait. 6775 int maxw = (int)(realdh/1.3f); 6776 if (maxw < realdw) { 6777 dw = maxw; 6778 } 6779 } else { 6780 // Turn portrait into landscape. 6781 int maxh = (int)(realdw/1.3f); 6782 if (maxh < realdh) { 6783 dh = maxh; 6784 } 6785 } 6786 } 6787 6788 if (config != null) { 6789 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : 6790 Configuration.ORIENTATION_LANDSCAPE; 6791 } 6792 6793 // Update application display metrics. 6794 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); 6795 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); 6796 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6797 synchronized(displayContent.mDisplaySizeLock) { 6798 displayInfo.rotation = mRotation; 6799 displayInfo.logicalWidth = dw; 6800 displayInfo.logicalHeight = dh; 6801 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; 6802 displayInfo.appWidth = appWidth; 6803 displayInfo.appHeight = appHeight; 6804 displayInfo.getLogicalMetrics(mRealDisplayMetrics, 6805 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 6806 displayInfo.getAppMetrics(mDisplayMetrics); 6807 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 6808 displayContent.getDisplayId(), displayInfo); 6809 } 6810 if (false) { 6811 Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); 6812 } 6813 6814 final DisplayMetrics dm = mDisplayMetrics; 6815 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, 6816 mCompatDisplayMetrics); 6817 6818 if (config != null) { 6819 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) 6820 / dm.density); 6821 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) 6822 / dm.density); 6823 computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config); 6824 6825 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 6826 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 6827 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); 6828 config.densityDpi = displayContent.mBaseDisplayDensity; 6829 6830 // Update the configuration based on available input devices, lid switch, 6831 // and platform configuration. 6832 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6833 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6834 config.navigation = Configuration.NAVIGATION_NONAV; 6835 6836 int keyboardPresence = 0; 6837 int navigationPresence = 0; 6838 final InputDevice[] devices = mInputManager.getInputDevices(); 6839 final int len = devices.length; 6840 for (int i = 0; i < len; i++) { 6841 InputDevice device = devices[i]; 6842 if (!device.isVirtual()) { 6843 final int sources = device.getSources(); 6844 final int presenceFlag = device.isExternal() ? 6845 WindowManagerPolicy.PRESENCE_EXTERNAL : 6846 WindowManagerPolicy.PRESENCE_INTERNAL; 6847 6848 if (mIsTouchDevice) { 6849 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 6850 InputDevice.SOURCE_TOUCHSCREEN) { 6851 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 6852 } 6853 } else { 6854 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6855 } 6856 6857 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 6858 config.navigation = Configuration.NAVIGATION_TRACKBALL; 6859 navigationPresence |= presenceFlag; 6860 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 6861 && config.navigation == Configuration.NAVIGATION_NONAV) { 6862 config.navigation = Configuration.NAVIGATION_DPAD; 6863 navigationPresence |= presenceFlag; 6864 } 6865 6866 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 6867 config.keyboard = Configuration.KEYBOARD_QWERTY; 6868 keyboardPresence |= presenceFlag; 6869 } 6870 } 6871 } 6872 6873 // Determine whether a hard keyboard is available and enabled. 6874 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 6875 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 6876 mHardKeyboardAvailable = hardKeyboardAvailable; 6877 mHardKeyboardEnabled = hardKeyboardAvailable; 6878 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6879 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6880 } 6881 if (!mHardKeyboardEnabled) { 6882 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6883 } 6884 6885 // Let the policy update hidden states. 6886 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 6887 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 6888 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 6889 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 6890 } 6891 6892 return true; 6893 } 6894 6895 public boolean isHardKeyboardAvailable() { 6896 synchronized (mWindowMap) { 6897 return mHardKeyboardAvailable; 6898 } 6899 } 6900 6901 public boolean isHardKeyboardEnabled() { 6902 synchronized (mWindowMap) { 6903 return mHardKeyboardEnabled; 6904 } 6905 } 6906 6907 public void setHardKeyboardEnabled(boolean enabled) { 6908 synchronized (mWindowMap) { 6909 if (mHardKeyboardEnabled != enabled) { 6910 mHardKeyboardEnabled = enabled; 6911 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6912 } 6913 } 6914 } 6915 6916 public void setOnHardKeyboardStatusChangeListener( 6917 OnHardKeyboardStatusChangeListener listener) { 6918 synchronized (mWindowMap) { 6919 mHardKeyboardStatusChangeListener = listener; 6920 } 6921 } 6922 6923 void notifyHardKeyboardStatusChange() { 6924 final boolean available, enabled; 6925 final OnHardKeyboardStatusChangeListener listener; 6926 synchronized (mWindowMap) { 6927 listener = mHardKeyboardStatusChangeListener; 6928 available = mHardKeyboardAvailable; 6929 enabled = mHardKeyboardEnabled; 6930 } 6931 if (listener != null) { 6932 listener.onHardKeyboardStatusChange(available, enabled); 6933 } 6934 } 6935 6936 // ------------------------------------------------------------- 6937 // Drag and drop 6938 // ------------------------------------------------------------- 6939 6940 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 6941 int flags, int width, int height, Surface outSurface) { 6942 if (DEBUG_DRAG) { 6943 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 6944 + " flags=" + Integer.toHexString(flags) + " win=" + window 6945 + " asbinder=" + window.asBinder()); 6946 } 6947 6948 final int callerPid = Binder.getCallingPid(); 6949 final long origId = Binder.clearCallingIdentity(); 6950 IBinder token = null; 6951 6952 try { 6953 synchronized (mWindowMap) { 6954 try { 6955 if (mDragState == null) { 6956 // TODO(multi-display): support other displays 6957 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6958 final Display display = displayContent.getDisplay(); 6959 SurfaceControl surface = new SurfaceControl(session, "drag surface", 6960 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 6961 surface.setLayerStack(display.getLayerStack()); 6962 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 6963 + surface + ": CREATE"); 6964 outSurface.copyFrom(surface); 6965 final IBinder winBinder = window.asBinder(); 6966 token = new Binder(); 6967 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 6968 token = mDragState.mToken = new Binder(); 6969 6970 // 5 second timeout for this window to actually begin the drag 6971 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 6972 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 6973 mH.sendMessageDelayed(msg, 5000); 6974 } else { 6975 Slog.w(TAG, "Drag already in progress"); 6976 } 6977 } catch (OutOfResourcesException e) { 6978 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 6979 if (mDragState != null) { 6980 mDragState.reset(); 6981 mDragState = null; 6982 } 6983 } 6984 } 6985 } finally { 6986 Binder.restoreCallingIdentity(origId); 6987 } 6988 6989 return token; 6990 } 6991 6992 // ------------------------------------------------------------- 6993 // Input Events and Focus Management 6994 // ------------------------------------------------------------- 6995 6996 final InputMonitor mInputMonitor = new InputMonitor(this); 6997 private boolean mEventDispatchingEnabled; 6998 6999 @Override 7000 public void pauseKeyDispatching(IBinder _token) { 7001 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7002 "pauseKeyDispatching()")) { 7003 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7004 } 7005 7006 synchronized (mWindowMap) { 7007 WindowToken token = mTokenMap.get(_token); 7008 if (token != null) { 7009 mInputMonitor.pauseDispatchingLw(token); 7010 } 7011 } 7012 } 7013 7014 @Override 7015 public void resumeKeyDispatching(IBinder _token) { 7016 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7017 "resumeKeyDispatching()")) { 7018 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7019 } 7020 7021 synchronized (mWindowMap) { 7022 WindowToken token = mTokenMap.get(_token); 7023 if (token != null) { 7024 mInputMonitor.resumeDispatchingLw(token); 7025 } 7026 } 7027 } 7028 7029 @Override 7030 public void setEventDispatching(boolean enabled) { 7031 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7032 "setEventDispatching()")) { 7033 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7034 } 7035 7036 synchronized (mWindowMap) { 7037 mEventDispatchingEnabled = enabled; 7038 if (mDisplayEnabled) { 7039 mInputMonitor.setEventDispatchingLw(enabled); 7040 } 7041 } 7042 } 7043 7044 private WindowState getFocusedWindow() { 7045 synchronized (mWindowMap) { 7046 return getFocusedWindowLocked(); 7047 } 7048 } 7049 7050 private WindowState getFocusedWindowLocked() { 7051 return mCurrentFocus; 7052 } 7053 7054 public boolean detectSafeMode() { 7055 if (!mInputMonitor.waitForInputDevicesReady( 7056 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 7057 Slog.w(TAG, "Devices still not ready after waiting " 7058 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 7059 + " milliseconds before attempting to detect safe mode."); 7060 } 7061 7062 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7063 KeyEvent.KEYCODE_MENU); 7064 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 7065 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 7066 KeyEvent.KEYCODE_DPAD_CENTER); 7067 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 7068 InputManagerService.BTN_MOUSE); 7069 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7070 KeyEvent.KEYCODE_VOLUME_DOWN); 7071 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 7072 || volumeDownState > 0; 7073 try { 7074 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 7075 mSafeMode = true; 7076 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 7077 } 7078 } catch (IllegalArgumentException e) { 7079 } 7080 if (mSafeMode) { 7081 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 7082 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 7083 } else { 7084 Log.i(TAG, "SAFE MODE not enabled"); 7085 } 7086 mPolicy.setSafeMode(mSafeMode); 7087 return mSafeMode; 7088 } 7089 7090 public void displayReady() { 7091 displayReady(Display.DEFAULT_DISPLAY); 7092 7093 synchronized(mWindowMap) { 7094 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7095 readForcedDisplaySizeAndDensityLocked(displayContent); 7096 mDisplayReady = true; 7097 } 7098 7099 try { 7100 mActivityManager.updateConfiguration(null); 7101 } catch (RemoteException e) { 7102 } 7103 7104 synchronized(mWindowMap) { 7105 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 7106 PackageManager.FEATURE_TOUCHSCREEN); 7107 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 7108 } 7109 7110 try { 7111 mActivityManager.updateConfiguration(null); 7112 } catch (RemoteException e) { 7113 } 7114 } 7115 7116 private void displayReady(int displayId) { 7117 synchronized(mWindowMap) { 7118 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7119 if (displayContent != null) { 7120 mAnimator.addDisplayLocked(displayId); 7121 synchronized(displayContent.mDisplaySizeLock) { 7122 // Bootstrap the default logical display from the display manager. 7123 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7124 DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId); 7125 if (newDisplayInfo != null) { 7126 displayInfo.copyFrom(newDisplayInfo); 7127 } 7128 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; 7129 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; 7130 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; 7131 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; 7132 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; 7133 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; 7134 displayContent.mBaseDisplayRect.set(0, 0, 7135 displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight); 7136 } 7137 } 7138 } 7139 } 7140 7141 public void systemReady() { 7142 mPolicy.systemReady(); 7143 } 7144 7145 // ------------------------------------------------------------- 7146 // Async Handler 7147 // ------------------------------------------------------------- 7148 7149 final class H extends Handler { 7150 public static final int REPORT_FOCUS_CHANGE = 2; 7151 public static final int REPORT_LOSING_FOCUS = 3; 7152 public static final int DO_TRAVERSAL = 4; 7153 public static final int ADD_STARTING = 5; 7154 public static final int REMOVE_STARTING = 6; 7155 public static final int FINISHED_STARTING = 7; 7156 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 7157 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 7158 public static final int WINDOW_FREEZE_TIMEOUT = 11; 7159 7160 public static final int APP_TRANSITION_TIMEOUT = 13; 7161 public static final int PERSIST_ANIMATION_SCALE = 14; 7162 public static final int FORCE_GC = 15; 7163 public static final int ENABLE_SCREEN = 16; 7164 public static final int APP_FREEZE_TIMEOUT = 17; 7165 public static final int SEND_NEW_CONFIGURATION = 18; 7166 public static final int REPORT_WINDOWS_CHANGE = 19; 7167 public static final int DRAG_START_TIMEOUT = 20; 7168 public static final int DRAG_END_TIMEOUT = 21; 7169 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 7170 public static final int BOOT_TIMEOUT = 23; 7171 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 7172 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 7173 public static final int DO_ANIMATION_CALLBACK = 26; 7174 7175 public static final int DO_DISPLAY_ADDED = 27; 7176 public static final int DO_DISPLAY_REMOVED = 28; 7177 public static final int DO_DISPLAY_CHANGED = 29; 7178 7179 public static final int CLIENT_FREEZE_TIMEOUT = 30; 7180 public static final int TAP_OUTSIDE_STACK = 31; 7181 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 7182 7183 public static final int ALL_WINDOWS_DRAWN = 33; 7184 7185 public static final int NEW_ANIMATOR_SCALE = 34; 7186 7187 @Override 7188 public void handleMessage(Message msg) { 7189 if (DEBUG_WINDOW_TRACE) { 7190 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 7191 } 7192 switch (msg.what) { 7193 case REPORT_FOCUS_CHANGE: { 7194 WindowState lastFocus; 7195 WindowState newFocus; 7196 7197 synchronized(mWindowMap) { 7198 lastFocus = mLastFocus; 7199 newFocus = mCurrentFocus; 7200 if (lastFocus == newFocus) { 7201 // Focus is not changing, so nothing to do. 7202 return; 7203 } 7204 mLastFocus = newFocus; 7205 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus + 7206 " to " + newFocus); 7207 if (newFocus != null && lastFocus != null 7208 && !newFocus.isDisplayedLw()) { 7209 //Slog.i(TAG, "Delaying loss of focus..."); 7210 mLosingFocus.add(lastFocus); 7211 lastFocus = null; 7212 } 7213 } 7214 7215 //System.out.println("Changing focus from " + lastFocus 7216 // + " to " + newFocus); 7217 if (newFocus != null) { 7218 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus); 7219 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 7220 notifyFocusChanged(); 7221 } 7222 7223 if (lastFocus != null) { 7224 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus); 7225 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 7226 } 7227 } break; 7228 7229 case REPORT_LOSING_FOCUS: { 7230 ArrayList<WindowState> losers; 7231 7232 synchronized(mWindowMap) { 7233 losers = mLosingFocus; 7234 mLosingFocus = new ArrayList<WindowState>(); 7235 } 7236 7237 final int N = losers.size(); 7238 for (int i=0; i<N; i++) { 7239 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " + 7240 losers.get(i)); 7241 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 7242 } 7243 } break; 7244 7245 case DO_TRAVERSAL: { 7246 synchronized(mWindowMap) { 7247 mTraversalScheduled = false; 7248 performLayoutAndPlaceSurfacesLocked(); 7249 } 7250 } break; 7251 7252 case ADD_STARTING: { 7253 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7254 final StartingData sd = wtoken.startingData; 7255 7256 if (sd == null) { 7257 // Animation has been canceled... do nothing. 7258 return; 7259 } 7260 7261 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 7262 + wtoken + ": pkg=" + sd.pkg); 7263 7264 View view = null; 7265 try { 7266 view = mPolicy.addStartingWindow( 7267 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 7268 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags); 7269 } catch (Exception e) { 7270 Slog.w(TAG, "Exception when adding starting window", e); 7271 } 7272 7273 if (view != null) { 7274 boolean abort = false; 7275 7276 synchronized(mWindowMap) { 7277 if (wtoken.removed || wtoken.startingData == null) { 7278 // If the window was successfully added, then 7279 // we need to remove it. 7280 if (wtoken.startingWindow != null) { 7281 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7282 "Aborted starting " + wtoken 7283 + ": removed=" + wtoken.removed 7284 + " startingData=" + wtoken.startingData); 7285 wtoken.startingWindow = null; 7286 wtoken.startingData = null; 7287 abort = true; 7288 } 7289 } else { 7290 wtoken.startingView = view; 7291 } 7292 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7293 "Added starting " + wtoken 7294 + ": startingWindow=" 7295 + wtoken.startingWindow + " startingView=" 7296 + wtoken.startingView); 7297 } 7298 7299 if (abort) { 7300 try { 7301 mPolicy.removeStartingWindow(wtoken.token, view); 7302 } catch (Exception e) { 7303 Slog.w(TAG, "Exception when removing starting window", e); 7304 } 7305 } 7306 } 7307 } break; 7308 7309 case REMOVE_STARTING: { 7310 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7311 IBinder token = null; 7312 View view = null; 7313 synchronized (mWindowMap) { 7314 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7315 + wtoken + ": startingWindow=" 7316 + wtoken.startingWindow + " startingView=" 7317 + wtoken.startingView); 7318 if (wtoken.startingWindow != null) { 7319 view = wtoken.startingView; 7320 token = wtoken.token; 7321 wtoken.startingData = null; 7322 wtoken.startingView = null; 7323 wtoken.startingWindow = null; 7324 wtoken.startingDisplayed = false; 7325 } 7326 } 7327 if (view != null) { 7328 try { 7329 mPolicy.removeStartingWindow(token, view); 7330 } catch (Exception e) { 7331 Slog.w(TAG, "Exception when removing starting window", e); 7332 } 7333 } 7334 } break; 7335 7336 case FINISHED_STARTING: { 7337 IBinder token = null; 7338 View view = null; 7339 while (true) { 7340 synchronized (mWindowMap) { 7341 final int N = mFinishedStarting.size(); 7342 if (N <= 0) { 7343 break; 7344 } 7345 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7346 7347 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7348 "Finished starting " + wtoken 7349 + ": startingWindow=" + wtoken.startingWindow 7350 + " startingView=" + wtoken.startingView); 7351 7352 if (wtoken.startingWindow == null) { 7353 continue; 7354 } 7355 7356 view = wtoken.startingView; 7357 token = wtoken.token; 7358 wtoken.startingData = null; 7359 wtoken.startingView = null; 7360 wtoken.startingWindow = null; 7361 wtoken.startingDisplayed = false; 7362 } 7363 7364 try { 7365 mPolicy.removeStartingWindow(token, view); 7366 } catch (Exception e) { 7367 Slog.w(TAG, "Exception when removing starting window", e); 7368 } 7369 } 7370 } break; 7371 7372 case REPORT_APPLICATION_TOKEN_DRAWN: { 7373 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7374 7375 try { 7376 if (DEBUG_VISIBILITY) Slog.v( 7377 TAG, "Reporting drawn in " + wtoken); 7378 wtoken.appToken.windowsDrawn(); 7379 } catch (RemoteException ex) { 7380 } 7381 } break; 7382 7383 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7384 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7385 7386 boolean nowVisible = msg.arg1 != 0; 7387 boolean nowGone = msg.arg2 != 0; 7388 7389 try { 7390 if (DEBUG_VISIBILITY) Slog.v( 7391 TAG, "Reporting visible in " + wtoken 7392 + " visible=" + nowVisible 7393 + " gone=" + nowGone); 7394 if (nowVisible) { 7395 wtoken.appToken.windowsVisible(); 7396 } else { 7397 wtoken.appToken.windowsGone(); 7398 } 7399 } catch (RemoteException ex) { 7400 } 7401 } break; 7402 7403 case WINDOW_FREEZE_TIMEOUT: { 7404 // TODO(multidisplay): Can non-default displays rotate? 7405 synchronized (mWindowMap) { 7406 Slog.w(TAG, "Window freeze timeout expired."); 7407 final WindowList windows = getDefaultWindowListLocked(); 7408 int i = windows.size(); 7409 while (i > 0) { 7410 i--; 7411 WindowState w = windows.get(i); 7412 if (w.mOrientationChanging) { 7413 w.mOrientationChanging = false; 7414 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 7415 - mDisplayFreezeTime); 7416 Slog.w(TAG, "Force clearing orientation change: " + w); 7417 } 7418 } 7419 performLayoutAndPlaceSurfacesLocked(); 7420 } 7421 break; 7422 } 7423 7424 case APP_TRANSITION_TIMEOUT: { 7425 synchronized (mWindowMap) { 7426 if (mAppTransition.isTransitionSet()) { 7427 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT"); 7428 mAppTransition.setTimeout(); 7429 performLayoutAndPlaceSurfacesLocked(); 7430 } 7431 } 7432 break; 7433 } 7434 7435 case PERSIST_ANIMATION_SCALE: { 7436 Settings.Global.putFloat(mContext.getContentResolver(), 7437 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 7438 Settings.Global.putFloat(mContext.getContentResolver(), 7439 Settings.Global.TRANSITION_ANIMATION_SCALE, 7440 mTransitionAnimationScaleSetting); 7441 Settings.Global.putFloat(mContext.getContentResolver(), 7442 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting); 7443 break; 7444 } 7445 7446 case FORCE_GC: { 7447 synchronized (mWindowMap) { 7448 // Since we're holding both mWindowMap and mAnimator we don't need to 7449 // hold mAnimator.mLayoutToAnim. 7450 if (mAnimator.mAnimating || mAnimationScheduled) { 7451 // If we are animating, don't do the gc now but 7452 // delay a bit so we don't interrupt the animation. 7453 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 7454 return; 7455 } 7456 // If we are currently rotating the display, it will 7457 // schedule a new message when done. 7458 if (mDisplayFrozen) { 7459 return; 7460 } 7461 } 7462 Runtime.getRuntime().gc(); 7463 break; 7464 } 7465 7466 case ENABLE_SCREEN: { 7467 performEnableScreen(); 7468 break; 7469 } 7470 7471 case APP_FREEZE_TIMEOUT: { 7472 synchronized (mWindowMap) { 7473 Slog.w(TAG, "App freeze timeout expired."); 7474 final int numStacks = mStackIdToStack.size(); 7475 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 7476 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 7477 final ArrayList<Task> tasks = stack.getTasks(); 7478 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 7479 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 7480 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 7481 AppWindowToken tok = tokens.get(tokenNdx); 7482 if (tok.mAppAnimator.freezingScreen) { 7483 Slog.w(TAG, "Force clearing freeze: " + tok); 7484 unsetAppFreezingScreenLocked(tok, true, true); 7485 } 7486 } 7487 } 7488 } 7489 } 7490 break; 7491 } 7492 7493 case CLIENT_FREEZE_TIMEOUT: { 7494 synchronized (mWindowMap) { 7495 if (mClientFreezingScreen) { 7496 mClientFreezingScreen = false; 7497 mLastFinishedFreezeSource = "client-timeout"; 7498 stopFreezingDisplayLocked(); 7499 } 7500 } 7501 break; 7502 } 7503 7504 case SEND_NEW_CONFIGURATION: { 7505 removeMessages(SEND_NEW_CONFIGURATION); 7506 sendNewConfiguration(); 7507 break; 7508 } 7509 7510 case REPORT_WINDOWS_CHANGE: { 7511 if (mWindowsChanged) { 7512 synchronized (mWindowMap) { 7513 mWindowsChanged = false; 7514 } 7515 notifyWindowsChanged(); 7516 } 7517 break; 7518 } 7519 7520 case DRAG_START_TIMEOUT: { 7521 IBinder win = (IBinder)msg.obj; 7522 if (DEBUG_DRAG) { 7523 Slog.w(TAG, "Timeout starting drag by win " + win); 7524 } 7525 synchronized (mWindowMap) { 7526 // !!! TODO: ANR the app that has failed to start the drag in time 7527 if (mDragState != null) { 7528 mDragState.unregister(); 7529 mInputMonitor.updateInputWindowsLw(true /*force*/); 7530 mDragState.reset(); 7531 mDragState = null; 7532 } 7533 } 7534 break; 7535 } 7536 7537 case DRAG_END_TIMEOUT: { 7538 IBinder win = (IBinder)msg.obj; 7539 if (DEBUG_DRAG) { 7540 Slog.w(TAG, "Timeout ending drag to win " + win); 7541 } 7542 synchronized (mWindowMap) { 7543 // !!! TODO: ANR the drag-receiving app 7544 if (mDragState != null) { 7545 mDragState.mDragResult = false; 7546 mDragState.endDragLw(); 7547 } 7548 } 7549 break; 7550 } 7551 7552 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7553 notifyHardKeyboardStatusChange(); 7554 break; 7555 } 7556 7557 case BOOT_TIMEOUT: { 7558 performBootTimeout(); 7559 break; 7560 } 7561 7562 case WAITING_FOR_DRAWN_TIMEOUT: { 7563 IRemoteCallback callback = null; 7564 synchronized (mWindowMap) { 7565 Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn); 7566 mWaitingForDrawn.clear(); 7567 callback = mWaitingForDrawnCallback; 7568 mWaitingForDrawnCallback = null; 7569 } 7570 if (callback != null) { 7571 try { 7572 callback.sendResult(null); 7573 } catch (RemoteException e) { 7574 } 7575 } 7576 break; 7577 } 7578 7579 case SHOW_STRICT_MODE_VIOLATION: { 7580 showStrictModeViolation(msg.arg1, msg.arg2); 7581 break; 7582 } 7583 7584 case DO_ANIMATION_CALLBACK: { 7585 try { 7586 ((IRemoteCallback)msg.obj).sendResult(null); 7587 } catch (RemoteException e) { 7588 } 7589 break; 7590 } 7591 7592 case DO_DISPLAY_ADDED: 7593 handleDisplayAdded(msg.arg1); 7594 break; 7595 7596 case DO_DISPLAY_REMOVED: 7597 synchronized (mWindowMap) { 7598 handleDisplayRemovedLocked(msg.arg1); 7599 } 7600 break; 7601 7602 case DO_DISPLAY_CHANGED: 7603 synchronized (mWindowMap) { 7604 handleDisplayChangedLocked(msg.arg1); 7605 } 7606 break; 7607 7608 case TAP_OUTSIDE_STACK: { 7609 int stackId; 7610 synchronized (mWindowMap) { 7611 stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2); 7612 } 7613 if (stackId >= 0) { 7614 try { 7615 mActivityManager.setFocusedStack(stackId); 7616 } catch (RemoteException e) { 7617 } 7618 } 7619 } 7620 break; 7621 case NOTIFY_ACTIVITY_DRAWN: 7622 try { 7623 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 7624 } catch (RemoteException e) { 7625 } 7626 break; 7627 case ALL_WINDOWS_DRAWN: { 7628 IRemoteCallback callback; 7629 synchronized (mWindowMap) { 7630 callback = mWaitingForDrawnCallback; 7631 mWaitingForDrawnCallback = null; 7632 } 7633 if (callback != null) { 7634 try { 7635 callback.sendResult(null); 7636 } catch (RemoteException e) { 7637 } 7638 } 7639 } 7640 case NEW_ANIMATOR_SCALE: { 7641 float scale = getCurrentAnimatorScale(); 7642 ValueAnimator.setDurationScale(scale); 7643 Session session = (Session)msg.obj; 7644 if (session != null) { 7645 try { 7646 session.mCallback.onAnimatorScaleChanged(scale); 7647 } catch (RemoteException e) { 7648 } 7649 } else { 7650 ArrayList<IWindowSessionCallback> callbacks 7651 = new ArrayList<IWindowSessionCallback>(); 7652 synchronized (mWindowMap) { 7653 for (int i=0; i<mSessions.size(); i++) { 7654 callbacks.add(mSessions.valueAt(i).mCallback); 7655 } 7656 7657 } 7658 for (int i=0; i<callbacks.size(); i++) { 7659 try { 7660 callbacks.get(i).onAnimatorScaleChanged(scale); 7661 } catch (RemoteException e) { 7662 } 7663 } 7664 } 7665 } 7666 break; 7667 } 7668 if (DEBUG_WINDOW_TRACE) { 7669 Slog.v(TAG, "handleMessage: exit"); 7670 } 7671 } 7672 } 7673 7674 // ------------------------------------------------------------- 7675 // IWindowManager API 7676 // ------------------------------------------------------------- 7677 7678 @Override 7679 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, 7680 IInputContext inputContext) { 7681 if (client == null) throw new IllegalArgumentException("null client"); 7682 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7683 Session session = new Session(this, callback, client, inputContext); 7684 return session; 7685 } 7686 7687 @Override 7688 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7689 synchronized (mWindowMap) { 7690 // The focus for the client is the window immediately below 7691 // where we would place the input method window. 7692 int idx = findDesiredInputMethodWindowIndexLocked(false); 7693 if (idx > 0) { 7694 // TODO(multidisplay): IMEs are only supported on the default display. 7695 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 7696 if (DEBUG_INPUT_METHOD) { 7697 Slog.i(TAG, "Desired input method target: " + imFocus); 7698 Slog.i(TAG, "Current focus: " + mCurrentFocus); 7699 Slog.i(TAG, "Last focus: " + mLastFocus); 7700 } 7701 if (imFocus != null) { 7702 // This may be a starting window, in which case we still want 7703 // to count it as okay. 7704 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7705 && imFocus.mAppToken != null) { 7706 // The client has definitely started, so it really should 7707 // have a window in this app token. Let's look for it. 7708 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7709 WindowState w = imFocus.mAppToken.windows.get(i); 7710 if (w != imFocus) { 7711 Log.i(TAG, "Switching to real app window: " + w); 7712 imFocus = w; 7713 break; 7714 } 7715 } 7716 } 7717 if (DEBUG_INPUT_METHOD) { 7718 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7719 if (imFocus.mSession.mClient != null) { 7720 Slog.i(TAG, "IM target client binder: " 7721 + imFocus.mSession.mClient.asBinder()); 7722 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 7723 } 7724 } 7725 if (imFocus.mSession.mClient != null && 7726 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7727 return true; 7728 } 7729 } 7730 } 7731 7732 // Okay, how about this... what is the current focus? 7733 // It seems in some cases we may not have moved the IM 7734 // target window, such as when it was in a pop-up window, 7735 // so let's also look at the current focus. (An example: 7736 // go to Gmail, start searching so the keyboard goes up, 7737 // press home. Sometimes the IME won't go down.) 7738 // Would be nice to fix this more correctly, but it's 7739 // way at the end of a release, and this should be good enough. 7740 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 7741 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7742 return true; 7743 } 7744 } 7745 return false; 7746 } 7747 7748 @Override 7749 public void getInitialDisplaySize(int displayId, Point size) { 7750 synchronized (mWindowMap) { 7751 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7752 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7753 synchronized(displayContent.mDisplaySizeLock) { 7754 size.x = displayContent.mInitialDisplayWidth; 7755 size.y = displayContent.mInitialDisplayHeight; 7756 } 7757 } 7758 } 7759 } 7760 7761 @Override 7762 public void getBaseDisplaySize(int displayId, Point size) { 7763 synchronized (mWindowMap) { 7764 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7765 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7766 synchronized(displayContent.mDisplaySizeLock) { 7767 size.x = displayContent.mBaseDisplayWidth; 7768 size.y = displayContent.mBaseDisplayHeight; 7769 } 7770 } 7771 } 7772 } 7773 7774 @Override 7775 public void setForcedDisplaySize(int displayId, int width, int height) { 7776 if (mContext.checkCallingOrSelfPermission( 7777 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7778 PackageManager.PERMISSION_GRANTED) { 7779 throw new SecurityException("Must hold permission " + 7780 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7781 } 7782 if (displayId != Display.DEFAULT_DISPLAY) { 7783 throw new IllegalArgumentException("Can only set the default display"); 7784 } 7785 final long ident = Binder.clearCallingIdentity(); 7786 try { 7787 synchronized(mWindowMap) { 7788 // Set some sort of reasonable bounds on the size of the display that we 7789 // will try to emulate. 7790 final int MIN_WIDTH = 200; 7791 final int MIN_HEIGHT = 200; 7792 final int MAX_SCALE = 2; 7793 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7794 if (displayContent != null) { 7795 width = Math.min(Math.max(width, MIN_WIDTH), 7796 displayContent.mInitialDisplayWidth * MAX_SCALE); 7797 height = Math.min(Math.max(height, MIN_HEIGHT), 7798 displayContent.mInitialDisplayHeight * MAX_SCALE); 7799 setForcedDisplaySizeLocked(displayContent, width, height); 7800 Settings.Global.putString(mContext.getContentResolver(), 7801 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 7802 } 7803 } 7804 } finally { 7805 Binder.restoreCallingIdentity(ident); 7806 } 7807 } 7808 7809 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 7810 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 7811 Settings.Global.DISPLAY_SIZE_FORCED); 7812 if (sizeStr == null || sizeStr.length() == 0) { 7813 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 7814 } 7815 if (sizeStr != null && sizeStr.length() > 0) { 7816 final int pos = sizeStr.indexOf(','); 7817 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 7818 int width, height; 7819 try { 7820 width = Integer.parseInt(sizeStr.substring(0, pos)); 7821 height = Integer.parseInt(sizeStr.substring(pos+1)); 7822 synchronized(displayContent.mDisplaySizeLock) { 7823 if (displayContent.mBaseDisplayWidth != width 7824 || displayContent.mBaseDisplayHeight != height) { 7825 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 7826 displayContent.mBaseDisplayWidth = width; 7827 displayContent.mBaseDisplayHeight = height; 7828 } 7829 } 7830 } catch (NumberFormatException ex) { 7831 } 7832 } 7833 } 7834 String densityStr = Settings.Global.getString(mContext.getContentResolver(), 7835 Settings.Global.DISPLAY_DENSITY_FORCED); 7836 if (densityStr == null || densityStr.length() == 0) { 7837 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 7838 } 7839 if (densityStr != null && densityStr.length() > 0) { 7840 int density; 7841 try { 7842 density = Integer.parseInt(densityStr); 7843 synchronized(displayContent.mDisplaySizeLock) { 7844 if (displayContent.mBaseDisplayDensity != density) { 7845 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 7846 displayContent.mBaseDisplayDensity = density; 7847 } 7848 } 7849 } catch (NumberFormatException ex) { 7850 } 7851 } 7852 } 7853 7854 // displayContent must not be null 7855 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 7856 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7857 7858 synchronized(displayContent.mDisplaySizeLock) { 7859 displayContent.mBaseDisplayWidth = width; 7860 displayContent.mBaseDisplayHeight = height; 7861 } 7862 reconfigureDisplayLocked(displayContent); 7863 } 7864 7865 @Override 7866 public void clearForcedDisplaySize(int displayId) { 7867 if (mContext.checkCallingOrSelfPermission( 7868 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7869 PackageManager.PERMISSION_GRANTED) { 7870 throw new SecurityException("Must hold permission " + 7871 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7872 } 7873 if (displayId != Display.DEFAULT_DISPLAY) { 7874 throw new IllegalArgumentException("Can only set the default display"); 7875 } 7876 final long ident = Binder.clearCallingIdentity(); 7877 try { 7878 synchronized(mWindowMap) { 7879 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7880 if (displayContent != null) { 7881 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 7882 displayContent.mInitialDisplayHeight); 7883 Settings.Global.putString(mContext.getContentResolver(), 7884 Settings.Global.DISPLAY_SIZE_FORCED, ""); 7885 } 7886 } 7887 } finally { 7888 Binder.restoreCallingIdentity(ident); 7889 } 7890 } 7891 7892 @Override 7893 public int getInitialDisplayDensity(int displayId) { 7894 synchronized (mWindowMap) { 7895 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7896 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7897 synchronized(displayContent.mDisplaySizeLock) { 7898 return displayContent.mInitialDisplayDensity; 7899 } 7900 } 7901 } 7902 return -1; 7903 } 7904 7905 @Override 7906 public int getBaseDisplayDensity(int displayId) { 7907 synchronized (mWindowMap) { 7908 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7909 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7910 synchronized(displayContent.mDisplaySizeLock) { 7911 return displayContent.mBaseDisplayDensity; 7912 } 7913 } 7914 } 7915 return -1; 7916 } 7917 7918 @Override 7919 public void setForcedDisplayDensity(int displayId, int density) { 7920 if (mContext.checkCallingOrSelfPermission( 7921 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7922 PackageManager.PERMISSION_GRANTED) { 7923 throw new SecurityException("Must hold permission " + 7924 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7925 } 7926 if (displayId != Display.DEFAULT_DISPLAY) { 7927 throw new IllegalArgumentException("Can only set the default display"); 7928 } 7929 final long ident = Binder.clearCallingIdentity(); 7930 try { 7931 synchronized(mWindowMap) { 7932 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7933 if (displayContent != null) { 7934 setForcedDisplayDensityLocked(displayContent, density); 7935 Settings.Global.putString(mContext.getContentResolver(), 7936 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 7937 } 7938 } 7939 } finally { 7940 Binder.restoreCallingIdentity(ident); 7941 } 7942 } 7943 7944 // displayContent must not be null 7945 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 7946 Slog.i(TAG, "Using new display density: " + density); 7947 7948 synchronized(displayContent.mDisplaySizeLock) { 7949 displayContent.mBaseDisplayDensity = density; 7950 } 7951 reconfigureDisplayLocked(displayContent); 7952 } 7953 7954 @Override 7955 public void clearForcedDisplayDensity(int displayId) { 7956 if (mContext.checkCallingOrSelfPermission( 7957 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7958 PackageManager.PERMISSION_GRANTED) { 7959 throw new SecurityException("Must hold permission " + 7960 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7961 } 7962 if (displayId != Display.DEFAULT_DISPLAY) { 7963 throw new IllegalArgumentException("Can only set the default display"); 7964 } 7965 final long ident = Binder.clearCallingIdentity(); 7966 try { 7967 synchronized(mWindowMap) { 7968 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7969 if (displayContent != null) { 7970 setForcedDisplayDensityLocked(displayContent, 7971 displayContent.mInitialDisplayDensity); 7972 Settings.Global.putString(mContext.getContentResolver(), 7973 Settings.Global.DISPLAY_DENSITY_FORCED, ""); 7974 } 7975 } 7976 } finally { 7977 Binder.restoreCallingIdentity(ident); 7978 } 7979 } 7980 7981 // displayContent must not be null 7982 private void reconfigureDisplayLocked(DisplayContent displayContent) { 7983 // TODO: Multidisplay: for now only use with default display. 7984 configureDisplayPolicyLocked(displayContent); 7985 displayContent.layoutNeeded = true; 7986 7987 boolean configChanged = updateOrientationFromAppTokensLocked(false); 7988 mTempConfiguration.setToDefaults(); 7989 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 7990 if (computeScreenConfigurationLocked(mTempConfiguration)) { 7991 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 7992 configChanged = true; 7993 } 7994 } 7995 7996 if (configChanged) { 7997 mWaitingForConfig = true; 7998 startFreezingDisplayLocked(false, 0, 0); 7999 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8000 } 8001 8002 performLayoutAndPlaceSurfacesLocked(); 8003 } 8004 8005 private void configureDisplayPolicyLocked(DisplayContent displayContent) { 8006 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 8007 displayContent.mBaseDisplayWidth, 8008 displayContent.mBaseDisplayHeight, 8009 displayContent.mBaseDisplayDensity); 8010 8011 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8012 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 8013 displayInfo.overscanLeft, displayInfo.overscanTop, 8014 displayInfo.overscanRight, displayInfo.overscanBottom); 8015 } 8016 8017 @Override 8018 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 8019 if (mContext.checkCallingOrSelfPermission( 8020 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8021 PackageManager.PERMISSION_GRANTED) { 8022 throw new SecurityException("Must hold permission " + 8023 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8024 } 8025 final long ident = Binder.clearCallingIdentity(); 8026 try { 8027 synchronized(mWindowMap) { 8028 DisplayContent displayContent = getDisplayContentLocked(displayId); 8029 if (displayContent != null) { 8030 setOverscanLocked(displayContent, left, top, right, bottom); 8031 } 8032 } 8033 } finally { 8034 Binder.restoreCallingIdentity(ident); 8035 } 8036 } 8037 8038 private void setOverscanLocked(DisplayContent displayContent, 8039 int left, int top, int right, int bottom) { 8040 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8041 synchronized (displayContent.mDisplaySizeLock) { 8042 displayInfo.overscanLeft = left; 8043 displayInfo.overscanTop = top; 8044 displayInfo.overscanRight = right; 8045 displayInfo.overscanBottom = bottom; 8046 } 8047 8048 mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom); 8049 mDisplaySettings.writeSettingsLocked(); 8050 8051 reconfigureDisplayLocked(displayContent); 8052 } 8053 8054 // ------------------------------------------------------------- 8055 // Internals 8056 // ------------------------------------------------------------- 8057 8058 final WindowState windowForClientLocked(Session session, IWindow client, 8059 boolean throwOnError) { 8060 return windowForClientLocked(session, client.asBinder(), throwOnError); 8061 } 8062 8063 final WindowState windowForClientLocked(Session session, IBinder client, 8064 boolean throwOnError) { 8065 WindowState win = mWindowMap.get(client); 8066 if (localLOGV) Slog.v( 8067 TAG, "Looking up client " + client + ": " + win); 8068 if (win == null) { 8069 RuntimeException ex = new IllegalArgumentException( 8070 "Requested window " + client + " does not exist"); 8071 if (throwOnError) { 8072 throw ex; 8073 } 8074 Slog.w(TAG, "Failed looking up window", ex); 8075 return null; 8076 } 8077 if (session != null && win.mSession != session) { 8078 RuntimeException ex = new IllegalArgumentException( 8079 "Requested window " + client + " is in session " + 8080 win.mSession + ", not " + session); 8081 if (throwOnError) { 8082 throw ex; 8083 } 8084 Slog.w(TAG, "Failed looking up window", ex); 8085 return null; 8086 } 8087 8088 return win; 8089 } 8090 8091 final void rebuildAppWindowListLocked() { 8092 rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); 8093 } 8094 8095 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 8096 final WindowList windows = displayContent.getWindowList(); 8097 int NW = windows.size(); 8098 int i; 8099 int lastBelow = -1; 8100 int numRemoved = 0; 8101 8102 if (mRebuildTmp.length < NW) { 8103 mRebuildTmp = new WindowState[NW+10]; 8104 } 8105 8106 // First remove all existing app windows. 8107 i=0; 8108 while (i < NW) { 8109 WindowState w = windows.get(i); 8110 if (w.mAppToken != null) { 8111 WindowState win = windows.remove(i); 8112 win.mRebuilding = true; 8113 mRebuildTmp[numRemoved] = win; 8114 mWindowsChanged = true; 8115 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win); 8116 NW--; 8117 numRemoved++; 8118 continue; 8119 } else if (lastBelow == i-1) { 8120 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8121 lastBelow = i; 8122 } 8123 } 8124 i++; 8125 } 8126 8127 // Keep whatever windows were below the app windows still below, 8128 // by skipping them. 8129 lastBelow++; 8130 i = lastBelow; 8131 8132 // First add all of the exiting app tokens... these are no longer 8133 // in the main app list, but still have windows shown. We put them 8134 // in the back because now that the animation is over we no longer 8135 // will care about them. 8136 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 8137 final int numStacks = stacks.size(); 8138 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8139 AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens; 8140 int NT = exitingAppTokens.size(); 8141 for (int j = 0; j < NT; j++) { 8142 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 8143 } 8144 } 8145 8146 // And add in the still active app tokens in Z order. 8147 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8148 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8149 final int numTasks = tasks.size(); 8150 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 8151 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8152 final int numTokens = tokens.size(); 8153 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 8154 final AppWindowToken wtoken = tokens.get(tokenNdx); 8155 if (wtoken.mDeferRemoval) { 8156 continue; 8157 } 8158 i = reAddAppWindowsLocked(displayContent, i, wtoken); 8159 } 8160 } 8161 } 8162 8163 i -= lastBelow; 8164 if (i != numRemoved) { 8165 Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " + 8166 numRemoved + " windows but added " + i, 8167 new RuntimeException("here").fillInStackTrace()); 8168 for (i=0; i<numRemoved; i++) { 8169 WindowState ws = mRebuildTmp[i]; 8170 if (ws.mRebuilding) { 8171 StringWriter sw = new StringWriter(); 8172 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 8173 ws.dump(pw, "", true); 8174 pw.flush(); 8175 Slog.w(TAG, "This window was lost: " + ws); 8176 Slog.w(TAG, sw.toString()); 8177 ws.mWinAnimator.destroySurfaceLocked(); 8178 } 8179 } 8180 Slog.w(TAG, "Current app token list:"); 8181 dumpAppTokensLocked(); 8182 Slog.w(TAG, "Final window list:"); 8183 dumpWindowsLocked(); 8184 } 8185 } 8186 8187 private final void assignLayersLocked(WindowList windows) { 8188 int N = windows.size(); 8189 int curBaseLayer = 0; 8190 int curLayer = 0; 8191 int i; 8192 8193 if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows, 8194 new RuntimeException("here").fillInStackTrace()); 8195 8196 boolean anyLayerChanged = false; 8197 8198 for (i=0; i<N; i++) { 8199 final WindowState w = windows.get(i); 8200 final WindowStateAnimator winAnimator = w.mWinAnimator; 8201 boolean layerChanged = false; 8202 int oldLayer = w.mLayer; 8203 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 8204 || (i > 0 && w.mIsWallpaper)) { 8205 curLayer += WINDOW_LAYER_MULTIPLIER; 8206 w.mLayer = curLayer; 8207 } else { 8208 curBaseLayer = curLayer = w.mBaseLayer; 8209 w.mLayer = curLayer; 8210 } 8211 if (w.mLayer != oldLayer) { 8212 layerChanged = true; 8213 anyLayerChanged = true; 8214 } 8215 final AppWindowToken wtoken = w.mAppToken; 8216 oldLayer = winAnimator.mAnimLayer; 8217 if (w.mTargetAppToken != null) { 8218 winAnimator.mAnimLayer = 8219 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 8220 } else if (wtoken != null) { 8221 winAnimator.mAnimLayer = 8222 w.mLayer + wtoken.mAppAnimator.animLayerAdjustment; 8223 } else { 8224 winAnimator.mAnimLayer = w.mLayer; 8225 } 8226 if (w.mIsImWindow) { 8227 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 8228 } else if (w.mIsWallpaper) { 8229 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 8230 } 8231 if (winAnimator.mAnimLayer != oldLayer) { 8232 layerChanged = true; 8233 anyLayerChanged = true; 8234 } 8235 if (layerChanged && w.getStack().isDimming(winAnimator)) { 8236 // Force an animation pass just to update the mDimLayer layer. 8237 scheduleAnimationLocked(); 8238 } 8239 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 8240 + "mBase=" + w.mBaseLayer 8241 + " mLayer=" + w.mLayer 8242 + (wtoken == null ? 8243 "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment) 8244 + " =mAnimLayer=" + winAnimator.mAnimLayer); 8245 //System.out.println( 8246 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 8247 } 8248 8249 //TODO (multidisplay): Magnification is supported only for the default display. 8250 if (mAccessibilityController != null && anyLayerChanged 8251 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) { 8252 mAccessibilityController.onWindowLayersChangedLocked(); 8253 } 8254 } 8255 8256 private final void performLayoutAndPlaceSurfacesLocked() { 8257 int loopCount = 6; 8258 do { 8259 mTraversalScheduled = false; 8260 performLayoutAndPlaceSurfacesLockedLoop(); 8261 mH.removeMessages(H.DO_TRAVERSAL); 8262 loopCount--; 8263 } while (mTraversalScheduled && loopCount > 0); 8264 mInnerFields.mWallpaperActionPending = false; 8265 } 8266 8267 private boolean mInLayout = false; 8268 private final void performLayoutAndPlaceSurfacesLockedLoop() { 8269 if (mInLayout) { 8270 if (DEBUG) { 8271 throw new RuntimeException("Recursive call!"); 8272 } 8273 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 8274 + Debug.getCallers(3)); 8275 return; 8276 } 8277 8278 if (mWaitingForConfig) { 8279 // Our configuration has changed (most likely rotation), but we 8280 // don't yet have the complete configuration to report to 8281 // applications. Don't do any window layout until we have it. 8282 return; 8283 } 8284 8285 if (!mDisplayReady) { 8286 // Not yet initialized, nothing to do. 8287 return; 8288 } 8289 8290 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 8291 mInLayout = true; 8292 boolean recoveringMemory = false; 8293 8294 try { 8295 if (mForceRemoves != null) { 8296 recoveringMemory = true; 8297 // Wait a little bit for things to settle down, and off we go. 8298 for (int i=0; i<mForceRemoves.size(); i++) { 8299 WindowState ws = mForceRemoves.get(i); 8300 Slog.i(TAG, "Force removing: " + ws); 8301 removeWindowInnerLocked(ws.mSession, ws); 8302 } 8303 mForceRemoves = null; 8304 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 8305 Object tmp = new Object(); 8306 synchronized (tmp) { 8307 try { 8308 tmp.wait(250); 8309 } catch (InterruptedException e) { 8310 } 8311 } 8312 } 8313 } catch (RuntimeException e) { 8314 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 8315 } 8316 8317 try { 8318 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 8319 8320 mInLayout = false; 8321 8322 if (needsLayout()) { 8323 if (++mLayoutRepeatCount < 6) { 8324 requestTraversalLocked(); 8325 } else { 8326 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 8327 mLayoutRepeatCount = 0; 8328 } 8329 } else { 8330 mLayoutRepeatCount = 0; 8331 } 8332 8333 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 8334 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 8335 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE); 8336 } 8337 } catch (RuntimeException e) { 8338 mInLayout = false; 8339 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 8340 } 8341 8342 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 8343 } 8344 8345 private final void performLayoutLockedInner(final DisplayContent displayContent, 8346 boolean initial, boolean updateInputWindows) { 8347 if (!displayContent.layoutNeeded) { 8348 return; 8349 } 8350 displayContent.layoutNeeded = false; 8351 WindowList windows = displayContent.getWindowList(); 8352 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 8353 8354 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8355 final int dw = displayInfo.logicalWidth; 8356 final int dh = displayInfo.logicalHeight; 8357 8358 final int NFW = mFakeWindows.size(); 8359 for (int i=0; i<NFW; i++) { 8360 mFakeWindows.get(i).layout(dw, dh); 8361 } 8362 8363 final int N = windows.size(); 8364 int i; 8365 8366 if (DEBUG_LAYOUT) { 8367 Slog.v(TAG, "-------------------------------------"); 8368 Slog.v(TAG, "performLayout: needed=" 8369 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 8370 } 8371 8372 WindowStateAnimator universeBackground = null; 8373 8374 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); 8375 if (isDefaultDisplay) { 8376 // Not needed on non-default displays. 8377 mSystemDecorLayer = mPolicy.getSystemDecorLayerLw(); 8378 mScreenRect.set(0, 0, dw, dh); 8379 } 8380 8381 mPolicy.getContentRectLw(mTmpContentRect); 8382 displayContent.resize(mTmpContentRect); 8383 8384 int seq = mLayoutSeq+1; 8385 if (seq < 0) seq = 0; 8386 mLayoutSeq = seq; 8387 8388 boolean behindDream = false; 8389 8390 // First perform layout of any root windows (not attached 8391 // to another window). 8392 int topAttached = -1; 8393 for (i = N-1; i >= 0; i--) { 8394 final WindowState win = windows.get(i); 8395 8396 // Don't do layout of a window if it is not visible, or 8397 // soon won't be visible, to avoid wasting time and funky 8398 // changes while a window is animating away. 8399 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) 8400 || win.isGoneForLayoutLw(); 8401 8402 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 8403 Slog.v(TAG, "1ST PASS " + win 8404 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 8405 + " mLayoutAttached=" + win.mLayoutAttached 8406 + " screen changed=" + win.isConfigChanged()); 8407 final AppWindowToken atoken = win.mAppToken; 8408 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 8409 + win.mViewVisibility + " mRelayoutCalled=" 8410 + win.mRelayoutCalled + " hidden=" 8411 + win.mRootToken.hidden + " hiddenRequested=" 8412 + (atoken != null && atoken.hiddenRequested) 8413 + " mAttachedHidden=" + win.mAttachedHidden); 8414 else Slog.v(TAG, " VIS: mViewVisibility=" 8415 + win.mViewVisibility + " mRelayoutCalled=" 8416 + win.mRelayoutCalled + " hidden=" 8417 + win.mRootToken.hidden + " hiddenRequested=" 8418 + (atoken != null && atoken.hiddenRequested) 8419 + " mAttachedHidden=" + win.mAttachedHidden); 8420 } 8421 8422 // If this view is GONE, then skip it -- keep the current 8423 // frame, and let the caller know so they can ignore it 8424 // if they want. (We do the normal layout for INVISIBLE 8425 // windows, since that means "perform layout as normal, 8426 // just don't display"). 8427 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 8428 || ((win.isConfigChanged() || win.setInsetsChanged()) && 8429 ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || 8430 win.mAppToken != null && win.mAppToken.layoutConfigChanges)) 8431 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8432 if (!win.mLayoutAttached) { 8433 if (initial) { 8434 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8435 win.mContentChanged = false; 8436 } 8437 if (win.mAttrs.type == TYPE_DREAM) { 8438 // Don't layout windows behind a dream, so that if it 8439 // does stuff like hide the status bar we won't get a 8440 // bad transition when it goes away. 8441 behindDream = true; 8442 } 8443 win.mLayoutNeeded = false; 8444 win.prelayout(); 8445 mPolicy.layoutWindowLw(win, null); 8446 win.mLayoutSeq = seq; 8447 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8448 + win.mFrame + " mContainingFrame=" 8449 + win.mContainingFrame + " mDisplayFrame=" 8450 + win.mDisplayFrame); 8451 } else { 8452 if (topAttached < 0) topAttached = i; 8453 } 8454 } 8455 if (win.mViewVisibility == View.VISIBLE 8456 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 8457 && universeBackground == null) { 8458 universeBackground = win.mWinAnimator; 8459 } 8460 } 8461 8462 if (mAnimator.mUniverseBackground != universeBackground) { 8463 mFocusMayChange = true; 8464 mAnimator.mUniverseBackground = universeBackground; 8465 } 8466 8467 boolean attachedBehindDream = false; 8468 8469 // Now perform layout of attached windows, which usually 8470 // depend on the position of the window they are attached to. 8471 // XXX does not deal with windows that are attached to windows 8472 // that are themselves attached. 8473 for (i = topAttached; i >= 0; i--) { 8474 final WindowState win = windows.get(i); 8475 8476 if (win.mLayoutAttached) { 8477 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 8478 + " mHaveFrame=" + win.mHaveFrame 8479 + " mViewVisibility=" + win.mViewVisibility 8480 + " mRelayoutCalled=" + win.mRelayoutCalled); 8481 // If this view is GONE, then skip it -- keep the current 8482 // frame, and let the caller know so they can ignore it 8483 // if they want. (We do the normal layout for INVISIBLE 8484 // windows, since that means "perform layout as normal, 8485 // just don't display"). 8486 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) { 8487 continue; 8488 } 8489 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8490 || !win.mHaveFrame || win.mLayoutNeeded) { 8491 if (initial) { 8492 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8493 win.mContentChanged = false; 8494 } 8495 win.mLayoutNeeded = false; 8496 win.prelayout(); 8497 mPolicy.layoutWindowLw(win, win.mAttachedWindow); 8498 win.mLayoutSeq = seq; 8499 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8500 + win.mFrame + " mContainingFrame=" 8501 + win.mContainingFrame + " mDisplayFrame=" 8502 + win.mDisplayFrame); 8503 } 8504 } else if (win.mAttrs.type == TYPE_DREAM) { 8505 // Don't layout windows behind a dream, so that if it 8506 // does stuff like hide the status bar we won't get a 8507 // bad transition when it goes away. 8508 attachedBehindDream = behindDream; 8509 } 8510 } 8511 8512 // Window frames may have changed. Tell the input dispatcher about it. 8513 mInputMonitor.setUpdateInputWindowsNeededLw(); 8514 if (updateInputWindows) { 8515 mInputMonitor.updateInputWindowsLw(false /*force*/); 8516 } 8517 8518 mPolicy.finishLayoutLw(); 8519 } 8520 8521 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8522 // If the screen is currently frozen or off, then keep 8523 // it frozen/off until this window draws at its new 8524 // orientation. 8525 if (!okToDisplay()) { 8526 if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w); 8527 w.mOrientationChanging = true; 8528 w.mLastFreezeDuration = 0; 8529 mInnerFields.mOrientationChangeComplete = false; 8530 if (!mWindowsFreezingScreen) { 8531 mWindowsFreezingScreen = true; 8532 // XXX should probably keep timeout from 8533 // when we first froze the display. 8534 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8535 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 8536 WINDOW_FREEZE_TIMEOUT_DURATION); 8537 } 8538 } 8539 } 8540 8541 /** 8542 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8543 * @param windows List of windows on default display. 8544 * @return bitmap indicating if another pass through layout must be made. 8545 */ 8546 public int handleAppTransitionReadyLocked(WindowList windows) { 8547 int changes = 0; 8548 int i; 8549 int NN = mOpeningApps.size(); 8550 boolean goodToGo = true; 8551 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8552 "Checking " + NN + " opening apps (frozen=" 8553 + mDisplayFrozen + " timeout=" 8554 + mAppTransition.isTimeout() + ")..."); 8555 if (!mDisplayFrozen && !mAppTransition.isTimeout()) { 8556 // If the display isn't frozen, wait to do anything until 8557 // all of the apps are ready. Otherwise just go because 8558 // we'll unfreeze the display when everyone is ready. 8559 for (i=0; i<NN && goodToGo; i++) { 8560 AppWindowToken wtoken = mOpeningApps.get(i); 8561 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8562 "Check opening app=" + wtoken + ": allDrawn=" 8563 + wtoken.allDrawn + " startingDisplayed=" 8564 + wtoken.startingDisplayed + " startingMoved=" 8565 + wtoken.startingMoved); 8566 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8567 && !wtoken.startingMoved) { 8568 goodToGo = false; 8569 } 8570 } 8571 } 8572 if (goodToGo) { 8573 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8574 int transit = mAppTransition.getAppTransition(); 8575 if (mSkipAppTransitionAnimation) { 8576 transit = AppTransition.TRANSIT_UNSET; 8577 } 8578 mAppTransition.goodToGo(); 8579 mStartingIconInTransition = false; 8580 mSkipAppTransitionAnimation = false; 8581 8582 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8583 8584 rebuildAppWindowListLocked(); 8585 8586 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8587 WindowState oldWallpaper = 8588 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8589 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8590 ? null : mWallpaperTarget; 8591 8592 mInnerFields.mWallpaperMayChange = false; 8593 8594 // The top-most window will supply the layout params, 8595 // and we will determine it below. 8596 LayoutParams animLp = null; 8597 int bestAnimLayer = -1; 8598 boolean fullscreenAnim = false; 8599 boolean voiceInteraction = false; 8600 8601 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8602 "New wallpaper target=" + mWallpaperTarget 8603 + ", oldWallpaper=" + oldWallpaper 8604 + ", lower target=" + mLowerWallpaperTarget 8605 + ", upper target=" + mUpperWallpaperTarget); 8606 8607 boolean openingAppHasWallpaper = false; 8608 boolean closingAppHasWallpaper = false; 8609 final AppWindowToken lowerWallpaperAppToken; 8610 final AppWindowToken upperWallpaperAppToken; 8611 if (mLowerWallpaperTarget == null) { 8612 lowerWallpaperAppToken = upperWallpaperAppToken = null; 8613 } else { 8614 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken; 8615 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken; 8616 } 8617 8618 // Do a first pass through the tokens for two 8619 // things: 8620 // (1) Determine if both the closing and opening 8621 // app token sets are wallpaper targets, in which 8622 // case special animations are needed 8623 // (since the wallpaper needs to stay static 8624 // behind them). 8625 // (2) Find the layout params of the top-most 8626 // application window in the tokens, which is 8627 // what will control the animation theme. 8628 final int NC = mClosingApps.size(); 8629 NN = NC + mOpeningApps.size(); 8630 for (i=0; i<NN; i++) { 8631 final AppWindowToken wtoken; 8632 if (i < NC) { 8633 wtoken = mClosingApps.get(i); 8634 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8635 closingAppHasWallpaper = true; 8636 } 8637 } else { 8638 wtoken = mOpeningApps.get(i - NC); 8639 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8640 openingAppHasWallpaper = true; 8641 } 8642 } 8643 8644 voiceInteraction |= wtoken.voiceInteraction; 8645 8646 if (wtoken.appFullscreen) { 8647 WindowState ws = wtoken.findMainWindow(); 8648 if (ws != null) { 8649 animLp = ws.mAttrs; 8650 bestAnimLayer = ws.mLayer; 8651 fullscreenAnim = true; 8652 } 8653 } else if (!fullscreenAnim) { 8654 WindowState ws = wtoken.findMainWindow(); 8655 if (ws != null) { 8656 if (ws.mLayer > bestAnimLayer) { 8657 animLp = ws.mAttrs; 8658 bestAnimLayer = ws.mLayer; 8659 } 8660 } 8661 } 8662 } 8663 8664 mAnimateWallpaperWithTarget = false; 8665 if (closingAppHasWallpaper && openingAppHasWallpaper) { 8666 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!"); 8667 switch (transit) { 8668 case AppTransition.TRANSIT_ACTIVITY_OPEN: 8669 case AppTransition.TRANSIT_TASK_OPEN: 8670 case AppTransition.TRANSIT_TASK_TO_FRONT: 8671 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN; 8672 break; 8673 case AppTransition.TRANSIT_ACTIVITY_CLOSE: 8674 case AppTransition.TRANSIT_TASK_CLOSE: 8675 case AppTransition.TRANSIT_TASK_TO_BACK: 8676 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; 8677 break; 8678 } 8679 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); 8680 } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty() 8681 && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 8682 // We are transitioning from an activity with 8683 // a wallpaper to one without. 8684 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; 8685 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8686 "New transit away from wallpaper: " + transit); 8687 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) { 8688 // We are transitioning from an activity without 8689 // a wallpaper to now showing the wallpaper 8690 transit = AppTransition.TRANSIT_WALLPAPER_OPEN; 8691 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8692 "New transit into wallpaper: " + transit); 8693 } else { 8694 mAnimateWallpaperWithTarget = true; 8695 } 8696 8697 // If all closing windows are obscured, then there is 8698 // no need to do an animation. This is the case, for 8699 // example, when this transition is being done behind 8700 // the lock screen. 8701 if (!mPolicy.allowAppAnimationsLw()) { 8702 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8703 "Animations disallowed by keyguard or dream."); 8704 animLp = null; 8705 } 8706 8707 AppWindowToken topOpeningApp = null; 8708 int topOpeningLayer = 0; 8709 8710 NN = mOpeningApps.size(); 8711 for (i=0; i<NN; i++) { 8712 AppWindowToken wtoken = mOpeningApps.get(i); 8713 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 8714 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 8715 appAnimator.clearThumbnail(); 8716 wtoken.inPendingTransaction = false; 8717 appAnimator.animation = null; 8718 setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction); 8719 wtoken.updateReportedVisibilityLocked(); 8720 wtoken.waitingToShow = false; 8721 8722 appAnimator.mAllAppWinAnimators.clear(); 8723 final int N = wtoken.allAppWindows.size(); 8724 for (int j = 0; j < N; j++) { 8725 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 8726 } 8727 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 8728 8729 if (animLp != null) { 8730 int layer = -1; 8731 for (int j=0; j<wtoken.windows.size(); j++) { 8732 WindowState win = wtoken.windows.get(j); 8733 if (win.mWinAnimator.mAnimLayer > layer) { 8734 layer = win.mWinAnimator.mAnimLayer; 8735 } 8736 } 8737 if (topOpeningApp == null || layer > topOpeningLayer) { 8738 topOpeningApp = wtoken; 8739 topOpeningLayer = layer; 8740 } 8741 } 8742 } 8743 NN = mClosingApps.size(); 8744 for (i=0; i<NN; i++) { 8745 AppWindowToken wtoken = mClosingApps.get(i); 8746 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken); 8747 wtoken.mAppAnimator.clearThumbnail(); 8748 wtoken.inPendingTransaction = false; 8749 wtoken.mAppAnimator.animation = null; 8750 setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction); 8751 wtoken.updateReportedVisibilityLocked(); 8752 wtoken.waitingToHide = false; 8753 // Force the allDrawn flag, because we want to start 8754 // this guy's animations regardless of whether it's 8755 // gotten drawn. 8756 wtoken.allDrawn = true; 8757 wtoken.deferClearAllDrawn = false; 8758 } 8759 8760 boolean useAlternateThumbnailAnimation = true; 8761 AppWindowAnimator appAnimator = 8762 topOpeningApp == null ? null : topOpeningApp.mAppAnimator; 8763 Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail(); 8764 if (!useAlternateThumbnailAnimation && nextAppTransitionThumbnail != null 8765 && appAnimator != null && appAnimator.animation != null) { 8766 // This thumbnail animation is very special, we need to have 8767 // an extra surface with the thumbnail included with the animation. 8768 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(), 8769 nextAppTransitionThumbnail.getHeight()); 8770 try { 8771 // TODO(multi-display): support other displays 8772 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8773 final Display display = displayContent.getDisplay(); 8774 SurfaceControl surfaceControl = new SurfaceControl(mFxSession, 8775 "thumbnail anim", 8776 dirty.width(), dirty.height(), 8777 PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 8778 surfaceControl.setLayerStack(display.getLayerStack()); 8779 appAnimator.thumbnail = surfaceControl; 8780 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE"); 8781 Surface drawSurface = new Surface(); 8782 drawSurface.copyFrom(surfaceControl); 8783 Canvas c = drawSurface.lockCanvas(dirty); 8784 c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null); 8785 drawSurface.unlockCanvasAndPost(c); 8786 drawSurface.release(); 8787 appAnimator.thumbnailLayer = topOpeningLayer; 8788 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 8789 Animation anim = mAppTransition.createThumbnailScaleAnimationLocked( 8790 displayInfo.appWidth, displayInfo.appHeight, transit); 8791 appAnimator.thumbnailAnimation = anim; 8792 anim.restrictDuration(MAX_ANIMATION_DURATION); 8793 anim.scaleCurrentDuration(getTransitionAnimationScaleLocked()); 8794 Point p = new Point(); 8795 mAppTransition.getStartingPoint(p); 8796 appAnimator.thumbnailX = p.x; 8797 appAnimator.thumbnailY = p.y; 8798 } catch (OutOfResourcesException e) { 8799 Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width() 8800 + " h=" + dirty.height(), e); 8801 appAnimator.clearThumbnail(); 8802 } 8803 } 8804 8805 mAppTransition.postAnimationCallback(); 8806 mAppTransition.clear(); 8807 8808 mOpeningApps.clear(); 8809 mClosingApps.clear(); 8810 8811 // This has changed the visibility of windows, so perform 8812 // a new layout to get them all up-to-date. 8813 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT 8814 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 8815 getDefaultDisplayContentLocked().layoutNeeded = true; 8816 8817 // TODO(multidisplay): IMEs are only supported on the default display. 8818 if (windows == getDefaultWindowListLocked() 8819 && !moveInputMethodWindowsIfNeededLocked(true)) { 8820 assignLayersLocked(windows); 8821 } 8822 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/); 8823 mFocusMayChange = false; 8824 } 8825 8826 return changes; 8827 } 8828 8829 /** 8830 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8831 * @return bitmap indicating if another pass through layout must be made. 8832 */ 8833 private int handleAnimatingStoppedAndTransitionLocked() { 8834 int changes = 0; 8835 8836 mAppTransition.setIdle(); 8837 // Restore window app tokens to the ActivityManager views 8838 ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks(); 8839 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 8840 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8841 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 8842 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8843 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 8844 tokens.get(tokenNdx).sendingToBottom = false; 8845 } 8846 } 8847 } 8848 rebuildAppWindowListLocked(); 8849 8850 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8851 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 8852 "Wallpaper layer changed: assigning layers + relayout"); 8853 moveInputMethodWindowsIfNeededLocked(true); 8854 mInnerFields.mWallpaperMayChange = true; 8855 // Since the window list has been rebuilt, focus might 8856 // have to be recomputed since the actual order of windows 8857 // might have changed again. 8858 mFocusMayChange = true; 8859 8860 return changes; 8861 } 8862 8863 private void updateResizingWindows(final WindowState w) { 8864 final WindowStateAnimator winAnimator = w.mWinAnimator; 8865 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { 8866 w.setInsetsChanged(); 8867 boolean configChanged = w.isConfigChanged(); 8868 if (DEBUG_CONFIGURATION && configChanged) { 8869 Slog.v(TAG, "Win " + w + " config changed: " 8870 + mCurConfiguration); 8871 } 8872 if (localLOGV) Slog.v(TAG, "Resizing " + w 8873 + ": configChanged=" + configChanged 8874 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8875 w.mLastFrame.set(w.mFrame); 8876 if (w.mContentInsetsChanged 8877 || w.mVisibleInsetsChanged 8878 || winAnimator.mSurfaceResized 8879 || configChanged) { 8880 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8881 Slog.v(TAG, "Resize reasons for w=" + w + ": " 8882 + " contentInsetsChanged=" + w.mContentInsetsChanged 8883 + " " + w.mContentInsets.toShortString() 8884 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8885 + " " + w.mVisibleInsets.toShortString() 8886 + " surfaceResized=" + winAnimator.mSurfaceResized 8887 + " configChanged=" + configChanged); 8888 } 8889 8890 w.mLastOverscanInsets.set(w.mOverscanInsets); 8891 w.mLastContentInsets.set(w.mContentInsets); 8892 w.mLastVisibleInsets.set(w.mVisibleInsets); 8893 makeWindowFreezingScreenIfNeededLocked(w); 8894 // If the orientation is changing, then we need to 8895 // hold off on unfreezing the display until this 8896 // window has been redrawn; to do that, we need 8897 // to go through the process of getting informed 8898 // by the application when it has finished drawing. 8899 if (w.mOrientationChanging) { 8900 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 8901 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 8902 + w + ", surface " + winAnimator.mSurfaceControl); 8903 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 8904 if (w.mAppToken != null) { 8905 w.mAppToken.allDrawn = false; 8906 w.mAppToken.deferClearAllDrawn = false; 8907 } 8908 } 8909 if (!mResizingWindows.contains(w)) { 8910 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8911 "Resizing window " + w + " to " + winAnimator.mSurfaceW 8912 + "x" + winAnimator.mSurfaceH); 8913 mResizingWindows.add(w); 8914 } 8915 } else if (w.mOrientationChanging) { 8916 if (w.isDrawnLw()) { 8917 if (DEBUG_ORIENTATION) Slog.v(TAG, 8918 "Orientation not waiting for draw in " 8919 + w + ", surface " + winAnimator.mSurfaceControl); 8920 w.mOrientationChanging = false; 8921 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 8922 - mDisplayFreezeTime); 8923 } 8924 } 8925 } 8926 } 8927 8928 /** 8929 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8930 * 8931 * @param w WindowState this method is applied to. 8932 * @param currentTime The time which animations use for calculating transitions. 8933 * @param innerDw Width of app window. 8934 * @param innerDh Height of app window. 8935 */ 8936 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 8937 final int innerDw, final int innerDh) { 8938 final WindowManager.LayoutParams attrs = w.mAttrs; 8939 final int attrFlags = attrs.flags; 8940 final boolean canBeSeen = w.isDisplayedLw(); 8941 final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8942 8943 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8944 // This window completely covers everything behind it, 8945 // so we want to leave all of them as undimmed (for 8946 // performance reasons). 8947 mInnerFields.mObscured = true; 8948 } 8949 8950 if (w.mHasSurface) { 8951 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8952 mInnerFields.mHoldScreen = w.mSession; 8953 } 8954 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 8955 && mInnerFields.mScreenBrightness < 0) { 8956 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 8957 } 8958 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 8959 && mInnerFields.mButtonBrightness < 0) { 8960 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 8961 } 8962 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0 8963 && mInnerFields.mUserActivityTimeout < 0) { 8964 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout; 8965 } 8966 8967 final int type = attrs.type; 8968 if (canBeSeen 8969 && (type == TYPE_SYSTEM_DIALOG 8970 || type == TYPE_RECENTS_OVERLAY 8971 || type == TYPE_SYSTEM_ERROR 8972 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) { 8973 mInnerFields.mSyswin = true; 8974 } 8975 8976 if (canBeSeen) { 8977 // This function assumes that the contents of the default display are 8978 // processed first before secondary displays. 8979 final DisplayContent displayContent = w.getDisplayContent(); 8980 if (displayContent != null && displayContent.isDefaultDisplay) { 8981 // While a dream or keyguard is showing, obscure ordinary application 8982 // content on secondary displays (by forcibly enabling mirroring unless 8983 // there is other content we want to show) but still allow opaque 8984 // keyguard dialogs to be shown. 8985 if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 8986 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true; 8987 } 8988 mInnerFields.mDisplayHasContent = true; 8989 } else if (displayContent != null && 8990 (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays 8991 || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) { 8992 // Allow full screen keyguard presentation dialogs to be seen. 8993 mInnerFields.mDisplayHasContent = true; 8994 } 8995 } 8996 } 8997 } 8998 8999 private void handleFlagDimBehind(WindowState w) { 9000 final WindowManager.LayoutParams attrs = w.mAttrs; 9001 if ((attrs.flags & FLAG_DIM_BEHIND) != 0 9002 && w.isDisplayedLw() 9003 && !w.mExiting) { 9004 final WindowStateAnimator winAnimator = w.mWinAnimator; 9005 final TaskStack stack = w.getStack(); 9006 stack.setDimmingTag(); 9007 if (!stack.isDimming(winAnimator)) { 9008 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming."); 9009 stack.startDimmingIfNeeded(winAnimator); 9010 } 9011 } 9012 } 9013 9014 private void updateAllDrawnLocked(DisplayContent displayContent) { 9015 // See if any windows have been drawn, so they (and others 9016 // associated with them) can now be shown. 9017 ArrayList<TaskStack> stacks = displayContent.getStacks(); 9018 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 9019 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9020 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9021 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9022 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9023 final AppWindowToken wtoken = tokens.get(tokenNdx); 9024 if (!wtoken.allDrawn) { 9025 int numInteresting = wtoken.numInterestingWindows; 9026 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 9027 if (DEBUG_VISIBILITY) Slog.v(TAG, 9028 "allDrawn: " + wtoken 9029 + " interesting=" + numInteresting 9030 + " drawn=" + wtoken.numDrawnWindows); 9031 wtoken.allDrawn = true; 9032 mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget(); 9033 } 9034 } 9035 } 9036 } 9037 } 9038 } 9039 9040 // "Something has changed! Let's make it correct now." 9041 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 9042 if (DEBUG_WINDOW_TRACE) { 9043 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 9044 + Debug.getCallers(3)); 9045 } 9046 9047 final long currentTime = SystemClock.uptimeMillis(); 9048 9049 int i; 9050 9051 if (mFocusMayChange) { 9052 mFocusMayChange = false; 9053 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 9054 false /*updateInputWindows*/); 9055 } 9056 9057 // Initialize state of exiting tokens. 9058 final int numDisplays = mDisplayContents.size(); 9059 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9060 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9061 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) { 9062 displayContent.mExitingTokens.get(i).hasVisible = false; 9063 } 9064 } 9065 9066 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9067 // Initialize state of exiting applications. 9068 final AppTokenList exitingAppTokens = 9069 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9070 for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9071 exitingAppTokens.get(tokenNdx).hasVisible = false; 9072 } 9073 } 9074 9075 mInnerFields.mHoldScreen = null; 9076 mInnerFields.mScreenBrightness = -1; 9077 mInnerFields.mButtonBrightness = -1; 9078 mInnerFields.mUserActivityTimeout = -1; 9079 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false; 9080 9081 mTransactionSequence++; 9082 9083 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked(); 9084 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 9085 final int defaultDw = defaultInfo.logicalWidth; 9086 final int defaultDh = defaultInfo.logicalHeight; 9087 9088 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9089 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 9090 SurfaceControl.openTransaction(); 9091 try { 9092 9093 if (mWatermark != null) { 9094 mWatermark.positionSurface(defaultDw, defaultDh); 9095 } 9096 if (mStrictModeFlash != null) { 9097 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 9098 } 9099 9100 boolean focusDisplayed = false; 9101 9102 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9103 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9104 boolean updateAllDrawn = false; 9105 WindowList windows = displayContent.getWindowList(); 9106 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9107 final int displayId = displayContent.getDisplayId(); 9108 final int dw = displayInfo.logicalWidth; 9109 final int dh = displayInfo.logicalHeight; 9110 final int innerDw = displayInfo.appWidth; 9111 final int innerDh = displayInfo.appHeight; 9112 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 9113 9114 // Reset for each display. 9115 mInnerFields.mDisplayHasContent = false; 9116 9117 int repeats = 0; 9118 do { 9119 repeats++; 9120 if (repeats > 6) { 9121 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 9122 displayContent.layoutNeeded = false; 9123 break; 9124 } 9125 9126 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 9127 displayContent.pendingLayoutChanges); 9128 9129 if ((displayContent.pendingLayoutChanges & 9130 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 && 9131 (adjustWallpaperWindowsLocked() & 9132 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 9133 assignLayersLocked(windows); 9134 displayContent.layoutNeeded = true; 9135 } 9136 9137 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 9138 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 9139 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 9140 if (updateOrientationFromAppTokensLocked(true)) { 9141 displayContent.layoutNeeded = true; 9142 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9143 } 9144 } 9145 9146 if ((displayContent.pendingLayoutChanges 9147 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9148 displayContent.layoutNeeded = true; 9149 } 9150 9151 // FIRST LOOP: Perform a layout, if needed. 9152 if (repeats < 4) { 9153 performLayoutLockedInner(displayContent, repeats == 1, 9154 false /*updateInputWindows*/); 9155 } else { 9156 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 9157 } 9158 9159 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 9160 // it is animating. 9161 displayContent.pendingLayoutChanges = 0; 9162 9163 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 9164 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 9165 9166 if (isDefaultDisplay) { 9167 mPolicy.beginPostLayoutPolicyLw(dw, dh); 9168 for (i = windows.size() - 1; i >= 0; i--) { 9169 WindowState w = windows.get(i); 9170 if (w.mHasSurface) { 9171 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); 9172 } 9173 } 9174 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 9175 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 9176 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges); 9177 } 9178 } while (displayContent.pendingLayoutChanges != 0); 9179 9180 mInnerFields.mObscured = false; 9181 mInnerFields.mSyswin = false; 9182 displayContent.resetDimming(); 9183 9184 // Only used if default window 9185 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 9186 9187 final int N = windows.size(); 9188 for (i=N-1; i>=0; i--) { 9189 WindowState w = windows.get(i); 9190 final TaskStack stack = w.getStack(); 9191 if (stack == null) { 9192 continue; 9193 } 9194 9195 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 9196 9197 // Update effect. 9198 w.mObscured = mInnerFields.mObscured; 9199 if (!mInnerFields.mObscured) { 9200 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 9201 } 9202 9203 if (!stack.testDimmingTag()) { 9204 handleFlagDimBehind(w); 9205 } 9206 9207 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 9208 && w.isVisibleLw()) { 9209 // This is the wallpaper target and its obscured state 9210 // changed... make sure the current wallaper's visibility 9211 // has been updated accordingly. 9212 updateWallpaperVisibilityLocked(); 9213 } 9214 9215 final WindowStateAnimator winAnimator = w.mWinAnimator; 9216 9217 // If the window has moved due to its containing 9218 // content frame changing, then we'd like to animate 9219 // it. 9220 if (w.mHasSurface && w.shouldAnimateMove()) { 9221 // Frame has moved, containing content frame 9222 // has also moved, and we're not currently animating... 9223 // let's do something. 9224 Animation a = AnimationUtils.loadAnimation(mContext, 9225 com.android.internal.R.anim.window_move_from_decor); 9226 winAnimator.setAnimation(a); 9227 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 9228 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 9229 9230 //TODO (multidisplay): Accessibility supported only for the default display. 9231 if (mAccessibilityController != null 9232 && displayId == Display.DEFAULT_DISPLAY) { 9233 mAccessibilityController.onSomeWindowResizedOrMovedLocked(); 9234 } 9235 9236 try { 9237 w.mClient.moved(w.mFrame.left, w.mFrame.top); 9238 } catch (RemoteException e) { 9239 } 9240 } 9241 9242 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 9243 w.mContentChanged = false; 9244 9245 // Moved from updateWindowsAndWallpaperLocked(). 9246 if (w.mHasSurface) { 9247 // Take care of the window being ready to display. 9248 final boolean committed = 9249 winAnimator.commitFinishDrawingLocked(currentTime); 9250 if (isDefaultDisplay && committed) { 9251 if (w.mAttrs.type == TYPE_DREAM) { 9252 // HACK: When a dream is shown, it may at that 9253 // point hide the lock screen. So we need to 9254 // redo the layout to let the phone window manager 9255 // make this happen. 9256 displayContent.pendingLayoutChanges |= 9257 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9258 if (DEBUG_LAYOUT_REPEATS) { 9259 debugLayoutRepeats( 9260 "dream and commitFinishDrawingLocked true", 9261 displayContent.pendingLayoutChanges); 9262 } 9263 } 9264 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 9265 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 9266 "First draw done in potential wallpaper target " + w); 9267 mInnerFields.mWallpaperMayChange = true; 9268 displayContent.pendingLayoutChanges |= 9269 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9270 if (DEBUG_LAYOUT_REPEATS) { 9271 debugLayoutRepeats( 9272 "wallpaper and commitFinishDrawingLocked true", 9273 displayContent.pendingLayoutChanges); 9274 } 9275 } 9276 } 9277 9278 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 9279 9280 final AppWindowToken atoken = w.mAppToken; 9281 if (DEBUG_STARTING_WINDOW && atoken != null 9282 && w == atoken.startingWindow) { 9283 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 9284 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 9285 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 9286 } 9287 if (atoken != null 9288 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 9289 if (atoken.lastTransactionSequence != mTransactionSequence) { 9290 atoken.lastTransactionSequence = mTransactionSequence; 9291 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 9292 atoken.startingDisplayed = false; 9293 } 9294 if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 9295 && !w.mExiting && !w.mDestroying) { 9296 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 9297 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 9298 + ", isAnimating=" + winAnimator.isAnimating()); 9299 if (!w.isDrawnLw()) { 9300 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl 9301 + " pv=" + w.mPolicyVisibility 9302 + " mDrawState=" + winAnimator.mDrawState 9303 + " ah=" + w.mAttachedHidden 9304 + " th=" + atoken.hiddenRequested 9305 + " a=" + winAnimator.mAnimating); 9306 } 9307 } 9308 if (w != atoken.startingWindow) { 9309 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 9310 atoken.numInterestingWindows++; 9311 if (w.isDrawnLw()) { 9312 atoken.numDrawnWindows++; 9313 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 9314 "tokenMayBeDrawn: " + atoken 9315 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 9316 + " mAppFreezing=" + w.mAppFreezing); 9317 updateAllDrawn = true; 9318 } 9319 } 9320 } else if (w.isDrawnLw()) { 9321 atoken.startingDisplayed = true; 9322 } 9323 } 9324 } 9325 } 9326 9327 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 9328 && w.isDisplayedLw()) { 9329 focusDisplayed = true; 9330 } 9331 9332 updateResizingWindows(w); 9333 } 9334 9335 mDisplayManagerInternal.setDisplayHasContent(displayId, 9336 mInnerFields.mDisplayHasContent, 9337 true /* inTraversal, must call performTraversalInTrans... below */); 9338 9339 getDisplayContentLocked(displayId).stopDimmingIfNeeded(); 9340 9341 if (updateAllDrawn) { 9342 updateAllDrawnLocked(displayContent); 9343 } 9344 } 9345 9346 if (focusDisplayed) { 9347 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 9348 } 9349 9350 // Give the display manager a chance to adjust properties 9351 // like display rotation if it needs to. 9352 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 9353 9354 } catch (RuntimeException e) { 9355 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 9356 } finally { 9357 SurfaceControl.closeTransaction(); 9358 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9359 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 9360 } 9361 9362 final WindowList defaultWindows = defaultDisplay.getWindowList(); 9363 9364 // If we are ready to perform an app transition, check through 9365 // all of the app tokens to be shown and see if they are ready 9366 // to go. 9367 if (mAppTransition.isReady()) { 9368 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 9369 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 9370 defaultDisplay.pendingLayoutChanges); 9371 } 9372 9373 if (!mAnimator.mAnimating && mAppTransition.isRunning()) { 9374 // We have finished the animation of an app transition. To do 9375 // this, we have delayed a lot of operations like showing and 9376 // hiding apps, moving apps in Z-order, etc. The app token list 9377 // reflects the correct Z-order, but the window list may now 9378 // be out of sync with it. So here we will just rebuild the 9379 // entire app window list. Fun! 9380 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 9381 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 9382 defaultDisplay.pendingLayoutChanges); 9383 } 9384 9385 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 9386 && !mAppTransition.isReady()) { 9387 // At this point, there was a window with a wallpaper that 9388 // was force hiding other windows behind it, but now it 9389 // is going away. This may be simple -- just animate 9390 // away the wallpaper and its window -- or it may be 9391 // hard -- the wallpaper now needs to be shown behind 9392 // something that was hidden. 9393 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9394 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 9395 defaultDisplay.pendingLayoutChanges); 9396 } 9397 mInnerFields.mWallpaperForceHidingChanged = false; 9398 9399 if (mInnerFields.mWallpaperMayChange) { 9400 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting"); 9401 defaultDisplay.pendingLayoutChanges |= 9402 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9403 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange", 9404 defaultDisplay.pendingLayoutChanges); 9405 } 9406 9407 if (mFocusMayChange) { 9408 mFocusMayChange = false; 9409 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 9410 false /*updateInputWindows*/)) { 9411 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 9412 } 9413 } 9414 9415 if (needsLayout()) { 9416 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9417 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 9418 defaultDisplay.pendingLayoutChanges); 9419 } 9420 9421 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 9422 WindowState win = mResizingWindows.get(i); 9423 if (win.mAppFreezing) { 9424 // Don't remove this window until rotation has completed. 9425 continue; 9426 } 9427 win.reportResized(); 9428 mResizingWindows.remove(i); 9429 } 9430 9431 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 9432 "With display frozen, orientationChangeComplete=" 9433 + mInnerFields.mOrientationChangeComplete); 9434 if (mInnerFields.mOrientationChangeComplete) { 9435 if (mWindowsFreezingScreen) { 9436 mWindowsFreezingScreen = false; 9437 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource; 9438 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9439 } 9440 stopFreezingDisplayLocked(); 9441 } 9442 9443 // Destroy the surface of any windows that are no longer visible. 9444 boolean wallpaperDestroyed = false; 9445 i = mDestroySurface.size(); 9446 if (i > 0) { 9447 do { 9448 i--; 9449 WindowState win = mDestroySurface.get(i); 9450 win.mDestroying = false; 9451 if (mInputMethodWindow == win) { 9452 mInputMethodWindow = null; 9453 } 9454 if (win == mWallpaperTarget) { 9455 wallpaperDestroyed = true; 9456 } 9457 win.mWinAnimator.destroySurfaceLocked(); 9458 } while (i > 0); 9459 mDestroySurface.clear(); 9460 } 9461 9462 // Time to remove any exiting tokens? 9463 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9464 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9465 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens; 9466 for (i = exitingTokens.size() - 1; i >= 0; i--) { 9467 WindowToken token = exitingTokens.get(i); 9468 if (!token.hasVisible) { 9469 exitingTokens.remove(i); 9470 if (token.windowType == TYPE_WALLPAPER) { 9471 mWallpaperTokens.remove(token); 9472 } 9473 } 9474 } 9475 } 9476 9477 // Time to remove any exiting applications? 9478 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9479 // Initialize state of exiting applications. 9480 final AppTokenList exitingAppTokens = 9481 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9482 for (i = exitingAppTokens.size() - 1; i >= 0; i--) { 9483 AppWindowToken token = exitingAppTokens.get(i); 9484 if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) { 9485 // Make sure there is no animation running on this token, 9486 // so any windows associated with it will be removed as 9487 // soon as their animations are complete 9488 token.mAppAnimator.clearAnimation(); 9489 token.mAppAnimator.animating = false; 9490 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 9491 "performLayout: App token exiting now removed" + token); 9492 removeAppFromTaskLocked(token); 9493 exitingAppTokens.remove(i); 9494 } 9495 } 9496 } 9497 9498 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 9499 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 9500 try { 9501 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 9502 } catch (RemoteException e) { 9503 } 9504 } 9505 mRelayoutWhileAnimating.clear(); 9506 } 9507 9508 if (wallpaperDestroyed) { 9509 defaultDisplay.pendingLayoutChanges |= 9510 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9511 defaultDisplay.layoutNeeded = true; 9512 } 9513 9514 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9515 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9516 if (displayContent.pendingLayoutChanges != 0) { 9517 displayContent.layoutNeeded = true; 9518 } 9519 } 9520 9521 // Finally update all input windows now that the window changes have stabilized. 9522 mInputMonitor.updateInputWindowsLw(true /*force*/); 9523 9524 setHoldScreenLocked(mInnerFields.mHoldScreen); 9525 if (!mDisplayFrozen) { 9526 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 9527 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1); 9528 } else { 9529 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager( 9530 toBrightnessOverride(mInnerFields.mScreenBrightness)); 9531 } 9532 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 9533 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1); 9534 } else { 9535 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager( 9536 toBrightnessOverride(mInnerFields.mButtonBrightness)); 9537 } 9538 mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager( 9539 mInnerFields.mUserActivityTimeout); 9540 } 9541 9542 if (mTurnOnScreen) { 9543 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 9544 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 9545 mTurnOnScreen = false; 9546 } 9547 9548 if (mInnerFields.mUpdateRotation) { 9549 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9550 if (updateRotationUncheckedLocked(false)) { 9551 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9552 } else { 9553 mInnerFields.mUpdateRotation = false; 9554 } 9555 } 9556 9557 if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded 9558 && !mInnerFields.mUpdateRotation) { 9559 checkDrawnWindowsLocked(); 9560 } 9561 9562 final int N = mPendingRemove.size(); 9563 if (N > 0) { 9564 if (mPendingRemoveTmp.length < N) { 9565 mPendingRemoveTmp = new WindowState[N+10]; 9566 } 9567 mPendingRemove.toArray(mPendingRemoveTmp); 9568 mPendingRemove.clear(); 9569 DisplayContentList displayList = new DisplayContentList(); 9570 for (i = 0; i < N; i++) { 9571 WindowState w = mPendingRemoveTmp[i]; 9572 removeWindowInnerLocked(w.mSession, w); 9573 final DisplayContent displayContent = w.getDisplayContent(); 9574 if (displayContent != null && !displayList.contains(displayContent)) { 9575 displayList.add(displayContent); 9576 } 9577 } 9578 9579 for (DisplayContent displayContent : displayList) { 9580 assignLayersLocked(displayContent.getWindowList()); 9581 displayContent.layoutNeeded = true; 9582 } 9583 } 9584 9585 // Remove all deferred displays stacks, tasks, and activities. 9586 for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) { 9587 mDisplayContents.valueAt(displayNdx).checkForDeferredActions(); 9588 } 9589 9590 setFocusedStackFrame(); 9591 9592 // Check to see if we are now in a state where the screen should 9593 // be enabled, because the window obscured flags have changed. 9594 enableScreenIfNeededLocked(); 9595 9596 scheduleAnimationLocked(); 9597 9598 if (DEBUG_WINDOW_TRACE) { 9599 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" 9600 + mAnimator.mAnimating); 9601 } 9602 } 9603 9604 private int toBrightnessOverride(float value) { 9605 return (int)(value * PowerManager.BRIGHTNESS_ON); 9606 } 9607 9608 void checkDrawnWindowsLocked() { 9609 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { 9610 return; 9611 } 9612 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { 9613 WindowState win = mWaitingForDrawn.get(j); 9614 if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win + 9615 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() + 9616 " mHasSurface=" + win.mHasSurface + 9617 " drawState=" + win.mWinAnimator.mDrawState); 9618 if (win.mRemoved || !win.mHasSurface) { 9619 // Window has been removed; no draw will now happen, so stop waiting. 9620 if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win); 9621 mWaitingForDrawn.remove(win); 9622 } else if (win.hasDrawnLw()) { 9623 // Window is now drawn (and shown). 9624 if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win); 9625 mWaitingForDrawn.remove(win); 9626 } 9627 } 9628 if (mWaitingForDrawn.isEmpty()) { 9629 if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!"); 9630 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 9631 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); 9632 } 9633 } 9634 9635 void setHoldScreenLocked(final Session newHoldScreen) { 9636 final boolean hold = newHoldScreen != null; 9637 9638 if (hold && mHoldingScreenOn != newHoldScreen) { 9639 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 9640 } 9641 mHoldingScreenOn = newHoldScreen; 9642 9643 final boolean state = mHoldingScreenWakeLock.isHeld(); 9644 if (hold != state) { 9645 if (hold) { 9646 mHoldingScreenWakeLock.acquire(); 9647 mPolicy.keepScreenOnStartedLw(); 9648 } else { 9649 mPolicy.keepScreenOnStoppedLw(); 9650 mHoldingScreenWakeLock.release(); 9651 } 9652 } 9653 } 9654 9655 void requestTraversal() { 9656 synchronized (mWindowMap) { 9657 requestTraversalLocked(); 9658 } 9659 } 9660 9661 void requestTraversalLocked() { 9662 if (!mTraversalScheduled) { 9663 mTraversalScheduled = true; 9664 mH.sendEmptyMessage(H.DO_TRAVERSAL); 9665 } 9666 } 9667 9668 /** Note that Locked in this case is on mLayoutToAnim */ 9669 void scheduleAnimationLocked() { 9670 if (!mAnimationScheduled) { 9671 mAnimationScheduled = true; 9672 mChoreographer.postCallback( 9673 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 9674 } 9675 } 9676 9677 private boolean needsLayout() { 9678 final int numDisplays = mDisplayContents.size(); 9679 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9680 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9681 if (displayContent.layoutNeeded) { 9682 return true; 9683 } 9684 } 9685 return false; 9686 } 9687 9688 boolean copyAnimToLayoutParamsLocked() { 9689 boolean doRequest = false; 9690 9691 final int bulkUpdateParams = mAnimator.mBulkUpdateParams; 9692 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 9693 mInnerFields.mUpdateRotation = true; 9694 doRequest = true; 9695 } 9696 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 9697 mInnerFields.mWallpaperMayChange = true; 9698 doRequest = true; 9699 } 9700 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 9701 mInnerFields.mWallpaperForceHidingChanged = true; 9702 doRequest = true; 9703 } 9704 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 9705 mInnerFields.mOrientationChangeComplete = false; 9706 } else { 9707 mInnerFields.mOrientationChangeComplete = true; 9708 mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource; 9709 if (mWindowsFreezingScreen) { 9710 doRequest = true; 9711 } 9712 } 9713 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 9714 mTurnOnScreen = true; 9715 } 9716 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) { 9717 mInnerFields.mWallpaperActionPending = true; 9718 } 9719 9720 return doRequest; 9721 } 9722 9723 /** If a window that has an animation specifying a colored background and the current wallpaper 9724 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 9725 * suddenly disappear. */ 9726 int adjustAnimationBackground(WindowStateAnimator winAnimator) { 9727 WindowList windows = winAnimator.mWin.getWindowList(); 9728 for (int i = windows.size() - 1; i >= 0; --i) { 9729 WindowState testWin = windows.get(i); 9730 if (testWin.mIsWallpaper && testWin.isVisibleNow()) { 9731 return testWin.mWinAnimator.mAnimLayer; 9732 } 9733 } 9734 return winAnimator.mAnimLayer; 9735 } 9736 9737 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9738 boolean secure) { 9739 final SurfaceControl surface = winAnimator.mSurfaceControl; 9740 boolean leakedSurface = false; 9741 boolean killedApps = false; 9742 9743 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9744 winAnimator.mSession.mPid, operation); 9745 9746 if (mForceRemoves == null) { 9747 mForceRemoves = new ArrayList<WindowState>(); 9748 } 9749 9750 long callingIdentity = Binder.clearCallingIdentity(); 9751 try { 9752 // There was some problem... first, do a sanity check of the 9753 // window list to make sure we haven't left any dangling surfaces 9754 // around. 9755 9756 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 9757 final int numDisplays = mDisplayContents.size(); 9758 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9759 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9760 final int numWindows = windows.size(); 9761 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9762 final WindowState ws = windows.get(winNdx); 9763 WindowStateAnimator wsa = ws.mWinAnimator; 9764 if (wsa.mSurfaceControl != null) { 9765 if (!mSessions.contains(wsa.mSession)) { 9766 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 9767 + ws + " surface=" + wsa.mSurfaceControl 9768 + " token=" + ws.mToken 9769 + " pid=" + ws.mSession.mPid 9770 + " uid=" + ws.mSession.mUid); 9771 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9772 wsa.mSurfaceControl.destroy(); 9773 wsa.mSurfaceShown = false; 9774 wsa.mSurfaceControl = null; 9775 ws.mHasSurface = false; 9776 mForceRemoves.add(ws); 9777 leakedSurface = true; 9778 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9779 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 9780 + ws + " surface=" + wsa.mSurfaceControl 9781 + " token=" + ws.mAppToken); 9782 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9783 wsa.mSurfaceControl.destroy(); 9784 wsa.mSurfaceShown = false; 9785 wsa.mSurfaceControl = null; 9786 ws.mHasSurface = false; 9787 leakedSurface = true; 9788 } 9789 } 9790 } 9791 } 9792 9793 if (!leakedSurface) { 9794 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 9795 SparseIntArray pidCandidates = new SparseIntArray(); 9796 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9797 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9798 final int numWindows = windows.size(); 9799 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9800 final WindowState ws = windows.get(winNdx); 9801 if (mForceRemoves.contains(ws)) { 9802 continue; 9803 } 9804 WindowStateAnimator wsa = ws.mWinAnimator; 9805 if (wsa.mSurfaceControl != null) { 9806 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9807 } 9808 } 9809 if (pidCandidates.size() > 0) { 9810 int[] pids = new int[pidCandidates.size()]; 9811 for (int i=0; i<pids.length; i++) { 9812 pids[i] = pidCandidates.keyAt(i); 9813 } 9814 try { 9815 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9816 killedApps = true; 9817 } 9818 } catch (RemoteException e) { 9819 } 9820 } 9821 } 9822 } 9823 9824 if (leakedSurface || killedApps) { 9825 // We managed to reclaim some memory, so get rid of the trouble 9826 // surface and ask the app to request another one. 9827 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 9828 if (surface != null) { 9829 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9830 "RECOVER DESTROY", null); 9831 surface.destroy(); 9832 winAnimator.mSurfaceShown = false; 9833 winAnimator.mSurfaceControl = null; 9834 winAnimator.mWin.mHasSurface = false; 9835 scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken); 9836 } 9837 9838 try { 9839 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9840 } catch (RemoteException e) { 9841 } 9842 } 9843 } finally { 9844 Binder.restoreCallingIdentity(callingIdentity); 9845 } 9846 9847 return leakedSurface || killedApps; 9848 } 9849 9850 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9851 WindowState newFocus = computeFocusedWindowLocked(); 9852 if (mCurrentFocus != newFocus) { 9853 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9854 // This check makes sure that we don't already have the focus 9855 // change message pending. 9856 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9857 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9858 // TODO(multidisplay): Focused windows on default display only. 9859 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9860 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked( 9861 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 9862 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES); 9863 if (imWindowChanged) { 9864 displayContent.layoutNeeded = true; 9865 newFocus = computeFocusedWindowLocked(); 9866 } 9867 9868 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " + 9869 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 9870 final WindowState oldFocus = mCurrentFocus; 9871 mCurrentFocus = newFocus; 9872 mLosingFocus.remove(newFocus); 9873 9874 // TODO(multidisplay): Accessibilty supported only of default desiplay. 9875 if (mAccessibilityController != null 9876 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 9877 mAccessibilityController.onWindowFocusChangedLocked(); 9878 } 9879 9880 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9881 9882 if (imWindowChanged && oldFocus != mInputMethodWindow) { 9883 // Focus of the input method window changed. Perform layout if needed. 9884 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9885 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9886 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9887 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9888 // Client will do the layout, but we need to assign layers 9889 // for handleNewWindowLocked() below. 9890 assignLayersLocked(displayContent.getWindowList()); 9891 } 9892 } 9893 9894 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9895 // The change in focus caused us to need to do a layout. Okay. 9896 displayContent.layoutNeeded = true; 9897 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9898 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9899 } 9900 } 9901 9902 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9903 // If we defer assigning layers, then the caller is responsible for 9904 // doing this part. 9905 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 9906 } 9907 9908 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9909 return true; 9910 } 9911 return false; 9912 } 9913 9914 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 9915 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9916 } 9917 9918 private WindowState computeFocusedWindowLocked() { 9919 if (mAnimator.mUniverseBackground != null 9920 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 9921 return mAnimator.mUniverseBackground.mWin; 9922 } 9923 9924 final int displayCount = mDisplayContents.size(); 9925 for (int i = 0; i < displayCount; i++) { 9926 final DisplayContent displayContent = mDisplayContents.valueAt(i); 9927 WindowState win = findFocusedWindowLocked(displayContent); 9928 if (win != null) { 9929 return win; 9930 } 9931 } 9932 return null; 9933 } 9934 9935 private WindowState findFocusedWindowLocked(DisplayContent displayContent) { 9936 final WindowList windows = displayContent.getWindowList(); 9937 for (int i = windows.size() - 1; i >= 0; i--) { 9938 final WindowState win = windows.get(i); 9939 9940 if (localLOGV || DEBUG_FOCUS) Slog.v( 9941 TAG, "Looking for focus: " + i 9942 + " = " + win 9943 + ", flags=" + win.mAttrs.flags 9944 + ", canReceive=" + win.canReceiveKeys()); 9945 9946 AppWindowToken wtoken = win.mAppToken; 9947 9948 // If this window's application has been removed, just skip it. 9949 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 9950 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because " 9951 + (wtoken.removed ? "removed" : "sendingToBottom")); 9952 continue; 9953 } 9954 9955 if (!win.canReceiveKeys()) { 9956 continue; 9957 } 9958 9959 // Descend through all of the app tokens and find the first that either matches 9960 // win.mAppToken (return win) or mFocusedApp (return null). 9961 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && 9962 mFocusedApp != null) { 9963 ArrayList<Task> tasks = displayContent.getTasks(); 9964 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9965 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9966 int tokenNdx = tokens.size() - 1; 9967 for ( ; tokenNdx >= 0; --tokenNdx) { 9968 final AppWindowToken token = tokens.get(tokenNdx); 9969 if (wtoken == token) { 9970 break; 9971 } 9972 if (mFocusedApp == token) { 9973 // Whoops, we are below the focused app... no focus for you! 9974 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG, 9975 "findFocusedWindow: Reached focused app=" + mFocusedApp); 9976 return null; 9977 } 9978 } 9979 if (tokenNdx >= 0) { 9980 // Early exit from loop, must have found the matching token. 9981 break; 9982 } 9983 } 9984 } 9985 9986 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i + 9987 " = " + win); 9988 return win; 9989 } 9990 9991 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows."); 9992 return null; 9993 } 9994 9995 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 9996 if (mDisplayFrozen) { 9997 return; 9998 } 9999 10000 if (!mDisplayReady || !mPolicy.isScreenOnFully()) { 10001 // No need to freeze the screen before the system is ready or if 10002 // the screen is off. 10003 return; 10004 } 10005 10006 mScreenFrozenLock.acquire(); 10007 10008 mDisplayFrozen = true; 10009 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 10010 mLastFinishedFreezeSource = null; 10011 10012 mInputMonitor.freezeInputDispatchingLw(); 10013 10014 // Clear the last input window -- that is just used for 10015 // clean transitions between IMEs, and if we are freezing 10016 // the screen then the whole world is changing behind the scenes. 10017 mPolicy.setLastInputMethodWindowLw(null, null); 10018 10019 if (mAppTransition.isTransitionSet()) { 10020 mAppTransition.freeze(); 10021 } 10022 10023 if (PROFILE_ORIENTATION) { 10024 File file = new File("/data/system/frozen"); 10025 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 10026 } 10027 10028 if (CUSTOM_SCREEN_ROTATION) { 10029 mExitAnimId = exitAnim; 10030 mEnterAnimId = enterAnim; 10031 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10032 final int displayId = displayContent.getDisplayId(); 10033 ScreenRotationAnimation screenRotationAnimation = 10034 mAnimator.getScreenRotationAnimationLocked(displayId); 10035 if (screenRotationAnimation != null) { 10036 screenRotationAnimation.kill(); 10037 } 10038 10039 // Check whether the current screen contains any secure content. 10040 boolean isSecure = false; 10041 final WindowList windows = getDefaultWindowListLocked(); 10042 final int N = windows.size(); 10043 for (int i = 0; i < N; i++) { 10044 WindowState ws = windows.get(i); 10045 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) { 10046 isSecure = true; 10047 break; 10048 } 10049 } 10050 10051 // TODO(multidisplay): rotation on main screen only. 10052 displayContent.updateDisplayInfo(); 10053 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 10054 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure); 10055 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10056 } 10057 } 10058 10059 private void stopFreezingDisplayLocked() { 10060 if (!mDisplayFrozen) { 10061 return; 10062 } 10063 10064 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen 10065 || mClientFreezingScreen) { 10066 if (DEBUG_ORIENTATION) Slog.d(TAG, 10067 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 10068 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 10069 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 10070 + ", mClientFreezingScreen=" + mClientFreezingScreen); 10071 return; 10072 } 10073 10074 mDisplayFrozen = false; 10075 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 10076 StringBuilder sb = new StringBuilder(128); 10077 sb.append("Screen frozen for "); 10078 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 10079 if (mLastFinishedFreezeSource != null) { 10080 sb.append(" due to "); 10081 sb.append(mLastFinishedFreezeSource); 10082 } 10083 Slog.i(TAG, sb.toString()); 10084 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 10085 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 10086 if (PROFILE_ORIENTATION) { 10087 Debug.stopMethodTracing(); 10088 } 10089 10090 boolean updateRotation = false; 10091 10092 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10093 final int displayId = displayContent.getDisplayId(); 10094 ScreenRotationAnimation screenRotationAnimation = 10095 mAnimator.getScreenRotationAnimationLocked(displayId); 10096 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 10097 && screenRotationAnimation.hasScreenshot()) { 10098 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 10099 // TODO(multidisplay): rotation on main screen only. 10100 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10101 // Get rotation animation again, with new top window 10102 boolean isDimming = displayContent.isDimming(); 10103 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 10104 mExitAnimId = mEnterAnimId = 0; 10105 } 10106 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 10107 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, 10108 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 10109 scheduleAnimationLocked(); 10110 } else { 10111 screenRotationAnimation.kill(); 10112 screenRotationAnimation = null; 10113 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10114 updateRotation = true; 10115 } 10116 } else { 10117 if (screenRotationAnimation != null) { 10118 screenRotationAnimation.kill(); 10119 screenRotationAnimation = null; 10120 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10121 } 10122 updateRotation = true; 10123 } 10124 10125 mInputMonitor.thawInputDispatchingLw(); 10126 10127 boolean configChanged; 10128 10129 // While the display is frozen we don't re-compute the orientation 10130 // to avoid inconsistent states. However, something interesting 10131 // could have actually changed during that time so re-evaluate it 10132 // now to catch that. 10133 configChanged = updateOrientationFromAppTokensLocked(false); 10134 10135 // A little kludge: a lot could have happened while the 10136 // display was frozen, so now that we are coming back we 10137 // do a gc so that any remote references the system 10138 // processes holds on others can be released if they are 10139 // no longer needed. 10140 mH.removeMessages(H.FORCE_GC); 10141 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 10142 10143 mScreenFrozenLock.release(); 10144 10145 if (updateRotation) { 10146 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 10147 configChanged |= updateRotationUncheckedLocked(false); 10148 } 10149 10150 if (configChanged) { 10151 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10152 } 10153 } 10154 10155 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 10156 DisplayMetrics dm) { 10157 if (index < tokens.length) { 10158 String str = tokens[index]; 10159 if (str != null && str.length() > 0) { 10160 try { 10161 int val = Integer.parseInt(str); 10162 return val; 10163 } catch (Exception e) { 10164 } 10165 } 10166 } 10167 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 10168 return defDps; 10169 } 10170 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 10171 return val; 10172 } 10173 10174 void createWatermarkInTransaction() { 10175 if (mWatermark != null) { 10176 return; 10177 } 10178 10179 File file = new File("/system/etc/setup.conf"); 10180 FileInputStream in = null; 10181 DataInputStream ind = null; 10182 try { 10183 in = new FileInputStream(file); 10184 ind = new DataInputStream(in); 10185 String line = ind.readLine(); 10186 if (line != null) { 10187 String[] toks = line.split("%"); 10188 if (toks != null && toks.length > 0) { 10189 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 10190 mRealDisplayMetrics, mFxSession, toks); 10191 } 10192 } 10193 } catch (FileNotFoundException e) { 10194 } catch (IOException e) { 10195 } finally { 10196 if (ind != null) { 10197 try { 10198 ind.close(); 10199 } catch (IOException e) { 10200 } 10201 } else if (in != null) { 10202 try { 10203 in.close(); 10204 } catch (IOException e) { 10205 } 10206 } 10207 } 10208 } 10209 10210 @Override 10211 public void statusBarVisibilityChanged(int visibility) { 10212 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10213 != PackageManager.PERMISSION_GRANTED) { 10214 throw new SecurityException("Caller does not hold permission " 10215 + android.Manifest.permission.STATUS_BAR); 10216 } 10217 10218 synchronized (mWindowMap) { 10219 mLastStatusBarVisibility = visibility; 10220 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 10221 updateStatusBarVisibilityLocked(visibility); 10222 } 10223 } 10224 10225 // TOOD(multidisplay): StatusBar on multiple screens? 10226 void updateStatusBarVisibilityLocked(int visibility) { 10227 mInputManager.setSystemUiVisibility(visibility); 10228 final WindowList windows = getDefaultWindowListLocked(); 10229 final int N = windows.size(); 10230 for (int i = 0; i < N; i++) { 10231 WindowState ws = windows.get(i); 10232 try { 10233 int curValue = ws.mSystemUiVisibility; 10234 int diff = curValue ^ visibility; 10235 // We are only interested in differences of one of the 10236 // clearable flags... 10237 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 10238 // ...if it has actually been cleared. 10239 diff &= ~visibility; 10240 int newValue = (curValue&~diff) | (visibility&diff); 10241 if (newValue != curValue) { 10242 ws.mSeq++; 10243 ws.mSystemUiVisibility = newValue; 10244 } 10245 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 10246 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 10247 visibility, newValue, diff); 10248 } 10249 } catch (RemoteException e) { 10250 // so sorry 10251 } 10252 } 10253 } 10254 10255 @Override 10256 public void reevaluateStatusBarVisibility() { 10257 synchronized (mWindowMap) { 10258 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 10259 updateStatusBarVisibilityLocked(visibility); 10260 performLayoutAndPlaceSurfacesLocked(); 10261 } 10262 } 10263 10264 @Override 10265 public FakeWindow addFakeWindow(Looper looper, 10266 InputEventReceiver.Factory inputEventReceiverFactory, 10267 String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags, 10268 boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) { 10269 synchronized (mWindowMap) { 10270 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 10271 name, windowType, 10272 layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys, 10273 hasFocus, touchFullscreen); 10274 int i=0; 10275 while (i<mFakeWindows.size()) { 10276 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 10277 break; 10278 } 10279 } 10280 mFakeWindows.add(i, fw); 10281 mInputMonitor.updateInputWindowsLw(true); 10282 return fw; 10283 } 10284 } 10285 10286 boolean removeFakeWindowLocked(FakeWindow window) { 10287 synchronized (mWindowMap) { 10288 if (mFakeWindows.remove(window)) { 10289 mInputMonitor.updateInputWindowsLw(true); 10290 return true; 10291 } 10292 return false; 10293 } 10294 } 10295 10296 // It is assumed that this method is called only by InputMethodManagerService. 10297 public void saveLastInputMethodWindowForTransition() { 10298 synchronized (mWindowMap) { 10299 // TODO(multidisplay): Pass in the displayID. 10300 DisplayContent displayContent = getDefaultDisplayContentLocked(); 10301 if (mInputMethodWindow != null) { 10302 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 10303 } 10304 } 10305 } 10306 10307 public int getInputMethodWindowVisibleHeight() { 10308 synchronized (mWindowMap) { 10309 return mPolicy.getInputMethodWindowVisibleHeightLw(); 10310 } 10311 } 10312 10313 @Override 10314 public boolean hasNavigationBar() { 10315 return mPolicy.hasNavigationBar(); 10316 } 10317 10318 @Override 10319 public void lockNow(Bundle options) { 10320 mPolicy.lockNow(options); 10321 } 10322 10323 @Override 10324 public boolean isSafeModeEnabled() { 10325 return mSafeMode; 10326 } 10327 10328 @Override 10329 public boolean clearWindowContentFrameStats(IBinder token) { 10330 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10331 "clearWindowContentFrameStats()")) { 10332 throw new SecurityException("Requires FRAME_STATS permission"); 10333 } 10334 synchronized (mWindowMap) { 10335 WindowState windowState = mWindowMap.get(token); 10336 if (windowState == null) { 10337 return false; 10338 } 10339 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10340 if (surfaceControl == null) { 10341 return false; 10342 } 10343 return surfaceControl.clearContentFrameStats(); 10344 } 10345 } 10346 10347 @Override 10348 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) { 10349 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10350 "getWindowContentFrameStats()")) { 10351 throw new SecurityException("Requires FRAME_STATS permission"); 10352 } 10353 synchronized (mWindowMap) { 10354 WindowState windowState = mWindowMap.get(token); 10355 if (windowState == null) { 10356 return null; 10357 } 10358 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10359 if (surfaceControl == null) { 10360 return null; 10361 } 10362 if (mTempWindowRenderStats == null) { 10363 mTempWindowRenderStats = new WindowContentFrameStats(); 10364 } 10365 WindowContentFrameStats stats = mTempWindowRenderStats; 10366 if (!surfaceControl.getContentFrameStats(stats)) { 10367 return null; 10368 } 10369 return stats; 10370 } 10371 } 10372 10373 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10374 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 10375 mPolicy.dump(" ", pw, args); 10376 } 10377 10378 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10379 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 10380 mAnimator.dumpLocked(pw, " ", dumpAll); 10381 } 10382 10383 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 10384 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 10385 if (mTokenMap.size() > 0) { 10386 pw.println(" All tokens:"); 10387 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10388 while (it.hasNext()) { 10389 WindowToken token = it.next(); 10390 pw.print(" "); pw.print(token); 10391 if (dumpAll) { 10392 pw.println(':'); 10393 token.dump(pw, " "); 10394 } else { 10395 pw.println(); 10396 } 10397 } 10398 } 10399 if (mWallpaperTokens.size() > 0) { 10400 pw.println(); 10401 pw.println(" Wallpaper tokens:"); 10402 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 10403 WindowToken token = mWallpaperTokens.get(i); 10404 pw.print(" Wallpaper #"); pw.print(i); 10405 pw.print(' '); pw.print(token); 10406 if (dumpAll) { 10407 pw.println(':'); 10408 token.dump(pw, " "); 10409 } else { 10410 pw.println(); 10411 } 10412 } 10413 } 10414 if (mFinishedStarting.size() > 0) { 10415 pw.println(); 10416 pw.println(" Finishing start of application tokens:"); 10417 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10418 WindowToken token = mFinishedStarting.get(i); 10419 pw.print(" Finished Starting #"); pw.print(i); 10420 pw.print(' '); pw.print(token); 10421 if (dumpAll) { 10422 pw.println(':'); 10423 token.dump(pw, " "); 10424 } else { 10425 pw.println(); 10426 } 10427 } 10428 } 10429 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 10430 pw.println(); 10431 if (mOpeningApps.size() > 0) { 10432 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10433 } 10434 if (mClosingApps.size() > 0) { 10435 pw.print(" mClosingApps="); pw.println(mClosingApps); 10436 } 10437 } 10438 } 10439 10440 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 10441 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 10442 for (int i=0; i<mSessions.size(); i++) { 10443 Session s = mSessions.valueAt(i); 10444 pw.print(" Session "); pw.print(s); pw.println(':'); 10445 s.dump(pw, " "); 10446 } 10447 } 10448 10449 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 10450 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 10451 if (mDisplayReady) { 10452 final int numDisplays = mDisplayContents.size(); 10453 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10454 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10455 displayContent.dump(" ", pw); 10456 } 10457 } else { 10458 pw.println(" NO DISPLAY"); 10459 } 10460 } 10461 10462 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 10463 ArrayList<WindowState> windows) { 10464 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 10465 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 10466 } 10467 10468 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 10469 ArrayList<WindowState> windows) { 10470 final int numDisplays = mDisplayContents.size(); 10471 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10472 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); 10473 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10474 final WindowState w = windowList.get(winNdx); 10475 if (windows == null || windows.contains(w)) { 10476 pw.print(" Window #"); pw.print(winNdx); pw.print(' '); 10477 pw.print(w); pw.println(":"); 10478 w.dump(pw, " ", dumpAll || windows != null); 10479 } 10480 } 10481 } 10482 if (mInputMethodDialogs.size() > 0) { 10483 pw.println(); 10484 pw.println(" Input method dialogs:"); 10485 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 10486 WindowState w = mInputMethodDialogs.get(i); 10487 if (windows == null || windows.contains(w)) { 10488 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 10489 } 10490 } 10491 } 10492 if (mPendingRemove.size() > 0) { 10493 pw.println(); 10494 pw.println(" Remove pending for:"); 10495 for (int i=mPendingRemove.size()-1; i>=0; i--) { 10496 WindowState w = mPendingRemove.get(i); 10497 if (windows == null || windows.contains(w)) { 10498 pw.print(" Remove #"); pw.print(i); pw.print(' '); 10499 pw.print(w); 10500 if (dumpAll) { 10501 pw.println(":"); 10502 w.dump(pw, " ", true); 10503 } else { 10504 pw.println(); 10505 } 10506 } 10507 } 10508 } 10509 if (mForceRemoves != null && mForceRemoves.size() > 0) { 10510 pw.println(); 10511 pw.println(" Windows force removing:"); 10512 for (int i=mForceRemoves.size()-1; i>=0; i--) { 10513 WindowState w = mForceRemoves.get(i); 10514 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10515 pw.print(w); 10516 if (dumpAll) { 10517 pw.println(":"); 10518 w.dump(pw, " ", true); 10519 } else { 10520 pw.println(); 10521 } 10522 } 10523 } 10524 if (mDestroySurface.size() > 0) { 10525 pw.println(); 10526 pw.println(" Windows waiting to destroy their surface:"); 10527 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10528 WindowState w = mDestroySurface.get(i); 10529 if (windows == null || windows.contains(w)) { 10530 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10531 pw.print(w); 10532 if (dumpAll) { 10533 pw.println(":"); 10534 w.dump(pw, " ", true); 10535 } else { 10536 pw.println(); 10537 } 10538 } 10539 } 10540 } 10541 if (mLosingFocus.size() > 0) { 10542 pw.println(); 10543 pw.println(" Windows losing focus:"); 10544 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10545 WindowState w = mLosingFocus.get(i); 10546 if (windows == null || windows.contains(w)) { 10547 pw.print(" Losing #"); pw.print(i); pw.print(' '); 10548 pw.print(w); 10549 if (dumpAll) { 10550 pw.println(":"); 10551 w.dump(pw, " ", true); 10552 } else { 10553 pw.println(); 10554 } 10555 } 10556 } 10557 } 10558 if (mResizingWindows.size() > 0) { 10559 pw.println(); 10560 pw.println(" Windows waiting to resize:"); 10561 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10562 WindowState w = mResizingWindows.get(i); 10563 if (windows == null || windows.contains(w)) { 10564 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 10565 pw.print(w); 10566 if (dumpAll) { 10567 pw.println(":"); 10568 w.dump(pw, " ", true); 10569 } else { 10570 pw.println(); 10571 } 10572 } 10573 } 10574 } 10575 if (mWaitingForDrawn.size() > 0) { 10576 pw.println(); 10577 pw.println(" Clients waiting for these windows to be drawn:"); 10578 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10579 WindowState win = mWaitingForDrawn.get(i); 10580 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); 10581 } 10582 } 10583 pw.println(); 10584 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10585 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10586 if (mLastFocus != mCurrentFocus) { 10587 pw.print(" mLastFocus="); pw.println(mLastFocus); 10588 } 10589 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10590 if (mInputMethodTarget != null) { 10591 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10592 } 10593 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10594 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10595 pw.print(" mLastDisplayFreezeDuration="); 10596 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 10597 if ( mLastFinishedFreezeSource != null) { 10598 pw.print(" due to "); 10599 pw.print(mLastFinishedFreezeSource); 10600 } 10601 pw.println(); 10602 if (dumpAll) { 10603 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 10604 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 10605 if (mLastStatusBarVisibility != 0) { 10606 pw.print(" mLastStatusBarVisibility=0x"); 10607 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 10608 } 10609 if (mInputMethodWindow != null) { 10610 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10611 } 10612 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 10613 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) { 10614 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 10615 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 10616 } 10617 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 10618 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 10619 if (mInputMethodAnimLayerAdjustment != 0 || 10620 mWallpaperAnimLayerAdjustment != 0) { 10621 pw.print(" mInputMethodAnimLayerAdjustment="); 10622 pw.print(mInputMethodAnimLayerAdjustment); 10623 pw.print(" mWallpaperAnimLayerAdjustment="); 10624 pw.println(mWallpaperAnimLayerAdjustment); 10625 } 10626 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10627 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10628 if (needsLayout()) { 10629 pw.print(" layoutNeeded on displays="); 10630 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10631 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10632 if (displayContent.layoutNeeded) { 10633 pw.print(displayContent.getDisplayId()); 10634 } 10635 } 10636 pw.println(); 10637 } 10638 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 10639 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10640 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 10641 pw.print(" client="); pw.print(mClientFreezingScreen); 10642 pw.print(" apps="); pw.print(mAppsFreezingScreen); 10643 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 10644 pw.print(" mRotation="); pw.print(mRotation); 10645 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 10646 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 10647 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 10648 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 10649 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled); 10650 pw.print(" window="); pw.print(mWindowAnimationScaleSetting); 10651 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); 10652 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); 10653 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); 10654 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 10655 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 10656 pw.println(" mLayoutToAnim:"); 10657 mAppTransition.dump(pw); 10658 } 10659 } 10660 10661 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10662 int opti, boolean dumpAll) { 10663 WindowList windows = new WindowList(); 10664 if ("visible".equals(name)) { 10665 synchronized(mWindowMap) { 10666 final int numDisplays = mDisplayContents.size(); 10667 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10668 final WindowList windowList = 10669 mDisplayContents.valueAt(displayNdx).getWindowList(); 10670 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10671 final WindowState w = windowList.get(winNdx); 10672 if (w.mWinAnimator.mSurfaceShown) { 10673 windows.add(w); 10674 } 10675 } 10676 } 10677 } 10678 } else { 10679 int objectId = 0; 10680 // See if this is an object ID. 10681 try { 10682 objectId = Integer.parseInt(name, 16); 10683 name = null; 10684 } catch (RuntimeException e) { 10685 } 10686 synchronized(mWindowMap) { 10687 final int numDisplays = mDisplayContents.size(); 10688 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10689 final WindowList windowList = 10690 mDisplayContents.valueAt(displayNdx).getWindowList(); 10691 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10692 final WindowState w = windowList.get(winNdx); 10693 if (name != null) { 10694 if (w.mAttrs.getTitle().toString().contains(name)) { 10695 windows.add(w); 10696 } 10697 } else if (System.identityHashCode(w) == objectId) { 10698 windows.add(w); 10699 } 10700 } 10701 } 10702 } 10703 } 10704 10705 if (windows.size() <= 0) { 10706 return false; 10707 } 10708 10709 synchronized(mWindowMap) { 10710 dumpWindowsLocked(pw, dumpAll, windows); 10711 } 10712 return true; 10713 } 10714 10715 void dumpLastANRLocked(PrintWriter pw) { 10716 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10717 if (mLastANRState == null) { 10718 pw.println(" <no ANR has occurred since boot>"); 10719 } else { 10720 pw.println(mLastANRState); 10721 } 10722 } 10723 10724 /** 10725 * Saves information about the state of the window manager at 10726 * the time an ANR occurred before anything else in the system changes 10727 * in response. 10728 * 10729 * @param appWindowToken The application that ANR'd, may be null. 10730 * @param windowState The window that ANR'd, may be null. 10731 * @param reason The reason for the ANR, may be null. 10732 */ 10733 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, 10734 String reason) { 10735 StringWriter sw = new StringWriter(); 10736 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 10737 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10738 if (appWindowToken != null) { 10739 pw.println(" Application at fault: " + appWindowToken.stringName); 10740 } 10741 if (windowState != null) { 10742 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10743 } 10744 if (reason != null) { 10745 pw.println(" Reason: " + reason); 10746 } 10747 pw.println(); 10748 dumpWindowsNoHeaderLocked(pw, true, null); 10749 pw.close(); 10750 mLastANRState = sw.toString(); 10751 } 10752 10753 @Override 10754 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10755 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10756 != PackageManager.PERMISSION_GRANTED) { 10757 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10758 + Binder.getCallingPid() 10759 + ", uid=" + Binder.getCallingUid()); 10760 return; 10761 } 10762 10763 boolean dumpAll = false; 10764 10765 int opti = 0; 10766 while (opti < args.length) { 10767 String opt = args[opti]; 10768 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10769 break; 10770 } 10771 opti++; 10772 if ("-a".equals(opt)) { 10773 dumpAll = true; 10774 } else if ("-h".equals(opt)) { 10775 pw.println("Window manager dump options:"); 10776 pw.println(" [-a] [-h] [cmd] ..."); 10777 pw.println(" cmd may be one of:"); 10778 pw.println(" l[astanr]: last ANR information"); 10779 pw.println(" p[policy]: policy state"); 10780 pw.println(" a[animator]: animator state"); 10781 pw.println(" s[essions]: active sessions"); 10782 pw.println(" d[isplays]: active display contents"); 10783 pw.println(" t[okens]: token list"); 10784 pw.println(" w[indows]: window list"); 10785 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10786 pw.println(" be a partial substring in a window name, a"); 10787 pw.println(" Window hex object identifier, or"); 10788 pw.println(" \"all\" for all windows, or"); 10789 pw.println(" \"visible\" for the visible windows."); 10790 pw.println(" -a: include all available server state."); 10791 return; 10792 } else { 10793 pw.println("Unknown argument: " + opt + "; use -h for help"); 10794 } 10795 } 10796 10797 // Is the caller requesting to dump a particular piece of data? 10798 if (opti < args.length) { 10799 String cmd = args[opti]; 10800 opti++; 10801 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10802 synchronized(mWindowMap) { 10803 dumpLastANRLocked(pw); 10804 } 10805 return; 10806 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10807 synchronized(mWindowMap) { 10808 dumpPolicyLocked(pw, args, true); 10809 } 10810 return; 10811 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 10812 synchronized(mWindowMap) { 10813 dumpAnimatorLocked(pw, args, true); 10814 } 10815 return; 10816 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10817 synchronized(mWindowMap) { 10818 dumpSessionsLocked(pw, true); 10819 } 10820 return; 10821 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 10822 synchronized(mWindowMap) { 10823 dumpDisplayContentsLocked(pw, true); 10824 } 10825 return; 10826 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10827 synchronized(mWindowMap) { 10828 dumpTokensLocked(pw, true); 10829 } 10830 return; 10831 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10832 synchronized(mWindowMap) { 10833 dumpWindowsLocked(pw, true, null); 10834 } 10835 return; 10836 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10837 synchronized(mWindowMap) { 10838 dumpWindowsLocked(pw, true, null); 10839 } 10840 return; 10841 } else { 10842 // Dumping a single name? 10843 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10844 pw.println("Bad window command, or no windows match: " + cmd); 10845 pw.println("Use -h for help."); 10846 } 10847 return; 10848 } 10849 } 10850 10851 synchronized(mWindowMap) { 10852 pw.println(); 10853 if (dumpAll) { 10854 pw.println("-------------------------------------------------------------------------------"); 10855 } 10856 dumpLastANRLocked(pw); 10857 pw.println(); 10858 if (dumpAll) { 10859 pw.println("-------------------------------------------------------------------------------"); 10860 } 10861 dumpPolicyLocked(pw, args, dumpAll); 10862 pw.println(); 10863 if (dumpAll) { 10864 pw.println("-------------------------------------------------------------------------------"); 10865 } 10866 dumpAnimatorLocked(pw, args, dumpAll); 10867 pw.println(); 10868 if (dumpAll) { 10869 pw.println("-------------------------------------------------------------------------------"); 10870 } 10871 dumpSessionsLocked(pw, dumpAll); 10872 pw.println(); 10873 if (dumpAll) { 10874 pw.println("-------------------------------------------------------------------------------"); 10875 } 10876 dumpDisplayContentsLocked(pw, dumpAll); 10877 pw.println(); 10878 if (dumpAll) { 10879 pw.println("-------------------------------------------------------------------------------"); 10880 } 10881 dumpTokensLocked(pw, dumpAll); 10882 pw.println(); 10883 if (dumpAll) { 10884 pw.println("-------------------------------------------------------------------------------"); 10885 } 10886 dumpWindowsLocked(pw, dumpAll, null); 10887 } 10888 } 10889 10890 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10891 @Override 10892 public void monitor() { 10893 synchronized (mWindowMap) { } 10894 } 10895 10896 public interface OnHardKeyboardStatusChangeListener { 10897 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 10898 } 10899 10900 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 10901 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 10902 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 10903 Integer.toHexString(pendingLayoutChanges)); 10904 } 10905 } 10906 10907 private DisplayContent newDisplayContentLocked(final Display display) { 10908 DisplayContent displayContent = new DisplayContent(display, this); 10909 final int displayId = display.getDisplayId(); 10910 if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display); 10911 mDisplayContents.put(displayId, displayContent); 10912 10913 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10914 final Rect rect = new Rect(); 10915 mDisplaySettings.getOverscanLocked(displayInfo.name, rect); 10916 synchronized (displayContent.mDisplaySizeLock) { 10917 displayInfo.overscanLeft = rect.left; 10918 displayInfo.overscanTop = rect.top; 10919 displayInfo.overscanRight = rect.right; 10920 displayInfo.overscanBottom = rect.bottom; 10921 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 10922 displayId, displayInfo); 10923 } 10924 configureDisplayPolicyLocked(displayContent); 10925 10926 // TODO: Create an input channel for each display with touch capability. 10927 if (displayId == Display.DEFAULT_DISPLAY) { 10928 displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent); 10929 registerPointerEventListener(displayContent.mTapDetector); 10930 } 10931 10932 return displayContent; 10933 } 10934 10935 public void createDisplayContentLocked(final Display display) { 10936 if (display == null) { 10937 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 10938 } 10939 getDisplayContentLocked(display.getDisplayId()); 10940 } 10941 10942 /** 10943 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 10944 * there is a Display for the displayId. 10945 * @param displayId The display the caller is interested in. 10946 * @return The DisplayContent associated with displayId or null if there is no Display for it. 10947 */ 10948 public DisplayContent getDisplayContentLocked(final int displayId) { 10949 DisplayContent displayContent = mDisplayContents.get(displayId); 10950 if (displayContent == null) { 10951 final Display display = mDisplayManager.getDisplay(displayId); 10952 if (display != null) { 10953 displayContent = newDisplayContentLocked(display); 10954 } 10955 } 10956 return displayContent; 10957 } 10958 10959 // There is an inherent assumption that this will never return null. 10960 public DisplayContent getDefaultDisplayContentLocked() { 10961 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 10962 } 10963 10964 public WindowList getDefaultWindowListLocked() { 10965 return getDefaultDisplayContentLocked().getWindowList(); 10966 } 10967 10968 public DisplayInfo getDefaultDisplayInfoLocked() { 10969 return getDefaultDisplayContentLocked().getDisplayInfo(); 10970 } 10971 10972 /** 10973 * Return the list of WindowStates associated on the passed display. 10974 * @param display The screen to return windows from. 10975 * @return The list of WindowStates on the screen, or null if the there is no screen. 10976 */ 10977 public WindowList getWindowListLocked(final Display display) { 10978 return getWindowListLocked(display.getDisplayId()); 10979 } 10980 10981 /** 10982 * Return the list of WindowStates associated on the passed display. 10983 * @param displayId The screen to return windows from. 10984 * @return The list of WindowStates on the screen, or null if the there is no screen. 10985 */ 10986 public WindowList getWindowListLocked(final int displayId) { 10987 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10988 return displayContent != null ? displayContent.getWindowList() : null; 10989 } 10990 10991 public void onDisplayAdded(int displayId) { 10992 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 10993 } 10994 10995 public void handleDisplayAdded(int displayId) { 10996 synchronized (mWindowMap) { 10997 final Display display = mDisplayManager.getDisplay(displayId); 10998 if (display != null) { 10999 createDisplayContentLocked(display); 11000 displayReady(displayId); 11001 } 11002 } 11003 } 11004 11005 public void onDisplayRemoved(int displayId) { 11006 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 11007 } 11008 11009 private void handleDisplayRemovedLocked(int displayId) { 11010 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11011 if (displayContent != null) { 11012 if (displayContent.isAnimating()) { 11013 displayContent.mDeferredRemoval = true; 11014 return; 11015 } 11016 if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent); 11017 mDisplayContents.delete(displayId); 11018 displayContent.close(); 11019 if (displayId == Display.DEFAULT_DISPLAY) { 11020 unregisterPointerEventListener(displayContent.mTapDetector); 11021 } 11022 } 11023 mAnimator.removeDisplayLocked(displayId); 11024 } 11025 11026 public void onDisplayChanged(int displayId) { 11027 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 11028 } 11029 11030 private void handleDisplayChangedLocked(int displayId) { 11031 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11032 if (displayContent != null) { 11033 displayContent.updateDisplayInfo(); 11034 } 11035 } 11036 11037 @Override 11038 public Object getWindowManagerLock() { 11039 return mWindowMap; 11040 } 11041 11042 private final class LocalService extends WindowManagerInternal { 11043 @Override 11044 public void requestTraversalFromDisplayManager() { 11045 requestTraversal(); 11046 } 11047 11048 @Override 11049 public void setMagnificationSpec(MagnificationSpec spec) { 11050 synchronized (mWindowMap) { 11051 if (mAccessibilityController != null) { 11052 mAccessibilityController.setMagnificationSpecLocked(spec); 11053 } else { 11054 throw new IllegalStateException("Magnification callbacks not set!"); 11055 } 11056 } 11057 if (Binder.getCallingPid() != android.os.Process.myPid()) { 11058 spec.recycle(); 11059 } 11060 } 11061 11062 @Override 11063 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { 11064 synchronized (mWindowMap) { 11065 WindowState windowState = mWindowMap.get(windowToken); 11066 if (windowState == null) { 11067 return null; 11068 } 11069 MagnificationSpec spec = null; 11070 if (mAccessibilityController != null) { 11071 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState); 11072 } 11073 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) { 11074 return null; 11075 } 11076 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec); 11077 spec.scale *= windowState.mGlobalScale; 11078 return spec; 11079 } 11080 } 11081 11082 @Override 11083 public void setMagnificationCallbacks(MagnificationCallbacks callbacks) { 11084 synchronized (mWindowMap) { 11085 if (mAccessibilityController == null) { 11086 mAccessibilityController = new AccessibilityController( 11087 WindowManagerService.this); 11088 } 11089 mAccessibilityController.setMagnificationCallbacksLocked(callbacks); 11090 if (!mAccessibilityController.hasCallbacksLocked()) { 11091 mAccessibilityController = null; 11092 } 11093 } 11094 } 11095 11096 @Override 11097 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) { 11098 synchronized (mWindowMap) { 11099 if (mAccessibilityController == null) { 11100 mAccessibilityController = new AccessibilityController( 11101 WindowManagerService.this); 11102 } 11103 mAccessibilityController.setWindowsForAccessibilityCallback(callback); 11104 if (!mAccessibilityController.hasCallbacksLocked()) { 11105 mAccessibilityController = null; 11106 } 11107 } 11108 } 11109 11110 @Override 11111 public void setInputFilter(IInputFilter filter) { 11112 mInputManager.setInputFilter(filter); 11113 } 11114 11115 @Override 11116 public IBinder getFocusedWindowToken() { 11117 synchronized (mWindowMap) { 11118 WindowState windowState = getFocusedWindowLocked(); 11119 if (windowState != null) { 11120 return windowState.mClient.asBinder(); 11121 } 11122 return null; 11123 } 11124 } 11125 11126 @Override 11127 public boolean isKeyguardLocked() { 11128 return isKeyguardLocked(); 11129 } 11130 11131 @Override 11132 public void getWindowFrame(IBinder token, Rect outBounds) { 11133 synchronized (mWindowMap) { 11134 WindowState windowState = mWindowMap.get(token); 11135 if (windowState != null) { 11136 outBounds.set(windowState.mFrame); 11137 } else { 11138 outBounds.setEmpty(); 11139 } 11140 } 11141 } 11142 11143 public void waitForAllWindowsDrawn(IRemoteCallback callback, long timeout) { 11144 synchronized (mWindowMap) { 11145 mWaitingForDrawnCallback = callback; 11146 final WindowList windows = getDefaultWindowListLocked(); 11147 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 11148 final WindowState win = windows.get(winNdx); 11149 if (win.mHasSurface) { 11150 win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 11151 // Force add to mResizingWindows. 11152 win.mLastContentInsets.set(-1, -1, -1, -1); 11153 mWaitingForDrawn.add(win); 11154 } 11155 } 11156 requestTraversalLocked(); 11157 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 11158 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); 11159 } 11160 checkDrawnWindowsLocked(); 11161 } 11162 } 11163} 11164