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