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