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