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