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