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