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