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