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