WindowManagerService.java revision 13f6ea78b0aa98ffea6ea644770e4320ec9a2242
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 Runnable 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 LocalServices.addService(WindowManagerPolicy.class, mPolicy); 770 771 mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG)); 772 773 mFxSession = new SurfaceSession(); 774 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); 775 Display[] displays = mDisplayManager.getDisplays(); 776 for (Display display : displays) { 777 createDisplayContentLocked(display); 778 } 779 780 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy); 781 782 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 783 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 784 mPowerManagerInternal.registerLowPowerModeObserver( 785 new PowerManagerInternal.LowPowerModeListener() { 786 @Override 787 public void onLowPowerModeChanged(boolean enabled) { 788 synchronized (mWindowMap) { 789 if (mAnimationsDisabled != enabled) { 790 mAnimationsDisabled = enabled; 791 dispatchNewAnimatorScaleLocked(null); 792 } 793 } 794 } 795 }); 796 mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled(); 797 mScreenFrozenLock = mPowerManager.newWakeLock( 798 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN"); 799 mScreenFrozenLock.setReferenceCounted(false); 800 801 mAppTransition = new AppTransition(context, mH); 802 803 mActivityManager = ActivityManagerNative.getDefault(); 804 mBatteryStats = BatteryStatsService.getService(); 805 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 806 mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null, 807 new AppOpsManager.OnOpChangedInternalListener() { 808 @Override 809 public void onOpChanged(int op, String packageName) { 810 updateAppOpsState(); 811 } 812 } 813 ); 814 815 // Get persisted window scale setting 816 mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 817 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 818 mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 819 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting); 820 setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(), 821 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting)); 822 823 // Track changes to DevicePolicyManager state so we can enable/disable keyguard. 824 IntentFilter filter = new IntentFilter(); 825 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 826 mContext.registerReceiver(mBroadcastReceiver, filter); 827 828 mHoldingScreenWakeLock = mPowerManager.newWakeLock( 829 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG); 830 mHoldingScreenWakeLock.setReferenceCounted(false); 831 832 mAnimator = new WindowAnimator(this); 833 834 LocalServices.addService(WindowManagerInternal.class, new LocalService()); 835 initPolicy(); 836 837 // Add ourself to the Watchdog monitors. 838 Watchdog.getInstance().addMonitor(this); 839 840 SurfaceControl.openTransaction(); 841 try { 842 createWatermarkInTransaction(); 843 mFocusedStackFrame = new FocusedStackFrame( 844 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 845 } finally { 846 SurfaceControl.closeTransaction(); 847 } 848 } 849 850 public InputMonitor getInputMonitor() { 851 return mInputMonitor; 852 } 853 854 @Override 855 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 856 throws RemoteException { 857 try { 858 return super.onTransact(code, data, reply, flags); 859 } catch (RuntimeException e) { 860 // The window manager only throws security exceptions, so let's 861 // log all others. 862 if (!(e instanceof SecurityException)) { 863 Slog.wtf(TAG, "Window Manager Crash", e); 864 } 865 throw e; 866 } 867 } 868 869 private void placeWindowAfter(WindowState pos, WindowState window) { 870 final WindowList windows = pos.getWindowList(); 871 final int i = windows.indexOf(pos); 872 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 873 TAG, "Adding window " + window + " at " 874 + (i+1) + " of " + windows.size() + " (after " + pos + ")"); 875 windows.add(i+1, window); 876 mWindowsChanged = true; 877 } 878 879 private void placeWindowBefore(WindowState pos, WindowState window) { 880 final WindowList windows = pos.getWindowList(); 881 int i = windows.indexOf(pos); 882 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 883 TAG, "Adding window " + window + " at " 884 + i + " of " + windows.size() + " (before " + pos + ")"); 885 if (i < 0) { 886 Slog.w(TAG, "placeWindowBefore: Unable to find " + pos + " in " + windows); 887 i = 0; 888 } 889 windows.add(i, window); 890 mWindowsChanged = true; 891 } 892 893 //This method finds out the index of a window that has the same app token as 894 //win. used for z ordering the windows in mWindows 895 private int findIdxBasedOnAppTokens(WindowState win) { 896 WindowList windows = win.getWindowList(); 897 for(int j = windows.size() - 1; j >= 0; j--) { 898 WindowState wentry = windows.get(j); 899 if(wentry.mAppToken == win.mAppToken) { 900 return j; 901 } 902 } 903 return -1; 904 } 905 906 /** 907 * Return the list of Windows from the passed token on the given Display. 908 * @param token The token with all the windows. 909 * @param displayContent The display we are interested in. 910 * @return List of windows from token that are on displayContent. 911 */ 912 WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) { 913 final WindowList windowList = new WindowList(); 914 final int count = token.windows.size(); 915 for (int i = 0; i < count; i++) { 916 final WindowState win = token.windows.get(i); 917 if (win.getDisplayContent() == displayContent) { 918 windowList.add(win); 919 } 920 } 921 return windowList; 922 } 923 924 /** 925 * Recursive search through a WindowList and all of its windows' children. 926 * @param targetWin The window to search for. 927 * @param windows The list to search. 928 * @return The index of win in windows or of the window that is an ancestor of win. 929 */ 930 private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) { 931 for (int i = windows.size() - 1; i >= 0; i--) { 932 final WindowState w = windows.get(i); 933 if (w == targetWin) { 934 return i; 935 } 936 if (!w.mChildWindows.isEmpty()) { 937 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) { 938 return i; 939 } 940 } 941 } 942 return -1; 943 } 944 945 private int addAppWindowToListLocked(final WindowState win) { 946 final IWindow client = win.mClient; 947 final WindowToken token = win.mToken; 948 final DisplayContent displayContent = win.getDisplayContent(); 949 if (displayContent == null) { 950 // It doesn't matter this display is going away. 951 return 0; 952 } 953 954 final WindowList windows = win.getWindowList(); 955 final int N = windows.size(); 956 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 957 int tokenWindowsPos = 0; 958 int windowListPos = tokenWindowList.size(); 959 if (!tokenWindowList.isEmpty()) { 960 // If this application has existing windows, we 961 // simply place the new window on top of them... but 962 // keep the starting window on top. 963 if (win.mAttrs.type == TYPE_BASE_APPLICATION) { 964 // Base windows go behind everything else. 965 WindowState lowestWindow = tokenWindowList.get(0); 966 placeWindowBefore(lowestWindow, win); 967 tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows); 968 } else { 969 AppWindowToken atoken = win.mAppToken; 970 WindowState lastWindow = tokenWindowList.get(windowListPos - 1); 971 if (atoken != null && lastWindow == atoken.startingWindow) { 972 placeWindowBefore(lastWindow, win); 973 tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows); 974 } else { 975 int newIdx = findIdxBasedOnAppTokens(win); 976 //there is a window above this one associated with the same 977 //apptoken note that the window could be a floating window 978 //that was created later or a window at the top of the list of 979 //windows associated with this token. 980 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 981 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " + 982 N); 983 windows.add(newIdx + 1, win); 984 if (newIdx < 0) { 985 // No window from token found on win's display. 986 tokenWindowsPos = 0; 987 } else { 988 tokenWindowsPos = indexOfWinInWindowList( 989 windows.get(newIdx), token.windows) + 1; 990 } 991 mWindowsChanged = true; 992 } 993 } 994 return tokenWindowsPos; 995 } 996 997 // No windows from this token on this display 998 if (localLOGV) Slog.v(TAG, "Figuring out where to add app window " + client.asBinder() 999 + " (token=" + token + ")"); 1000 // Figure out where the window should go, based on the 1001 // order of applications. 1002 WindowState pos = null; 1003 1004 final ArrayList<Task> tasks = displayContent.getTasks(); 1005 int taskNdx; 1006 int tokenNdx = -1; 1007 for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 1008 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1009 for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 1010 final AppWindowToken t = tokens.get(tokenNdx); 1011 if (t == token) { 1012 --tokenNdx; 1013 if (tokenNdx < 0) { 1014 --taskNdx; 1015 if (taskNdx >= 0) { 1016 tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1; 1017 } 1018 } 1019 break; 1020 } 1021 1022 // We haven't reached the token yet; if this token 1023 // is not going to the bottom and has windows on this display, we can 1024 // use it as an anchor for when we do reach the token. 1025 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1026 if (!t.sendingToBottom && tokenWindowList.size() > 0) { 1027 pos = tokenWindowList.get(0); 1028 } 1029 } 1030 if (tokenNdx >= 0) { 1031 // early exit 1032 break; 1033 } 1034 } 1035 1036 // We now know the index into the apps. If we found 1037 // an app window above, that gives us the position; else 1038 // we need to look some more. 1039 if (pos != null) { 1040 // Move behind any windows attached to this one. 1041 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1042 if (atoken != null) { 1043 tokenWindowList = 1044 getTokenWindowsOnDisplay(atoken, displayContent); 1045 final int NC = tokenWindowList.size(); 1046 if (NC > 0) { 1047 WindowState bottom = tokenWindowList.get(0); 1048 if (bottom.mSubLayer < 0) { 1049 pos = bottom; 1050 } 1051 } 1052 } 1053 placeWindowBefore(pos, win); 1054 return tokenWindowsPos; 1055 } 1056 1057 // Continue looking down until we find the first 1058 // token that has windows on this display. 1059 for ( ; taskNdx >= 0; --taskNdx) { 1060 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1061 for ( ; tokenNdx >= 0; --tokenNdx) { 1062 final AppWindowToken t = tokens.get(tokenNdx); 1063 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1064 final int NW = tokenWindowList.size(); 1065 if (NW > 0) { 1066 pos = tokenWindowList.get(NW-1); 1067 break; 1068 } 1069 } 1070 if (tokenNdx >= 0) { 1071 // found 1072 break; 1073 } 1074 } 1075 1076 if (pos != null) { 1077 // Move in front of any windows attached to this 1078 // one. 1079 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1080 if (atoken != null) { 1081 final int NC = atoken.windows.size(); 1082 if (NC > 0) { 1083 WindowState top = atoken.windows.get(NC-1); 1084 if (top.mSubLayer >= 0) { 1085 pos = top; 1086 } 1087 } 1088 } 1089 placeWindowAfter(pos, win); 1090 return tokenWindowsPos; 1091 } 1092 1093 // Just search for the start of this layer. 1094 final int myLayer = win.mBaseLayer; 1095 int i; 1096 for (i = 0; i < N; i++) { 1097 WindowState w = windows.get(i); 1098 if (w.mBaseLayer > myLayer) { 1099 break; 1100 } 1101 } 1102 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1103 "Based on layer: Adding window " + win + " at " + i + " of " + N); 1104 windows.add(i, win); 1105 mWindowsChanged = true; 1106 return tokenWindowsPos; 1107 } 1108 1109 private void addFreeWindowToListLocked(final WindowState win) { 1110 final WindowList windows = win.getWindowList(); 1111 1112 // Figure out where window should go, based on layer. 1113 final int myLayer = win.mBaseLayer; 1114 int i; 1115 for (i = windows.size() - 1; i >= 0; i--) { 1116 if (windows.get(i).mBaseLayer <= myLayer) { 1117 break; 1118 } 1119 } 1120 i++; 1121 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1122 "Free window: Adding window " + win + " at " + i + " of " + windows.size()); 1123 windows.add(i, win); 1124 mWindowsChanged = true; 1125 } 1126 1127 private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) { 1128 final WindowToken token = win.mToken; 1129 final DisplayContent displayContent = win.getDisplayContent(); 1130 if (displayContent == null) { 1131 return; 1132 } 1133 final WindowState attached = win.mAttachedWindow; 1134 1135 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 1136 1137 // Figure out this window's ordering relative to the window 1138 // it is attached to. 1139 final int NA = tokenWindowList.size(); 1140 final int sublayer = win.mSubLayer; 1141 int largestSublayer = Integer.MIN_VALUE; 1142 WindowState windowWithLargestSublayer = null; 1143 int i; 1144 for (i = 0; i < NA; i++) { 1145 WindowState w = tokenWindowList.get(i); 1146 final int wSublayer = w.mSubLayer; 1147 if (wSublayer >= largestSublayer) { 1148 largestSublayer = wSublayer; 1149 windowWithLargestSublayer = w; 1150 } 1151 if (sublayer < 0) { 1152 // For negative sublayers, we go below all windows 1153 // in the same sublayer. 1154 if (wSublayer >= sublayer) { 1155 if (addToToken) { 1156 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1157 token.windows.add(i, win); 1158 } 1159 placeWindowBefore(wSublayer >= 0 ? attached : w, win); 1160 break; 1161 } 1162 } else { 1163 // For positive sublayers, we go above all windows 1164 // in the same sublayer. 1165 if (wSublayer > sublayer) { 1166 if (addToToken) { 1167 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1168 token.windows.add(i, win); 1169 } 1170 placeWindowBefore(w, win); 1171 break; 1172 } 1173 } 1174 } 1175 if (i >= NA) { 1176 if (addToToken) { 1177 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1178 token.windows.add(win); 1179 } 1180 if (sublayer < 0) { 1181 placeWindowBefore(attached, win); 1182 } else { 1183 placeWindowAfter(largestSublayer >= 0 1184 ? windowWithLargestSublayer 1185 : attached, 1186 win); 1187 } 1188 } 1189 } 1190 1191 private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) { 1192 if (DEBUG_FOCUS_LIGHT) Slog.d(TAG, "addWindowToListInOrderLocked: win=" + win + 1193 " Callers=" + Debug.getCallers(4)); 1194 if (win.mAttachedWindow == null) { 1195 final WindowToken token = win.mToken; 1196 int tokenWindowsPos = 0; 1197 if (token.appWindowToken != null) { 1198 tokenWindowsPos = addAppWindowToListLocked(win); 1199 } else { 1200 addFreeWindowToListLocked(win); 1201 } 1202 if (addToToken) { 1203 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1204 token.windows.add(tokenWindowsPos, win); 1205 } 1206 } else { 1207 addAttachedWindowToListLocked(win, addToToken); 1208 } 1209 1210 if (win.mAppToken != null && addToToken) { 1211 win.mAppToken.allAppWindows.add(win); 1212 } 1213 } 1214 1215 static boolean canBeImeTarget(WindowState w) { 1216 final int fl = w.mAttrs.flags 1217 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); 1218 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM) 1219 || w.mAttrs.type == TYPE_APPLICATION_STARTING) { 1220 if (DEBUG_INPUT_METHOD) { 1221 Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding()); 1222 if (!w.isVisibleOrAdding()) { 1223 Slog.i(TAG, " mSurface=" + w.mWinAnimator.mSurfaceControl 1224 + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility 1225 + " policyVis=" + w.mPolicyVisibility 1226 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim 1227 + " attachHid=" + w.mAttachedHidden 1228 + " exiting=" + w.mExiting + " destroying=" + w.mDestroying); 1229 if (w.mAppToken != null) { 1230 Slog.i(TAG, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested); 1231 } 1232 } 1233 } 1234 return w.isVisibleOrAdding(); 1235 } 1236 return false; 1237 } 1238 1239 /** 1240 * Dig through the WindowStates and find the one that the Input Method will target. 1241 * @param willMove 1242 * @return The index+1 in mWindows of the discovered target. 1243 */ 1244 int findDesiredInputMethodWindowIndexLocked(boolean willMove) { 1245 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the 1246 // same display. Or even when the current IME/target are not on the same screen as the next 1247 // IME/target. For now only look for input windows on the main screen. 1248 WindowList windows = getDefaultWindowListLocked(); 1249 WindowState w = null; 1250 int i; 1251 for (i = windows.size() - 1; i >= 0; --i) { 1252 WindowState win = windows.get(i); 1253 1254 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i 1255 + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags)); 1256 if (canBeImeTarget(win)) { 1257 w = win; 1258 //Slog.i(TAG, "Putting input method here!"); 1259 1260 // Yet more tricksyness! If this window is a "starting" 1261 // window, we do actually want to be on top of it, but 1262 // it is not -really- where input will go. So if the caller 1263 // is not actually looking to move the IME, look down below 1264 // for a real window to target... 1265 if (!willMove 1266 && w.mAttrs.type == TYPE_APPLICATION_STARTING 1267 && i > 0) { 1268 WindowState wb = windows.get(i-1); 1269 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) { 1270 i--; 1271 w = wb; 1272 } 1273 } 1274 break; 1275 } 1276 } 1277 1278 // Now w is either mWindows[0] or an IME (or null if mWindows is empty). 1279 1280 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w); 1281 1282 // Now, a special case -- if the last target's window is in the 1283 // process of exiting, and is above the new target, keep on the 1284 // last target to avoid flicker. Consider for example a Dialog with 1285 // the IME shown: when the Dialog is dismissed, we want to keep 1286 // the IME above it until it is completely gone so it doesn't drop 1287 // behind the dialog or its full-screen scrim. 1288 final WindowState curTarget = mInputMethodTarget; 1289 if (curTarget != null 1290 && curTarget.isDisplayedLw() 1291 && curTarget.isClosing() 1292 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) { 1293 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing"); 1294 return windows.indexOf(curTarget) + 1; 1295 } 1296 1297 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target=" 1298 + w + " willMove=" + willMove); 1299 1300 if (willMove && w != null) { 1301 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken; 1302 if (token != null) { 1303 1304 // Now some fun for dealing with window animations that 1305 // modify the Z order. We need to look at all windows below 1306 // the current target that are in this app, finding the highest 1307 // visible one in layering. 1308 WindowState highestTarget = null; 1309 int highestPos = 0; 1310 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) { 1311 WindowList curWindows = curTarget.getWindowList(); 1312 int pos = curWindows.indexOf(curTarget); 1313 while (pos >= 0) { 1314 WindowState win = curWindows.get(pos); 1315 if (win.mAppToken != token) { 1316 break; 1317 } 1318 if (!win.mRemoved) { 1319 if (highestTarget == null || win.mWinAnimator.mAnimLayer > 1320 highestTarget.mWinAnimator.mAnimLayer) { 1321 highestTarget = win; 1322 highestPos = pos; 1323 } 1324 } 1325 pos--; 1326 } 1327 } 1328 1329 if (highestTarget != null) { 1330 if (DEBUG_INPUT_METHOD) Slog.v(TAG, mAppTransition + " " + highestTarget 1331 + " animating=" + highestTarget.mWinAnimator.isAnimating() 1332 + " layer=" + highestTarget.mWinAnimator.mAnimLayer 1333 + " new layer=" + w.mWinAnimator.mAnimLayer); 1334 1335 if (mAppTransition.isTransitionSet()) { 1336 // If we are currently setting up for an animation, 1337 // hold everything until we can find out what will happen. 1338 mInputMethodTargetWaitingAnim = true; 1339 mInputMethodTarget = highestTarget; 1340 return highestPos + 1; 1341 } else if (highestTarget.mWinAnimator.isAnimating() && 1342 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) { 1343 // If the window we are currently targeting is involved 1344 // with an animation, and it is on top of the next target 1345 // we will be over, then hold off on moving until 1346 // that is done. 1347 mInputMethodTargetWaitingAnim = true; 1348 mInputMethodTarget = highestTarget; 1349 return highestPos + 1; 1350 } 1351 } 1352 } 1353 } 1354 1355 //Slog.i(TAG, "Placing input method @" + (i+1)); 1356 if (w != null) { 1357 if (willMove) { 1358 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to " 1359 + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4))); 1360 mInputMethodTarget = w; 1361 mInputMethodTargetWaitingAnim = false; 1362 if (w.mAppToken != null) { 1363 setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment); 1364 } else { 1365 setInputMethodAnimLayerAdjustment(0); 1366 } 1367 } 1368 return i+1; 1369 } 1370 if (willMove) { 1371 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null." 1372 + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4))); 1373 mInputMethodTarget = null; 1374 setInputMethodAnimLayerAdjustment(0); 1375 } 1376 return -1; 1377 } 1378 1379 void addInputMethodWindowToListLocked(WindowState win) { 1380 int pos = findDesiredInputMethodWindowIndexLocked(true); 1381 if (pos >= 0) { 1382 win.mTargetAppToken = mInputMethodTarget.mAppToken; 1383 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 1384 TAG, "Adding input method window " + win + " at " + pos); 1385 // TODO(multidisplay): IMEs are only supported on the default display. 1386 getDefaultWindowListLocked().add(pos, win); 1387 mWindowsChanged = true; 1388 moveInputMethodDialogsLocked(pos+1); 1389 return; 1390 } 1391 win.mTargetAppToken = null; 1392 addWindowToListInOrderLocked(win, true); 1393 moveInputMethodDialogsLocked(pos); 1394 } 1395 1396 void setInputMethodAnimLayerAdjustment(int adj) { 1397 if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj); 1398 mInputMethodAnimLayerAdjustment = adj; 1399 WindowState imw = mInputMethodWindow; 1400 if (imw != null) { 1401 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj; 1402 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw 1403 + " anim layer: " + imw.mWinAnimator.mAnimLayer); 1404 int wi = imw.mChildWindows.size(); 1405 while (wi > 0) { 1406 wi--; 1407 WindowState cw = imw.mChildWindows.get(wi); 1408 cw.mWinAnimator.mAnimLayer = cw.mLayer + adj; 1409 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw 1410 + " anim layer: " + cw.mWinAnimator.mAnimLayer); 1411 } 1412 } 1413 int di = mInputMethodDialogs.size(); 1414 while (di > 0) { 1415 di --; 1416 imw = mInputMethodDialogs.get(di); 1417 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj; 1418 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw 1419 + " anim layer: " + imw.mWinAnimator.mAnimLayer); 1420 } 1421 } 1422 1423 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) { 1424 WindowList windows = win.getWindowList(); 1425 int wpos = windows.indexOf(win); 1426 if (wpos >= 0) { 1427 if (wpos < interestingPos) interestingPos--; 1428 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win); 1429 windows.remove(wpos); 1430 mWindowsChanged = true; 1431 int NC = win.mChildWindows.size(); 1432 while (NC > 0) { 1433 NC--; 1434 WindowState cw = win.mChildWindows.get(NC); 1435 int cpos = windows.indexOf(cw); 1436 if (cpos >= 0) { 1437 if (cpos < interestingPos) interestingPos--; 1438 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at " 1439 + cpos + ": " + cw); 1440 windows.remove(cpos); 1441 } 1442 } 1443 } 1444 return interestingPos; 1445 } 1446 1447 private void reAddWindowToListInOrderLocked(WindowState win) { 1448 addWindowToListInOrderLocked(win, false); 1449 // This is a hack to get all of the child windows added as well 1450 // at the right position. Child windows should be rare and 1451 // this case should be rare, so it shouldn't be that big a deal. 1452 WindowList windows = win.getWindowList(); 1453 int wpos = windows.indexOf(win); 1454 if (wpos >= 0) { 1455 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win); 1456 windows.remove(wpos); 1457 mWindowsChanged = true; 1458 reAddWindowLocked(wpos, win); 1459 } 1460 } 1461 1462 void logWindowList(final WindowList windows, String prefix) { 1463 int N = windows.size(); 1464 while (N > 0) { 1465 N--; 1466 Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N)); 1467 } 1468 } 1469 1470 void moveInputMethodDialogsLocked(int pos) { 1471 ArrayList<WindowState> dialogs = mInputMethodDialogs; 1472 1473 // TODO(multidisplay): IMEs are only supported on the default display. 1474 WindowList windows = getDefaultWindowListLocked(); 1475 final int N = dialogs.size(); 1476 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos); 1477 for (int i=0; i<N; i++) { 1478 pos = tmpRemoveWindowLocked(pos, dialogs.get(i)); 1479 } 1480 if (DEBUG_INPUT_METHOD) { 1481 Slog.v(TAG, "Window list w/pos=" + pos); 1482 logWindowList(windows, " "); 1483 } 1484 1485 if (pos >= 0) { 1486 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken; 1487 // Skip windows owned by the input method. 1488 if (mInputMethodWindow != null) { 1489 while (pos < windows.size()) { 1490 WindowState wp = windows.get(pos); 1491 if (wp == mInputMethodWindow || wp.mAttachedWindow == mInputMethodWindow) { 1492 pos++; 1493 continue; 1494 } 1495 break; 1496 } 1497 } 1498 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos); 1499 for (int i=0; i<N; i++) { 1500 WindowState win = dialogs.get(i); 1501 win.mTargetAppToken = targetAppToken; 1502 pos = reAddWindowLocked(pos, win); 1503 } 1504 if (DEBUG_INPUT_METHOD) { 1505 Slog.v(TAG, "Final window list:"); 1506 logWindowList(windows, " "); 1507 } 1508 return; 1509 } 1510 for (int i=0; i<N; i++) { 1511 WindowState win = dialogs.get(i); 1512 win.mTargetAppToken = null; 1513 reAddWindowToListInOrderLocked(win); 1514 if (DEBUG_INPUT_METHOD) { 1515 Slog.v(TAG, "No IM target, final list:"); 1516 logWindowList(windows, " "); 1517 } 1518 } 1519 } 1520 1521 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) { 1522 final WindowState imWin = mInputMethodWindow; 1523 final int DN = mInputMethodDialogs.size(); 1524 if (imWin == null && DN == 0) { 1525 return false; 1526 } 1527 1528 // TODO(multidisplay): IMEs are only supported on the default display. 1529 WindowList windows = getDefaultWindowListLocked(); 1530 1531 int imPos = findDesiredInputMethodWindowIndexLocked(true); 1532 if (imPos >= 0) { 1533 // In this case, the input method windows are to be placed 1534 // immediately above the window they are targeting. 1535 1536 // First check to see if the input method windows are already 1537 // located here, and contiguous. 1538 final int N = windows.size(); 1539 WindowState firstImWin = imPos < N 1540 ? windows.get(imPos) : null; 1541 1542 // Figure out the actual input method window that should be 1543 // at the bottom of their stack. 1544 WindowState baseImWin = imWin != null 1545 ? imWin : mInputMethodDialogs.get(0); 1546 if (baseImWin.mChildWindows.size() > 0) { 1547 WindowState cw = baseImWin.mChildWindows.get(0); 1548 if (cw.mSubLayer < 0) baseImWin = cw; 1549 } 1550 1551 if (firstImWin == baseImWin) { 1552 // The windows haven't moved... but are they still contiguous? 1553 // First find the top IM window. 1554 int pos = imPos+1; 1555 while (pos < N) { 1556 if (!(windows.get(pos)).mIsImWindow) { 1557 break; 1558 } 1559 pos++; 1560 } 1561 pos++; 1562 // Now there should be no more input method windows above. 1563 while (pos < N) { 1564 if ((windows.get(pos)).mIsImWindow) { 1565 break; 1566 } 1567 pos++; 1568 } 1569 if (pos >= N) { 1570 // Z order is good. 1571 // The IM target window may be changed, so update the mTargetAppToken. 1572 if (imWin != null) { 1573 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1574 } 1575 return false; 1576 } 1577 } 1578 1579 if (imWin != null) { 1580 if (DEBUG_INPUT_METHOD) { 1581 Slog.v(TAG, "Moving IM from " + imPos); 1582 logWindowList(windows, " "); 1583 } 1584 imPos = tmpRemoveWindowLocked(imPos, imWin); 1585 if (DEBUG_INPUT_METHOD) { 1586 Slog.v(TAG, "List after removing with new pos " + imPos + ":"); 1587 logWindowList(windows, " "); 1588 } 1589 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1590 reAddWindowLocked(imPos, imWin); 1591 if (DEBUG_INPUT_METHOD) { 1592 Slog.v(TAG, "List after moving IM to " + imPos + ":"); 1593 logWindowList(windows, " "); 1594 } 1595 if (DN > 0) moveInputMethodDialogsLocked(imPos+1); 1596 } else { 1597 moveInputMethodDialogsLocked(imPos); 1598 } 1599 1600 } else { 1601 // In this case, the input method windows go in a fixed layer, 1602 // because they aren't currently associated with a focus window. 1603 1604 if (imWin != null) { 1605 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos); 1606 tmpRemoveWindowLocked(0, imWin); 1607 imWin.mTargetAppToken = null; 1608 reAddWindowToListInOrderLocked(imWin); 1609 if (DEBUG_INPUT_METHOD) { 1610 Slog.v(TAG, "List with no IM target:"); 1611 logWindowList(windows, " "); 1612 } 1613 if (DN > 0) moveInputMethodDialogsLocked(-1); 1614 } else { 1615 moveInputMethodDialogsLocked(-1); 1616 } 1617 1618 } 1619 1620 if (needAssignLayers) { 1621 assignLayersLocked(windows); 1622 } 1623 1624 return true; 1625 } 1626 1627 final boolean isWallpaperVisible(WindowState wallpaperTarget) { 1628 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured=" 1629 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??") 1630 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null) 1631 ? wallpaperTarget.mAppToken.mAppAnimator.animation : null) 1632 + " upper=" + mUpperWallpaperTarget 1633 + " lower=" + mLowerWallpaperTarget); 1634 return (wallpaperTarget != null 1635 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null 1636 && wallpaperTarget.mAppToken.mAppAnimator.animation != null))) 1637 || mUpperWallpaperTarget != null 1638 || mLowerWallpaperTarget != null; 1639 } 1640 1641 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1; 1642 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2; 1643 1644 int adjustWallpaperWindowsLocked() { 1645 mInnerFields.mWallpaperMayChange = false; 1646 boolean targetChanged = false; 1647 1648 // TODO(multidisplay): Wallpapers on main screen only. 1649 final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo(); 1650 final int dw = displayInfo.logicalWidth; 1651 final int dh = displayInfo.logicalHeight; 1652 1653 // First find top-most window that has asked to be on top of the 1654 // wallpaper; all wallpapers go behind it. 1655 final WindowList windows = getDefaultWindowListLocked(); 1656 int N = windows.size(); 1657 WindowState w = null; 1658 WindowState foundW = null; 1659 int foundI = 0; 1660 WindowState topCurW = null; 1661 int topCurI = 0; 1662 int windowDetachedI = -1; 1663 int i = N; 1664 while (i > 0) { 1665 i--; 1666 w = windows.get(i); 1667 if ((w.mAttrs.type == TYPE_WALLPAPER)) { 1668 if (topCurW == null) { 1669 topCurW = w; 1670 topCurI = i; 1671 } 1672 continue; 1673 } 1674 topCurW = null; 1675 if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) { 1676 // If this window's app token is hidden and not animating, 1677 // it is of no interest to us. 1678 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) { 1679 if (DEBUG_WALLPAPER) Slog.v(TAG, 1680 "Skipping hidden and not animating token: " + w); 1681 continue; 1682 } 1683 } 1684 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen=" 1685 + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState); 1686 if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isOnScreen() 1687 && (mWallpaperTarget == w || w.isDrawFinishedLw())) { 1688 if (DEBUG_WALLPAPER) Slog.v(TAG, 1689 "Found wallpaper target: #" + i + "=" + w); 1690 foundW = w; 1691 foundI = i; 1692 if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) { 1693 // The current wallpaper target is animating, so we'll 1694 // look behind it for another possible target and figure 1695 // out what is going on below. 1696 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w 1697 + ": token animating, looking behind."); 1698 continue; 1699 } 1700 break; 1701 } else if (w == mAnimator.mWindowDetachedWallpaper) { 1702 windowDetachedI = i; 1703 } 1704 } 1705 1706 if (foundW == null && windowDetachedI >= 0) { 1707 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 1708 "Found animating detached wallpaper activity: #" + i + "=" + w); 1709 foundW = w; 1710 foundI = windowDetachedI; 1711 } 1712 1713 if (mWallpaperTarget != foundW 1714 && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) { 1715 if (DEBUG_WALLPAPER_LIGHT) { 1716 Slog.v(TAG, "New wallpaper target: " + foundW 1717 + " oldTarget: " + mWallpaperTarget); 1718 } 1719 1720 mLowerWallpaperTarget = null; 1721 mUpperWallpaperTarget = null; 1722 1723 WindowState oldW = mWallpaperTarget; 1724 mWallpaperTarget = foundW; 1725 targetChanged = true; 1726 1727 // Now what is happening... if the current and new targets are 1728 // animating, then we are in our super special mode! 1729 if (foundW != null && oldW != null) { 1730 boolean oldAnim = oldW.isAnimatingLw(); 1731 boolean foundAnim = foundW.isAnimatingLw(); 1732 if (DEBUG_WALLPAPER_LIGHT) { 1733 Slog.v(TAG, "New animation: " + foundAnim 1734 + " old animation: " + oldAnim); 1735 } 1736 if (foundAnim && oldAnim) { 1737 int oldI = windows.indexOf(oldW); 1738 if (DEBUG_WALLPAPER_LIGHT) { 1739 Slog.v(TAG, "New i: " + foundI + " old i: " + oldI); 1740 } 1741 if (oldI >= 0) { 1742 if (DEBUG_WALLPAPER_LIGHT) { 1743 Slog.v(TAG, "Animating wallpapers: old#" + oldI 1744 + "=" + oldW + "; new#" + foundI 1745 + "=" + foundW); 1746 } 1747 1748 // Set the new target correctly. 1749 if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) { 1750 if (DEBUG_WALLPAPER_LIGHT) { 1751 Slog.v(TAG, "Old wallpaper still the target."); 1752 } 1753 mWallpaperTarget = oldW; 1754 foundW = oldW; 1755 foundI = oldI; 1756 } 1757 // Now set the upper and lower wallpaper targets 1758 // correctly, and make sure that we are positioning 1759 // the wallpaper below the lower. 1760 else if (foundI > oldI) { 1761 // The new target is on top of the old one. 1762 if (DEBUG_WALLPAPER_LIGHT) { 1763 Slog.v(TAG, "Found target above old target."); 1764 } 1765 mUpperWallpaperTarget = foundW; 1766 mLowerWallpaperTarget = oldW; 1767 foundW = oldW; 1768 foundI = oldI; 1769 } else { 1770 // The new target is below the old one. 1771 if (DEBUG_WALLPAPER_LIGHT) { 1772 Slog.v(TAG, "Found target below old target."); 1773 } 1774 mUpperWallpaperTarget = oldW; 1775 mLowerWallpaperTarget = foundW; 1776 } 1777 } 1778 } 1779 } 1780 1781 } else if (mLowerWallpaperTarget != null) { 1782 // Is it time to stop animating? 1783 if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) { 1784 if (DEBUG_WALLPAPER_LIGHT) { 1785 Slog.v(TAG, "No longer animating wallpaper targets!"); 1786 } 1787 mLowerWallpaperTarget = null; 1788 mUpperWallpaperTarget = null; 1789 mWallpaperTarget = foundW; 1790 targetChanged = true; 1791 } 1792 } 1793 1794 boolean visible = foundW != null; 1795 if (visible) { 1796 // The window is visible to the compositor... but is it visible 1797 // to the user? That is what the wallpaper cares about. 1798 visible = isWallpaperVisible(foundW); 1799 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible); 1800 1801 // If the wallpaper target is animating, we may need to copy 1802 // its layer adjustment. Only do this if we are not transfering 1803 // between two wallpaper targets. 1804 mWallpaperAnimLayerAdjustment = 1805 (mLowerWallpaperTarget == null && foundW.mAppToken != null) 1806 ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0; 1807 1808 final int maxLayer = mPolicy.getMaxWallpaperLayer() 1809 * TYPE_LAYER_MULTIPLIER 1810 + TYPE_LAYER_OFFSET; 1811 1812 // Now w is the window we are supposed to be behind... but we 1813 // need to be sure to also be behind any of its attached windows, 1814 // AND any starting window associated with it, AND below the 1815 // maximum layer the policy allows for wallpapers. 1816 while (foundI > 0) { 1817 WindowState wb = windows.get(foundI-1); 1818 if (wb.mBaseLayer < maxLayer && 1819 wb.mAttachedWindow != foundW && 1820 (foundW.mAttachedWindow == null || 1821 wb.mAttachedWindow != foundW.mAttachedWindow) && 1822 (wb.mAttrs.type != TYPE_APPLICATION_STARTING || 1823 foundW.mToken == null || wb.mToken != foundW.mToken)) { 1824 // This window is not related to the previous one in any 1825 // interesting way, so stop here. 1826 break; 1827 } 1828 foundW = wb; 1829 foundI--; 1830 } 1831 } else { 1832 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target"); 1833 } 1834 1835 if (foundW == null && topCurW != null) { 1836 // There is no wallpaper target, so it goes at the bottom. 1837 // We will assume it is the same place as last time, if known. 1838 foundW = topCurW; 1839 foundI = topCurI+1; 1840 } else { 1841 // Okay i is the position immediately above the wallpaper. Look at 1842 // what is below it for later. 1843 foundW = foundI > 0 ? windows.get(foundI-1) : null; 1844 } 1845 1846 if (visible) { 1847 if (mWallpaperTarget.mWallpaperX >= 0) { 1848 mLastWallpaperX = mWallpaperTarget.mWallpaperX; 1849 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep; 1850 } 1851 if (mWallpaperTarget.mWallpaperY >= 0) { 1852 mLastWallpaperY = mWallpaperTarget.mWallpaperY; 1853 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep; 1854 } 1855 } 1856 1857 // Start stepping backwards from here, ensuring that our wallpaper windows 1858 // are correctly placed. 1859 int changed = 0; 1860 int curTokenIndex = mWallpaperTokens.size(); 1861 while (curTokenIndex > 0) { 1862 curTokenIndex--; 1863 WindowToken token = mWallpaperTokens.get(curTokenIndex); 1864 if (token.hidden == visible) { 1865 if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, 1866 "Wallpaper token " + token + " hidden=" + !visible); 1867 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED; 1868 token.hidden = !visible; 1869 // Need to do a layout to ensure the wallpaper now has the 1870 // correct size. 1871 getDefaultDisplayContentLocked().layoutNeeded = true; 1872 } 1873 1874 int curWallpaperIndex = token.windows.size(); 1875 while (curWallpaperIndex > 0) { 1876 curWallpaperIndex--; 1877 WindowState wallpaper = token.windows.get(curWallpaperIndex); 1878 1879 if (visible) { 1880 updateWallpaperOffsetLocked(wallpaper, dw, dh, false); 1881 } 1882 1883 // First, make sure the client has the current visibility 1884 // state. 1885 dispatchWallpaperVisibility(wallpaper, visible); 1886 1887 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment; 1888 if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win " 1889 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); 1890 1891 // First, if this window is at the current index, then all 1892 // is well. 1893 if (wallpaper == foundW) { 1894 foundI--; 1895 foundW = foundI > 0 1896 ? windows.get(foundI-1) : null; 1897 continue; 1898 } 1899 1900 // The window didn't match... the current wallpaper window, 1901 // wherever it is, is in the wrong place, so make sure it is 1902 // not in the list. 1903 int oldIndex = windows.indexOf(wallpaper); 1904 if (oldIndex >= 0) { 1905 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at " 1906 + oldIndex + ": " + wallpaper); 1907 windows.remove(oldIndex); 1908 mWindowsChanged = true; 1909 if (oldIndex < foundI) { 1910 foundI--; 1911 } 1912 } 1913 1914 // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost 1915 // layer. For keyguard over wallpaper put the wallpaper under the keyguard. 1916 int insertionIndex = 0; 1917 if (visible && foundW != null) { 1918 final int type = foundW.mAttrs.type; 1919 final int privateFlags = foundW.mAttrs.privateFlags; 1920 if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 1921 || type == TYPE_KEYGUARD_SCRIM) { 1922 insertionIndex = windows.indexOf(foundW); 1923 } 1924 } 1925 if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) { 1926 Slog.v(TAG, "Moving wallpaper " + wallpaper 1927 + " from " + oldIndex + " to " + insertionIndex); 1928 } 1929 1930 windows.add(insertionIndex, wallpaper); 1931 mWindowsChanged = true; 1932 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED; 1933 } 1934 } 1935 1936 /* 1937 final TaskStack targetStack = 1938 mWallpaperTarget == null ? null : mWallpaperTarget.getStack(); 1939 if ((changed & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0 && 1940 targetStack != null && !targetStack.isHomeStack()) { 1941 // If the wallpaper target is not on the home stack then make sure that all windows 1942 // from other non-home stacks are above the wallpaper. 1943 for (i = foundI - 1; i >= 0; --i) { 1944 WindowState win = windows.get(i); 1945 if (!win.isVisibleLw()) { 1946 continue; 1947 } 1948 final TaskStack winStack = win.getStack(); 1949 if (winStack != null && !winStack.isHomeStack() && winStack != targetStack) { 1950 windows.remove(i); 1951 windows.add(foundI + 1, win); 1952 } 1953 } 1954 } 1955 */ 1956 1957 if (targetChanged && DEBUG_WALLPAPER_LIGHT) { 1958 Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget 1959 + " lower=" + mLowerWallpaperTarget + " upper=" 1960 + mUpperWallpaperTarget); 1961 } 1962 1963 return changed; 1964 } 1965 1966 void setWallpaperAnimLayerAdjustmentLocked(int adj) { 1967 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, 1968 "Setting wallpaper layer adj to " + adj); 1969 mWallpaperAnimLayerAdjustment = adj; 1970 int curTokenIndex = mWallpaperTokens.size(); 1971 while (curTokenIndex > 0) { 1972 curTokenIndex--; 1973 WindowToken token = mWallpaperTokens.get(curTokenIndex); 1974 int curWallpaperIndex = token.windows.size(); 1975 while (curWallpaperIndex > 0) { 1976 curWallpaperIndex--; 1977 WindowState wallpaper = token.windows.get(curWallpaperIndex); 1978 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj; 1979 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win " 1980 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); 1981 } 1982 } 1983 } 1984 1985 boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh, 1986 boolean sync) { 1987 boolean changed = false; 1988 boolean rawChanged = false; 1989 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f; 1990 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f; 1991 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw; 1992 int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0; 1993 changed = wallpaperWin.mXOffset != offset; 1994 if (changed) { 1995 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " 1996 + wallpaperWin + " x: " + offset); 1997 wallpaperWin.mXOffset = offset; 1998 } 1999 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) { 2000 wallpaperWin.mWallpaperX = wpx; 2001 wallpaperWin.mWallpaperXStep = wpxs; 2002 rawChanged = true; 2003 } 2004 2005 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f; 2006 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f; 2007 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh; 2008 offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0; 2009 if (wallpaperWin.mYOffset != offset) { 2010 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " 2011 + wallpaperWin + " y: " + offset); 2012 changed = true; 2013 wallpaperWin.mYOffset = offset; 2014 } 2015 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) { 2016 wallpaperWin.mWallpaperY = wpy; 2017 wallpaperWin.mWallpaperYStep = wpys; 2018 rawChanged = true; 2019 } 2020 2021 if (rawChanged && (wallpaperWin.mAttrs.privateFlags & 2022 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) { 2023 try { 2024 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset " 2025 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX 2026 + " y=" + wallpaperWin.mWallpaperY); 2027 if (sync) { 2028 mWaitingOnWallpaper = wallpaperWin; 2029 } 2030 wallpaperWin.mClient.dispatchWallpaperOffsets( 2031 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY, 2032 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync); 2033 if (sync) { 2034 if (mWaitingOnWallpaper != null) { 2035 long start = SystemClock.uptimeMillis(); 2036 if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY) 2037 < start) { 2038 try { 2039 if (DEBUG_WALLPAPER) Slog.v(TAG, 2040 "Waiting for offset complete..."); 2041 mWindowMap.wait(WALLPAPER_TIMEOUT); 2042 } catch (InterruptedException e) { 2043 } 2044 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!"); 2045 if ((start+WALLPAPER_TIMEOUT) 2046 < SystemClock.uptimeMillis()) { 2047 Slog.i(TAG, "Timeout waiting for wallpaper to offset: " 2048 + wallpaperWin); 2049 mLastWallpaperTimeoutTime = start; 2050 } 2051 } 2052 mWaitingOnWallpaper = null; 2053 } 2054 } 2055 } catch (RemoteException e) { 2056 } 2057 } 2058 2059 return changed; 2060 } 2061 2062 void wallpaperOffsetsComplete(IBinder window) { 2063 synchronized (mWindowMap) { 2064 if (mWaitingOnWallpaper != null && 2065 mWaitingOnWallpaper.mClient.asBinder() == window) { 2066 mWaitingOnWallpaper = null; 2067 mWindowMap.notifyAll(); 2068 } 2069 } 2070 } 2071 2072 void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) { 2073 final DisplayContent displayContent = changingTarget.getDisplayContent(); 2074 if (displayContent == null) { 2075 return; 2076 } 2077 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2078 final int dw = displayInfo.logicalWidth; 2079 final int dh = displayInfo.logicalHeight; 2080 2081 WindowState target = mWallpaperTarget; 2082 if (target != null) { 2083 if (target.mWallpaperX >= 0) { 2084 mLastWallpaperX = target.mWallpaperX; 2085 } else if (changingTarget.mWallpaperX >= 0) { 2086 mLastWallpaperX = changingTarget.mWallpaperX; 2087 } 2088 if (target.mWallpaperY >= 0) { 2089 mLastWallpaperY = target.mWallpaperY; 2090 } else if (changingTarget.mWallpaperY >= 0) { 2091 mLastWallpaperY = changingTarget.mWallpaperY; 2092 } 2093 } 2094 2095 int curTokenIndex = mWallpaperTokens.size(); 2096 while (curTokenIndex > 0) { 2097 curTokenIndex--; 2098 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2099 int curWallpaperIndex = token.windows.size(); 2100 while (curWallpaperIndex > 0) { 2101 curWallpaperIndex--; 2102 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2103 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) { 2104 WindowStateAnimator winAnimator = wallpaper.mWinAnimator; 2105 winAnimator.computeShownFrameLocked(); 2106 // No need to lay out the windows - we can just set the wallpaper position 2107 // directly. 2108 winAnimator.setWallpaperOffset(wallpaper.mShownFrame); 2109 // We only want to be synchronous with one wallpaper. 2110 sync = false; 2111 } 2112 } 2113 } 2114 } 2115 2116 /** 2117 * Check wallpaper for visiblity change and notify window if so. 2118 * @param wallpaper The wallpaper to test and notify. 2119 * @param visible Current visibility. 2120 */ 2121 void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) { 2122 if (wallpaper.mWallpaperVisible != visible) { 2123 wallpaper.mWallpaperVisible = visible; 2124 try { 2125 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 2126 "Updating vis of wallpaper " + wallpaper 2127 + ": " + visible + " from:\n" + Debug.getCallers(4, " ")); 2128 wallpaper.mClient.dispatchAppVisibility(visible); 2129 } catch (RemoteException e) { 2130 } 2131 } 2132 } 2133 2134 void updateWallpaperVisibilityLocked() { 2135 final boolean visible = isWallpaperVisible(mWallpaperTarget); 2136 final DisplayContent displayContent = mWallpaperTarget.getDisplayContent(); 2137 if (displayContent == null) { 2138 return; 2139 } 2140 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2141 final int dw = displayInfo.logicalWidth; 2142 final int dh = displayInfo.logicalHeight; 2143 2144 int curTokenIndex = mWallpaperTokens.size(); 2145 while (curTokenIndex > 0) { 2146 curTokenIndex--; 2147 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2148 if (token.hidden == visible) { 2149 token.hidden = !visible; 2150 // Need to do a layout to ensure the wallpaper now has the 2151 // correct size. 2152 getDefaultDisplayContentLocked().layoutNeeded = true; 2153 } 2154 2155 int curWallpaperIndex = token.windows.size(); 2156 while (curWallpaperIndex > 0) { 2157 curWallpaperIndex--; 2158 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2159 if (visible) { 2160 updateWallpaperOffsetLocked(wallpaper, dw, dh, false); 2161 } 2162 2163 dispatchWallpaperVisibility(wallpaper, visible); 2164 } 2165 } 2166 } 2167 2168 public int addWindow(Session session, IWindow client, int seq, 2169 WindowManager.LayoutParams attrs, int viewVisibility, int displayId, 2170 Rect outContentInsets, InputChannel outInputChannel) { 2171 int[] appOp = new int[1]; 2172 int res = mPolicy.checkAddPermission(attrs, appOp); 2173 if (res != WindowManagerGlobal.ADD_OKAY) { 2174 return res; 2175 } 2176 2177 boolean reportNewConfig = false; 2178 WindowState attachedWindow = null; 2179 WindowState win = null; 2180 long origId; 2181 final int type = attrs.type; 2182 2183 synchronized(mWindowMap) { 2184 if (!mDisplayReady) { 2185 throw new IllegalStateException("Display has not been initialialized"); 2186 } 2187 2188 final DisplayContent displayContent = getDisplayContentLocked(displayId); 2189 if (displayContent == null) { 2190 Slog.w(TAG, "Attempted to add window to a display that does not exist: " 2191 + displayId + ". Aborting."); 2192 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2193 } 2194 if (!displayContent.hasAccess(session.mUid)) { 2195 Slog.w(TAG, "Attempted to add window to a display for which the application " 2196 + "does not have access: " + displayId + ". Aborting."); 2197 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2198 } 2199 2200 if (mWindowMap.containsKey(client.asBinder())) { 2201 Slog.w(TAG, "Window " + client + " is already added"); 2202 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 2203 } 2204 2205 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) { 2206 attachedWindow = windowForClientLocked(null, attrs.token, false); 2207 if (attachedWindow == null) { 2208 Slog.w(TAG, "Attempted to add window with token that is not a window: " 2209 + attrs.token + ". Aborting."); 2210 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 2211 } 2212 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW 2213 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) { 2214 Slog.w(TAG, "Attempted to add window with token that is a sub-window: " 2215 + attrs.token + ". Aborting."); 2216 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 2217 } 2218 } 2219 2220 if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) { 2221 Slog.w(TAG, "Attempted to add private presentation window to a non-private display. Aborting."); 2222 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 2223 } 2224 2225 boolean addToken = false; 2226 WindowToken token = mTokenMap.get(attrs.token); 2227 if (token == null) { 2228 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2229 Slog.w(TAG, "Attempted to add application window with unknown token " 2230 + attrs.token + ". Aborting."); 2231 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2232 } 2233 if (type == TYPE_INPUT_METHOD) { 2234 Slog.w(TAG, "Attempted to add input method window with unknown token " 2235 + attrs.token + ". Aborting."); 2236 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2237 } 2238 if (type == TYPE_VOICE_INTERACTION) { 2239 Slog.w(TAG, "Attempted to add voice interaction window with unknown token " 2240 + attrs.token + ". Aborting."); 2241 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2242 } 2243 if (type == TYPE_WALLPAPER) { 2244 Slog.w(TAG, "Attempted to add wallpaper window with unknown token " 2245 + attrs.token + ". Aborting."); 2246 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2247 } 2248 if (type == TYPE_DREAM) { 2249 Slog.w(TAG, "Attempted to add Dream window with unknown token " 2250 + attrs.token + ". Aborting."); 2251 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2252 } 2253 token = new WindowToken(this, attrs.token, -1, false); 2254 addToken = true; 2255 } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2256 AppWindowToken atoken = token.appWindowToken; 2257 if (atoken == null) { 2258 Slog.w(TAG, "Attempted to add window with non-application token " 2259 + token + ". Aborting."); 2260 return WindowManagerGlobal.ADD_NOT_APP_TOKEN; 2261 } else if (atoken.removed) { 2262 Slog.w(TAG, "Attempted to add window with exiting application token " 2263 + token + ". Aborting."); 2264 return WindowManagerGlobal.ADD_APP_EXITING; 2265 } 2266 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) { 2267 // No need for this guy! 2268 if (localLOGV) Slog.v( 2269 TAG, "**** NO NEED TO START: " + attrs.getTitle()); 2270 return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED; 2271 } 2272 } else if (type == TYPE_INPUT_METHOD) { 2273 if (token.windowType != TYPE_INPUT_METHOD) { 2274 Slog.w(TAG, "Attempted to add input method window with bad token " 2275 + attrs.token + ". Aborting."); 2276 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2277 } 2278 } else if (type == TYPE_VOICE_INTERACTION) { 2279 if (token.windowType != TYPE_VOICE_INTERACTION) { 2280 Slog.w(TAG, "Attempted to add voice interaction window with bad token " 2281 + attrs.token + ". Aborting."); 2282 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2283 } 2284 } else if (type == TYPE_WALLPAPER) { 2285 if (token.windowType != TYPE_WALLPAPER) { 2286 Slog.w(TAG, "Attempted to add wallpaper window with bad token " 2287 + attrs.token + ". Aborting."); 2288 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2289 } 2290 } else if (type == TYPE_DREAM) { 2291 if (token.windowType != TYPE_DREAM) { 2292 Slog.w(TAG, "Attempted to add Dream window with bad token " 2293 + attrs.token + ". Aborting."); 2294 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2295 } 2296 } 2297 2298 win = new WindowState(this, session, client, token, 2299 attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent); 2300 if (win.mDeathRecipient == null) { 2301 // Client has apparently died, so there is no reason to 2302 // continue. 2303 Slog.w(TAG, "Adding window client " + client.asBinder() 2304 + " that is dead, aborting."); 2305 return WindowManagerGlobal.ADD_APP_EXITING; 2306 } 2307 2308 if (win.getDisplayContent() == null) { 2309 Slog.w(TAG, "Adding window to Display that has been removed."); 2310 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2311 } 2312 2313 mPolicy.adjustWindowParamsLw(win.mAttrs); 2314 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs)); 2315 2316 res = mPolicy.prepareAddWindowLw(win, attrs); 2317 if (res != WindowManagerGlobal.ADD_OKAY) { 2318 return res; 2319 } 2320 2321 if (outInputChannel != null && (attrs.inputFeatures 2322 & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) { 2323 String name = win.makeInputChannelName(); 2324 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); 2325 win.setInputChannel(inputChannels[0]); 2326 inputChannels[1].transferTo(outInputChannel); 2327 2328 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle); 2329 } 2330 2331 // From now on, no exceptions or errors allowed! 2332 2333 res = WindowManagerGlobal.ADD_OKAY; 2334 2335 origId = Binder.clearCallingIdentity(); 2336 2337 if (addToken) { 2338 mTokenMap.put(attrs.token, token); 2339 } 2340 win.attach(); 2341 mWindowMap.put(client.asBinder(), win); 2342 if (win.mAppOp != AppOpsManager.OP_NONE) { 2343 if (mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage()) 2344 != AppOpsManager.MODE_ALLOWED) { 2345 win.setAppOpVisibilityLw(false); 2346 } 2347 } 2348 2349 if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) { 2350 token.appWindowToken.startingWindow = win; 2351 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken 2352 + " startingWindow=" + win); 2353 } 2354 2355 boolean imMayMove = true; 2356 2357 if (type == TYPE_INPUT_METHOD) { 2358 win.mGivenInsetsPending = true; 2359 mInputMethodWindow = win; 2360 addInputMethodWindowToListLocked(win); 2361 imMayMove = false; 2362 } else if (type == TYPE_INPUT_METHOD_DIALOG) { 2363 mInputMethodDialogs.add(win); 2364 addWindowToListInOrderLocked(win, true); 2365 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true)); 2366 imMayMove = false; 2367 } else { 2368 addWindowToListInOrderLocked(win, true); 2369 if (type == TYPE_WALLPAPER) { 2370 mLastWallpaperTimeoutTime = 0; 2371 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2372 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2373 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2374 } else if (mWallpaperTarget != null 2375 && mWallpaperTarget.mLayer >= win.mBaseLayer) { 2376 // If there is currently a wallpaper being shown, and 2377 // the base layer of the new window is below the current 2378 // layer of the target window, then adjust the wallpaper. 2379 // This is to avoid a new window being placed between the 2380 // wallpaper and its target. 2381 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2382 } 2383 } 2384 2385 win.mWinAnimator.mEnterAnimationPending = true; 2386 2387 if (displayContent.isDefaultDisplay) { 2388 mPolicy.getContentInsetHintLw(attrs, outContentInsets); 2389 } else { 2390 outContentInsets.setEmpty(); 2391 } 2392 2393 if (mInTouchMode) { 2394 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE; 2395 } 2396 if (win.mAppToken == null || !win.mAppToken.clientHidden) { 2397 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE; 2398 } 2399 2400 mInputMonitor.setUpdateInputWindowsNeededLw(); 2401 2402 boolean focusChanged = false; 2403 if (win.canReceiveKeys()) { 2404 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, 2405 false /*updateInputWindows*/); 2406 if (focusChanged) { 2407 imMayMove = false; 2408 } 2409 } 2410 2411 if (imMayMove) { 2412 moveInputMethodWindowsIfNeededLocked(false); 2413 } 2414 2415 assignLayersLocked(displayContent.getWindowList()); 2416 // Don't do layout here, the window must call 2417 // relayout to be displayed, so we'll do it there. 2418 2419 if (focusChanged) { 2420 finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/); 2421 } 2422 mInputMonitor.updateInputWindowsLw(false /*force*/); 2423 2424 if (localLOGV) Slog.v( 2425 TAG, "New client " + client.asBinder() 2426 + ": window=" + win); 2427 2428 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) { 2429 reportNewConfig = true; 2430 } 2431 } 2432 2433 if (reportNewConfig) { 2434 sendNewConfiguration(); 2435 } 2436 2437 Binder.restoreCallingIdentity(origId); 2438 2439 return res; 2440 } 2441 2442 public void removeWindow(Session session, IWindow client) { 2443 synchronized(mWindowMap) { 2444 WindowState win = windowForClientLocked(session, client, false); 2445 if (win == null) { 2446 return; 2447 } 2448 removeWindowLocked(session, win); 2449 } 2450 } 2451 2452 public void removeWindowLocked(Session session, WindowState win) { 2453 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2454 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Starting window removed " + win); 2455 } 2456 2457 if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v( 2458 TAG, "Remove " + win + " client=" 2459 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder())) 2460 + ", surface=" + win.mWinAnimator.mSurfaceControl + " Callers=" 2461 + Debug.getCallers(4)); 2462 2463 final long origId = Binder.clearCallingIdentity(); 2464 2465 win.disposeInputChannel(); 2466 2467 if (DEBUG_APP_TRANSITIONS) Slog.v( 2468 TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurfaceControl 2469 + " mExiting=" + win.mExiting 2470 + " isAnimating=" + win.mWinAnimator.isAnimating() 2471 + " app-animation=" 2472 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null) 2473 + " inPendingTransaction=" 2474 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false) 2475 + " mDisplayFrozen=" + mDisplayFrozen); 2476 // Visibility of the removed window. Will be used later to update orientation later on. 2477 boolean wasVisible = false; 2478 // First, see if we need to run an animation. If we do, we have 2479 // to hold off on removing the window until the animation is done. 2480 // If the display is frozen, just remove immediately, since the 2481 // animation wouldn't be seen. 2482 if (win.mHasSurface && okToDisplay()) { 2483 // If we are not currently running the exit animation, we 2484 // need to see about starting one. 2485 wasVisible = win.isWinVisibleLw(); 2486 if (wasVisible) { 2487 2488 int transit = WindowManagerPolicy.TRANSIT_EXIT; 2489 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2490 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 2491 } 2492 // Try starting an animation. 2493 if (win.mWinAnimator.applyAnimationLocked(transit, false)) { 2494 win.mExiting = true; 2495 } 2496 //TODO (multidisplay): Magnification is supported only for the default display. 2497 if (mAccessibilityController != null 2498 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 2499 mAccessibilityController.onWindowTransitionLocked(win, transit); 2500 } 2501 } 2502 if (win.mExiting || win.mWinAnimator.isAnimating()) { 2503 // The exit animation is running... wait for it! 2504 //Slog.i(TAG, "*** Running exit animation..."); 2505 win.mExiting = true; 2506 win.mRemoveOnExit = true; 2507 final DisplayContent displayContent = win.getDisplayContent(); 2508 if (displayContent != null) { 2509 displayContent.layoutNeeded = true; 2510 } 2511 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 2512 false /*updateInputWindows*/); 2513 performLayoutAndPlaceSurfacesLocked(); 2514 if (win.mAppToken != null) { 2515 win.mAppToken.updateReportedVisibilityLocked(); 2516 } 2517 //dump(); 2518 Binder.restoreCallingIdentity(origId); 2519 return; 2520 } 2521 } 2522 2523 removeWindowInnerLocked(session, win); 2524 // Removing a visible window will effect the computed orientation 2525 // So just update orientation if needed. 2526 if (wasVisible && updateOrientationFromAppTokensLocked(false)) { 2527 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 2528 } 2529 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 2530 Binder.restoreCallingIdentity(origId); 2531 } 2532 2533 void removeWindowInnerLocked(Session session, WindowState win) { 2534 if (win.mRemoved) { 2535 // Nothing to do. 2536 return; 2537 } 2538 2539 for (int i=win.mChildWindows.size()-1; i>=0; i--) { 2540 WindowState cwin = win.mChildWindows.get(i); 2541 Slog.w(TAG, "Force-removing child win " + cwin + " from container " 2542 + win); 2543 removeWindowInnerLocked(cwin.mSession, cwin); 2544 } 2545 2546 win.mRemoved = true; 2547 2548 if (mInputMethodTarget == win) { 2549 moveInputMethodWindowsIfNeededLocked(false); 2550 } 2551 2552 if (false) { 2553 RuntimeException e = new RuntimeException("here"); 2554 e.fillInStackTrace(); 2555 Slog.w(TAG, "Removing window " + win, e); 2556 } 2557 2558 mPolicy.removeWindowLw(win); 2559 win.removeLocked(); 2560 2561 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win); 2562 mWindowMap.remove(win.mClient.asBinder()); 2563 if (win.mAppOp != AppOpsManager.OP_NONE) { 2564 mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage()); 2565 } 2566 2567 mPendingRemove.remove(win); 2568 mResizingWindows.remove(win); 2569 mWindowsChanged = true; 2570 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win); 2571 2572 if (mInputMethodWindow == win) { 2573 mInputMethodWindow = null; 2574 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) { 2575 mInputMethodDialogs.remove(win); 2576 } 2577 2578 final WindowToken token = win.mToken; 2579 final AppWindowToken atoken = win.mAppToken; 2580 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token); 2581 token.windows.remove(win); 2582 if (atoken != null) { 2583 atoken.allAppWindows.remove(win); 2584 } 2585 if (localLOGV) Slog.v( 2586 TAG, "**** Removing window " + win + ": count=" 2587 + token.windows.size()); 2588 if (token.windows.size() == 0) { 2589 if (!token.explicit) { 2590 mTokenMap.remove(token.token); 2591 } else if (atoken != null) { 2592 atoken.firstWindowDrawn = false; 2593 } 2594 } 2595 2596 if (atoken != null) { 2597 if (atoken.startingWindow == win) { 2598 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling startingWindow " + win); 2599 atoken.startingWindow = null; 2600 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) { 2601 // If this is the last window and we had requested a starting 2602 // transition window, well there is no point now. 2603 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling last startingWindow"); 2604 atoken.startingData = null; 2605 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) { 2606 // If this is the last window except for a starting transition 2607 // window, we need to get rid of the starting transition. 2608 scheduleRemoveStartingWindow(atoken); 2609 } 2610 } 2611 2612 if (win.mAttrs.type == TYPE_WALLPAPER) { 2613 mLastWallpaperTimeoutTime = 0; 2614 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2615 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2616 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2617 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2618 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2619 } 2620 2621 final WindowList windows = win.getWindowList(); 2622 if (windows != null) { 2623 windows.remove(win); 2624 if (!mInLayout) { 2625 assignLayersLocked(windows); 2626 final DisplayContent displayContent = win.getDisplayContent(); 2627 if (displayContent != null) { 2628 displayContent.layoutNeeded = true; 2629 } 2630 performLayoutAndPlaceSurfacesLocked(); 2631 if (win.mAppToken != null) { 2632 win.mAppToken.updateReportedVisibilityLocked(); 2633 } 2634 } 2635 } 2636 2637 mInputMonitor.updateInputWindowsLw(true /*force*/); 2638 } 2639 2640 public void updateAppOpsState() { 2641 synchronized(mWindowMap) { 2642 final int numDisplays = mDisplayContents.size(); 2643 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 2644 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 2645 final int numWindows = windows.size(); 2646 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 2647 final WindowState win = windows.get(winNdx); 2648 if (win.mAppOp != AppOpsManager.OP_NONE) { 2649 final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(), 2650 win.getOwningPackage()); 2651 win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED); 2652 } 2653 } 2654 } 2655 } 2656 } 2657 2658 static void logSurface(WindowState w, String msg, RuntimeException where) { 2659 String str = " SURFACE " + msg + ": " + w; 2660 if (where != null) { 2661 Slog.i(TAG, str, where); 2662 } else { 2663 Slog.i(TAG, str); 2664 } 2665 } 2666 2667 static void logSurface(SurfaceControl s, String title, String msg, RuntimeException where) { 2668 String str = " SURFACE " + s + ": " + msg + " / " + title; 2669 if (where != null) { 2670 Slog.i(TAG, str, where); 2671 } else { 2672 Slog.i(TAG, str); 2673 } 2674 } 2675 2676 void setTransparentRegionWindow(Session session, IWindow client, Region region) { 2677 long origId = Binder.clearCallingIdentity(); 2678 try { 2679 synchronized (mWindowMap) { 2680 WindowState w = windowForClientLocked(session, client, false); 2681 if ((w != null) && w.mHasSurface) { 2682 w.mWinAnimator.setTransparentRegionHintLocked(region); 2683 } 2684 } 2685 } finally { 2686 Binder.restoreCallingIdentity(origId); 2687 } 2688 } 2689 2690 void setInsetsWindow(Session session, IWindow client, 2691 int touchableInsets, Rect contentInsets, 2692 Rect visibleInsets, Region touchableRegion) { 2693 long origId = Binder.clearCallingIdentity(); 2694 try { 2695 synchronized (mWindowMap) { 2696 WindowState w = windowForClientLocked(session, client, false); 2697 if (w != null) { 2698 w.mGivenInsetsPending = false; 2699 w.mGivenContentInsets.set(contentInsets); 2700 w.mGivenVisibleInsets.set(visibleInsets); 2701 w.mGivenTouchableRegion.set(touchableRegion); 2702 w.mTouchableInsets = touchableInsets; 2703 if (w.mGlobalScale != 1) { 2704 w.mGivenContentInsets.scale(w.mGlobalScale); 2705 w.mGivenVisibleInsets.scale(w.mGlobalScale); 2706 w.mGivenTouchableRegion.scale(w.mGlobalScale); 2707 } 2708 final DisplayContent displayContent = w.getDisplayContent(); 2709 if (displayContent != null) { 2710 displayContent.layoutNeeded = true; 2711 } 2712 performLayoutAndPlaceSurfacesLocked(); 2713 } 2714 } 2715 } finally { 2716 Binder.restoreCallingIdentity(origId); 2717 } 2718 } 2719 2720 public void getWindowDisplayFrame(Session session, IWindow client, 2721 Rect outDisplayFrame) { 2722 synchronized(mWindowMap) { 2723 WindowState win = windowForClientLocked(session, client, false); 2724 if (win == null) { 2725 outDisplayFrame.setEmpty(); 2726 return; 2727 } 2728 outDisplayFrame.set(win.mDisplayFrame); 2729 } 2730 } 2731 2732 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y, 2733 float xStep, float yStep) { 2734 if (window.mWallpaperX != x || window.mWallpaperY != y) { 2735 window.mWallpaperX = x; 2736 window.mWallpaperY = y; 2737 window.mWallpaperXStep = xStep; 2738 window.mWallpaperYStep = yStep; 2739 updateWallpaperOffsetLocked(window, true); 2740 } 2741 } 2742 2743 void wallpaperCommandComplete(IBinder window, Bundle result) { 2744 synchronized (mWindowMap) { 2745 if (mWaitingOnWallpaper != null && 2746 mWaitingOnWallpaper.mClient.asBinder() == window) { 2747 mWaitingOnWallpaper = null; 2748 mWindowMap.notifyAll(); 2749 } 2750 } 2751 } 2752 2753 public Bundle sendWindowWallpaperCommandLocked(WindowState window, 2754 String action, int x, int y, int z, Bundle extras, boolean sync) { 2755 if (window == mWallpaperTarget || window == mLowerWallpaperTarget 2756 || window == mUpperWallpaperTarget) { 2757 boolean doWait = sync; 2758 int curTokenIndex = mWallpaperTokens.size(); 2759 while (curTokenIndex > 0) { 2760 curTokenIndex--; 2761 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2762 int curWallpaperIndex = token.windows.size(); 2763 while (curWallpaperIndex > 0) { 2764 curWallpaperIndex--; 2765 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2766 try { 2767 wallpaper.mClient.dispatchWallpaperCommand(action, 2768 x, y, z, extras, sync); 2769 // We only want to be synchronous with one wallpaper. 2770 sync = false; 2771 } catch (RemoteException e) { 2772 } 2773 } 2774 } 2775 2776 if (doWait) { 2777 // XXX Need to wait for result. 2778 } 2779 } 2780 2781 return null; 2782 } 2783 2784 public void setUniverseTransformLocked(WindowState window, float alpha, 2785 float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) { 2786 Transformation transform = window.mWinAnimator.mUniverseTransform; 2787 transform.setAlpha(alpha); 2788 Matrix matrix = transform.getMatrix(); 2789 matrix.getValues(mTmpFloats); 2790 mTmpFloats[Matrix.MTRANS_X] = offx; 2791 mTmpFloats[Matrix.MTRANS_Y] = offy; 2792 mTmpFloats[Matrix.MSCALE_X] = dsdx; 2793 mTmpFloats[Matrix.MSKEW_Y] = dtdx; 2794 mTmpFloats[Matrix.MSKEW_X] = dsdy; 2795 mTmpFloats[Matrix.MSCALE_Y] = dtdy; 2796 matrix.setValues(mTmpFloats); 2797 final DisplayContent displayContent = window.getDisplayContent(); 2798 if (displayContent == null) { 2799 return; 2800 } 2801 2802 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2803 final RectF dispRect = new RectF(0, 0, 2804 displayInfo.logicalWidth, displayInfo.logicalHeight); 2805 matrix.mapRect(dispRect); 2806 window.mGivenTouchableRegion.set(0, 0, 2807 displayInfo.logicalWidth, displayInfo.logicalHeight); 2808 window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top, 2809 (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE); 2810 window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; 2811 displayContent.layoutNeeded = true; 2812 performLayoutAndPlaceSurfacesLocked(); 2813 } 2814 2815 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) { 2816 synchronized (mWindowMap) { 2817 if (mAccessibilityController != null) { 2818 WindowState window = mWindowMap.get(token); 2819 //TODO (multidisplay): Magnification is supported only for the default display. 2820 if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 2821 mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle); 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 Runnable 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 callback.run(); 7573 } 7574 break; 7575 } 7576 7577 case SHOW_STRICT_MODE_VIOLATION: { 7578 showStrictModeViolation(msg.arg1, msg.arg2); 7579 break; 7580 } 7581 7582 case DO_ANIMATION_CALLBACK: { 7583 try { 7584 ((IRemoteCallback)msg.obj).sendResult(null); 7585 } catch (RemoteException e) { 7586 } 7587 break; 7588 } 7589 7590 case DO_DISPLAY_ADDED: 7591 handleDisplayAdded(msg.arg1); 7592 break; 7593 7594 case DO_DISPLAY_REMOVED: 7595 synchronized (mWindowMap) { 7596 handleDisplayRemovedLocked(msg.arg1); 7597 } 7598 break; 7599 7600 case DO_DISPLAY_CHANGED: 7601 synchronized (mWindowMap) { 7602 handleDisplayChangedLocked(msg.arg1); 7603 } 7604 break; 7605 7606 case TAP_OUTSIDE_STACK: { 7607 int stackId; 7608 synchronized (mWindowMap) { 7609 stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2); 7610 } 7611 if (stackId >= 0) { 7612 try { 7613 mActivityManager.setFocusedStack(stackId); 7614 } catch (RemoteException e) { 7615 } 7616 } 7617 } 7618 break; 7619 case NOTIFY_ACTIVITY_DRAWN: 7620 try { 7621 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 7622 } catch (RemoteException e) { 7623 } 7624 break; 7625 case ALL_WINDOWS_DRAWN: { 7626 Runnable callback; 7627 synchronized (mWindowMap) { 7628 callback = mWaitingForDrawnCallback; 7629 mWaitingForDrawnCallback = null; 7630 } 7631 if (callback != null) { 7632 callback.run(); 7633 } 7634 } 7635 case NEW_ANIMATOR_SCALE: { 7636 float scale = getCurrentAnimatorScale(); 7637 ValueAnimator.setDurationScale(scale); 7638 Session session = (Session)msg.obj; 7639 if (session != null) { 7640 try { 7641 session.mCallback.onAnimatorScaleChanged(scale); 7642 } catch (RemoteException e) { 7643 } 7644 } else { 7645 ArrayList<IWindowSessionCallback> callbacks 7646 = new ArrayList<IWindowSessionCallback>(); 7647 synchronized (mWindowMap) { 7648 for (int i=0; i<mSessions.size(); i++) { 7649 callbacks.add(mSessions.valueAt(i).mCallback); 7650 } 7651 7652 } 7653 for (int i=0; i<callbacks.size(); i++) { 7654 try { 7655 callbacks.get(i).onAnimatorScaleChanged(scale); 7656 } catch (RemoteException e) { 7657 } 7658 } 7659 } 7660 } 7661 break; 7662 } 7663 if (DEBUG_WINDOW_TRACE) { 7664 Slog.v(TAG, "handleMessage: exit"); 7665 } 7666 } 7667 } 7668 7669 // ------------------------------------------------------------- 7670 // IWindowManager API 7671 // ------------------------------------------------------------- 7672 7673 @Override 7674 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, 7675 IInputContext inputContext) { 7676 if (client == null) throw new IllegalArgumentException("null client"); 7677 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7678 Session session = new Session(this, callback, client, inputContext); 7679 return session; 7680 } 7681 7682 @Override 7683 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7684 synchronized (mWindowMap) { 7685 // The focus for the client is the window immediately below 7686 // where we would place the input method window. 7687 int idx = findDesiredInputMethodWindowIndexLocked(false); 7688 if (idx > 0) { 7689 // TODO(multidisplay): IMEs are only supported on the default display. 7690 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 7691 if (DEBUG_INPUT_METHOD) { 7692 Slog.i(TAG, "Desired input method target: " + imFocus); 7693 Slog.i(TAG, "Current focus: " + mCurrentFocus); 7694 Slog.i(TAG, "Last focus: " + mLastFocus); 7695 } 7696 if (imFocus != null) { 7697 // This may be a starting window, in which case we still want 7698 // to count it as okay. 7699 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7700 && imFocus.mAppToken != null) { 7701 // The client has definitely started, so it really should 7702 // have a window in this app token. Let's look for it. 7703 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7704 WindowState w = imFocus.mAppToken.windows.get(i); 7705 if (w != imFocus) { 7706 Log.i(TAG, "Switching to real app window: " + w); 7707 imFocus = w; 7708 break; 7709 } 7710 } 7711 } 7712 if (DEBUG_INPUT_METHOD) { 7713 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7714 if (imFocus.mSession.mClient != null) { 7715 Slog.i(TAG, "IM target client binder: " 7716 + imFocus.mSession.mClient.asBinder()); 7717 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 7718 } 7719 } 7720 if (imFocus.mSession.mClient != null && 7721 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7722 return true; 7723 } 7724 } 7725 } 7726 7727 // Okay, how about this... what is the current focus? 7728 // It seems in some cases we may not have moved the IM 7729 // target window, such as when it was in a pop-up window, 7730 // so let's also look at the current focus. (An example: 7731 // go to Gmail, start searching so the keyboard goes up, 7732 // press home. Sometimes the IME won't go down.) 7733 // Would be nice to fix this more correctly, but it's 7734 // way at the end of a release, and this should be good enough. 7735 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 7736 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7737 return true; 7738 } 7739 } 7740 return false; 7741 } 7742 7743 @Override 7744 public void getInitialDisplaySize(int displayId, Point size) { 7745 synchronized (mWindowMap) { 7746 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7747 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7748 synchronized(displayContent.mDisplaySizeLock) { 7749 size.x = displayContent.mInitialDisplayWidth; 7750 size.y = displayContent.mInitialDisplayHeight; 7751 } 7752 } 7753 } 7754 } 7755 7756 @Override 7757 public void getBaseDisplaySize(int displayId, Point size) { 7758 synchronized (mWindowMap) { 7759 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7760 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7761 synchronized(displayContent.mDisplaySizeLock) { 7762 size.x = displayContent.mBaseDisplayWidth; 7763 size.y = displayContent.mBaseDisplayHeight; 7764 } 7765 } 7766 } 7767 } 7768 7769 @Override 7770 public void setForcedDisplaySize(int displayId, int width, int height) { 7771 if (mContext.checkCallingOrSelfPermission( 7772 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7773 PackageManager.PERMISSION_GRANTED) { 7774 throw new SecurityException("Must hold permission " + 7775 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7776 } 7777 if (displayId != Display.DEFAULT_DISPLAY) { 7778 throw new IllegalArgumentException("Can only set the default display"); 7779 } 7780 final long ident = Binder.clearCallingIdentity(); 7781 try { 7782 synchronized(mWindowMap) { 7783 // Set some sort of reasonable bounds on the size of the display that we 7784 // will try to emulate. 7785 final int MIN_WIDTH = 200; 7786 final int MIN_HEIGHT = 200; 7787 final int MAX_SCALE = 2; 7788 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7789 if (displayContent != null) { 7790 width = Math.min(Math.max(width, MIN_WIDTH), 7791 displayContent.mInitialDisplayWidth * MAX_SCALE); 7792 height = Math.min(Math.max(height, MIN_HEIGHT), 7793 displayContent.mInitialDisplayHeight * MAX_SCALE); 7794 setForcedDisplaySizeLocked(displayContent, width, height); 7795 Settings.Global.putString(mContext.getContentResolver(), 7796 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 7797 } 7798 } 7799 } finally { 7800 Binder.restoreCallingIdentity(ident); 7801 } 7802 } 7803 7804 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 7805 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 7806 Settings.Global.DISPLAY_SIZE_FORCED); 7807 if (sizeStr == null || sizeStr.length() == 0) { 7808 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 7809 } 7810 if (sizeStr != null && sizeStr.length() > 0) { 7811 final int pos = sizeStr.indexOf(','); 7812 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 7813 int width, height; 7814 try { 7815 width = Integer.parseInt(sizeStr.substring(0, pos)); 7816 height = Integer.parseInt(sizeStr.substring(pos+1)); 7817 synchronized(displayContent.mDisplaySizeLock) { 7818 if (displayContent.mBaseDisplayWidth != width 7819 || displayContent.mBaseDisplayHeight != height) { 7820 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 7821 displayContent.mBaseDisplayWidth = width; 7822 displayContent.mBaseDisplayHeight = height; 7823 } 7824 } 7825 } catch (NumberFormatException ex) { 7826 } 7827 } 7828 } 7829 String densityStr = Settings.Global.getString(mContext.getContentResolver(), 7830 Settings.Global.DISPLAY_DENSITY_FORCED); 7831 if (densityStr == null || densityStr.length() == 0) { 7832 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 7833 } 7834 if (densityStr != null && densityStr.length() > 0) { 7835 int density; 7836 try { 7837 density = Integer.parseInt(densityStr); 7838 synchronized(displayContent.mDisplaySizeLock) { 7839 if (displayContent.mBaseDisplayDensity != density) { 7840 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 7841 displayContent.mBaseDisplayDensity = density; 7842 } 7843 } 7844 } catch (NumberFormatException ex) { 7845 } 7846 } 7847 } 7848 7849 // displayContent must not be null 7850 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 7851 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7852 7853 synchronized(displayContent.mDisplaySizeLock) { 7854 displayContent.mBaseDisplayWidth = width; 7855 displayContent.mBaseDisplayHeight = height; 7856 } 7857 reconfigureDisplayLocked(displayContent); 7858 } 7859 7860 @Override 7861 public void clearForcedDisplaySize(int displayId) { 7862 if (mContext.checkCallingOrSelfPermission( 7863 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7864 PackageManager.PERMISSION_GRANTED) { 7865 throw new SecurityException("Must hold permission " + 7866 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7867 } 7868 if (displayId != Display.DEFAULT_DISPLAY) { 7869 throw new IllegalArgumentException("Can only set the default display"); 7870 } 7871 final long ident = Binder.clearCallingIdentity(); 7872 try { 7873 synchronized(mWindowMap) { 7874 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7875 if (displayContent != null) { 7876 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 7877 displayContent.mInitialDisplayHeight); 7878 Settings.Global.putString(mContext.getContentResolver(), 7879 Settings.Global.DISPLAY_SIZE_FORCED, ""); 7880 } 7881 } 7882 } finally { 7883 Binder.restoreCallingIdentity(ident); 7884 } 7885 } 7886 7887 @Override 7888 public int getInitialDisplayDensity(int displayId) { 7889 synchronized (mWindowMap) { 7890 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7891 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7892 synchronized(displayContent.mDisplaySizeLock) { 7893 return displayContent.mInitialDisplayDensity; 7894 } 7895 } 7896 } 7897 return -1; 7898 } 7899 7900 @Override 7901 public int getBaseDisplayDensity(int displayId) { 7902 synchronized (mWindowMap) { 7903 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7904 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7905 synchronized(displayContent.mDisplaySizeLock) { 7906 return displayContent.mBaseDisplayDensity; 7907 } 7908 } 7909 } 7910 return -1; 7911 } 7912 7913 @Override 7914 public void setForcedDisplayDensity(int displayId, int density) { 7915 if (mContext.checkCallingOrSelfPermission( 7916 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7917 PackageManager.PERMISSION_GRANTED) { 7918 throw new SecurityException("Must hold permission " + 7919 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7920 } 7921 if (displayId != Display.DEFAULT_DISPLAY) { 7922 throw new IllegalArgumentException("Can only set the default display"); 7923 } 7924 final long ident = Binder.clearCallingIdentity(); 7925 try { 7926 synchronized(mWindowMap) { 7927 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7928 if (displayContent != null) { 7929 setForcedDisplayDensityLocked(displayContent, density); 7930 Settings.Global.putString(mContext.getContentResolver(), 7931 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 7932 } 7933 } 7934 } finally { 7935 Binder.restoreCallingIdentity(ident); 7936 } 7937 } 7938 7939 // displayContent must not be null 7940 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 7941 Slog.i(TAG, "Using new display density: " + density); 7942 7943 synchronized(displayContent.mDisplaySizeLock) { 7944 displayContent.mBaseDisplayDensity = density; 7945 } 7946 reconfigureDisplayLocked(displayContent); 7947 } 7948 7949 @Override 7950 public void clearForcedDisplayDensity(int displayId) { 7951 if (mContext.checkCallingOrSelfPermission( 7952 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7953 PackageManager.PERMISSION_GRANTED) { 7954 throw new SecurityException("Must hold permission " + 7955 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7956 } 7957 if (displayId != Display.DEFAULT_DISPLAY) { 7958 throw new IllegalArgumentException("Can only set the default display"); 7959 } 7960 final long ident = Binder.clearCallingIdentity(); 7961 try { 7962 synchronized(mWindowMap) { 7963 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7964 if (displayContent != null) { 7965 setForcedDisplayDensityLocked(displayContent, 7966 displayContent.mInitialDisplayDensity); 7967 Settings.Global.putString(mContext.getContentResolver(), 7968 Settings.Global.DISPLAY_DENSITY_FORCED, ""); 7969 } 7970 } 7971 } finally { 7972 Binder.restoreCallingIdentity(ident); 7973 } 7974 } 7975 7976 // displayContent must not be null 7977 private void reconfigureDisplayLocked(DisplayContent displayContent) { 7978 // TODO: Multidisplay: for now only use with default display. 7979 configureDisplayPolicyLocked(displayContent); 7980 displayContent.layoutNeeded = true; 7981 7982 boolean configChanged = updateOrientationFromAppTokensLocked(false); 7983 mTempConfiguration.setToDefaults(); 7984 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 7985 if (computeScreenConfigurationLocked(mTempConfiguration)) { 7986 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 7987 configChanged = true; 7988 } 7989 } 7990 7991 if (configChanged) { 7992 mWaitingForConfig = true; 7993 startFreezingDisplayLocked(false, 0, 0); 7994 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 7995 } 7996 7997 performLayoutAndPlaceSurfacesLocked(); 7998 } 7999 8000 private void configureDisplayPolicyLocked(DisplayContent displayContent) { 8001 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 8002 displayContent.mBaseDisplayWidth, 8003 displayContent.mBaseDisplayHeight, 8004 displayContent.mBaseDisplayDensity); 8005 8006 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8007 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 8008 displayInfo.overscanLeft, displayInfo.overscanTop, 8009 displayInfo.overscanRight, displayInfo.overscanBottom); 8010 } 8011 8012 @Override 8013 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 8014 if (mContext.checkCallingOrSelfPermission( 8015 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8016 PackageManager.PERMISSION_GRANTED) { 8017 throw new SecurityException("Must hold permission " + 8018 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8019 } 8020 final long ident = Binder.clearCallingIdentity(); 8021 try { 8022 synchronized(mWindowMap) { 8023 DisplayContent displayContent = getDisplayContentLocked(displayId); 8024 if (displayContent != null) { 8025 setOverscanLocked(displayContent, left, top, right, bottom); 8026 } 8027 } 8028 } finally { 8029 Binder.restoreCallingIdentity(ident); 8030 } 8031 } 8032 8033 private void setOverscanLocked(DisplayContent displayContent, 8034 int left, int top, int right, int bottom) { 8035 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8036 synchronized (displayContent.mDisplaySizeLock) { 8037 displayInfo.overscanLeft = left; 8038 displayInfo.overscanTop = top; 8039 displayInfo.overscanRight = right; 8040 displayInfo.overscanBottom = bottom; 8041 } 8042 8043 mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom); 8044 mDisplaySettings.writeSettingsLocked(); 8045 8046 reconfigureDisplayLocked(displayContent); 8047 } 8048 8049 // ------------------------------------------------------------- 8050 // Internals 8051 // ------------------------------------------------------------- 8052 8053 final WindowState windowForClientLocked(Session session, IWindow client, 8054 boolean throwOnError) { 8055 return windowForClientLocked(session, client.asBinder(), throwOnError); 8056 } 8057 8058 final WindowState windowForClientLocked(Session session, IBinder client, 8059 boolean throwOnError) { 8060 WindowState win = mWindowMap.get(client); 8061 if (localLOGV) Slog.v( 8062 TAG, "Looking up client " + client + ": " + win); 8063 if (win == null) { 8064 RuntimeException ex = new IllegalArgumentException( 8065 "Requested window " + client + " does not exist"); 8066 if (throwOnError) { 8067 throw ex; 8068 } 8069 Slog.w(TAG, "Failed looking up window", ex); 8070 return null; 8071 } 8072 if (session != null && win.mSession != session) { 8073 RuntimeException ex = new IllegalArgumentException( 8074 "Requested window " + client + " is in session " + 8075 win.mSession + ", not " + session); 8076 if (throwOnError) { 8077 throw ex; 8078 } 8079 Slog.w(TAG, "Failed looking up window", ex); 8080 return null; 8081 } 8082 8083 return win; 8084 } 8085 8086 final void rebuildAppWindowListLocked() { 8087 rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); 8088 } 8089 8090 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 8091 final WindowList windows = displayContent.getWindowList(); 8092 int NW = windows.size(); 8093 int i; 8094 int lastBelow = -1; 8095 int numRemoved = 0; 8096 8097 if (mRebuildTmp.length < NW) { 8098 mRebuildTmp = new WindowState[NW+10]; 8099 } 8100 8101 // First remove all existing app windows. 8102 i=0; 8103 while (i < NW) { 8104 WindowState w = windows.get(i); 8105 if (w.mAppToken != null) { 8106 WindowState win = windows.remove(i); 8107 win.mRebuilding = true; 8108 mRebuildTmp[numRemoved] = win; 8109 mWindowsChanged = true; 8110 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win); 8111 NW--; 8112 numRemoved++; 8113 continue; 8114 } else if (lastBelow == i-1) { 8115 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8116 lastBelow = i; 8117 } 8118 } 8119 i++; 8120 } 8121 8122 // Keep whatever windows were below the app windows still below, 8123 // by skipping them. 8124 lastBelow++; 8125 i = lastBelow; 8126 8127 // First add all of the exiting app tokens... these are no longer 8128 // in the main app list, but still have windows shown. We put them 8129 // in the back because now that the animation is over we no longer 8130 // will care about them. 8131 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 8132 final int numStacks = stacks.size(); 8133 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8134 AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens; 8135 int NT = exitingAppTokens.size(); 8136 for (int j = 0; j < NT; j++) { 8137 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 8138 } 8139 } 8140 8141 // And add in the still active app tokens in Z order. 8142 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8143 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8144 final int numTasks = tasks.size(); 8145 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 8146 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8147 final int numTokens = tokens.size(); 8148 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 8149 final AppWindowToken wtoken = tokens.get(tokenNdx); 8150 if (wtoken.mDeferRemoval) { 8151 continue; 8152 } 8153 i = reAddAppWindowsLocked(displayContent, i, wtoken); 8154 } 8155 } 8156 } 8157 8158 i -= lastBelow; 8159 if (i != numRemoved) { 8160 Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " + 8161 numRemoved + " windows but added " + i, 8162 new RuntimeException("here").fillInStackTrace()); 8163 for (i=0; i<numRemoved; i++) { 8164 WindowState ws = mRebuildTmp[i]; 8165 if (ws.mRebuilding) { 8166 StringWriter sw = new StringWriter(); 8167 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 8168 ws.dump(pw, "", true); 8169 pw.flush(); 8170 Slog.w(TAG, "This window was lost: " + ws); 8171 Slog.w(TAG, sw.toString()); 8172 ws.mWinAnimator.destroySurfaceLocked(); 8173 } 8174 } 8175 Slog.w(TAG, "Current app token list:"); 8176 dumpAppTokensLocked(); 8177 Slog.w(TAG, "Final window list:"); 8178 dumpWindowsLocked(); 8179 } 8180 } 8181 8182 private final void assignLayersLocked(WindowList windows) { 8183 int N = windows.size(); 8184 int curBaseLayer = 0; 8185 int curLayer = 0; 8186 int i; 8187 8188 if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows, 8189 new RuntimeException("here").fillInStackTrace()); 8190 8191 boolean anyLayerChanged = false; 8192 8193 for (i=0; i<N; i++) { 8194 final WindowState w = windows.get(i); 8195 final WindowStateAnimator winAnimator = w.mWinAnimator; 8196 boolean layerChanged = false; 8197 int oldLayer = w.mLayer; 8198 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 8199 || (i > 0 && w.mIsWallpaper)) { 8200 curLayer += WINDOW_LAYER_MULTIPLIER; 8201 w.mLayer = curLayer; 8202 } else { 8203 curBaseLayer = curLayer = w.mBaseLayer; 8204 w.mLayer = curLayer; 8205 } 8206 if (w.mLayer != oldLayer) { 8207 layerChanged = true; 8208 anyLayerChanged = true; 8209 } 8210 final AppWindowToken wtoken = w.mAppToken; 8211 oldLayer = winAnimator.mAnimLayer; 8212 if (w.mTargetAppToken != null) { 8213 winAnimator.mAnimLayer = 8214 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 8215 } else if (wtoken != null) { 8216 winAnimator.mAnimLayer = 8217 w.mLayer + wtoken.mAppAnimator.animLayerAdjustment; 8218 } else { 8219 winAnimator.mAnimLayer = w.mLayer; 8220 } 8221 if (w.mIsImWindow) { 8222 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 8223 } else if (w.mIsWallpaper) { 8224 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 8225 } 8226 if (winAnimator.mAnimLayer != oldLayer) { 8227 layerChanged = true; 8228 anyLayerChanged = true; 8229 } 8230 if (layerChanged && w.getStack().isDimming(winAnimator)) { 8231 // Force an animation pass just to update the mDimLayer layer. 8232 scheduleAnimationLocked(); 8233 } 8234 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 8235 + "mBase=" + w.mBaseLayer 8236 + " mLayer=" + w.mLayer 8237 + (wtoken == null ? 8238 "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment) 8239 + " =mAnimLayer=" + winAnimator.mAnimLayer); 8240 //System.out.println( 8241 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 8242 } 8243 8244 //TODO (multidisplay): Magnification is supported only for the default display. 8245 if (mAccessibilityController != null && anyLayerChanged 8246 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) { 8247 mAccessibilityController.onWindowLayersChangedLocked(); 8248 } 8249 } 8250 8251 private final void performLayoutAndPlaceSurfacesLocked() { 8252 int loopCount = 6; 8253 do { 8254 mTraversalScheduled = false; 8255 performLayoutAndPlaceSurfacesLockedLoop(); 8256 mH.removeMessages(H.DO_TRAVERSAL); 8257 loopCount--; 8258 } while (mTraversalScheduled && loopCount > 0); 8259 mInnerFields.mWallpaperActionPending = false; 8260 } 8261 8262 private boolean mInLayout = false; 8263 private final void performLayoutAndPlaceSurfacesLockedLoop() { 8264 if (mInLayout) { 8265 if (DEBUG) { 8266 throw new RuntimeException("Recursive call!"); 8267 } 8268 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 8269 + Debug.getCallers(3)); 8270 return; 8271 } 8272 8273 if (mWaitingForConfig) { 8274 // Our configuration has changed (most likely rotation), but we 8275 // don't yet have the complete configuration to report to 8276 // applications. Don't do any window layout until we have it. 8277 return; 8278 } 8279 8280 if (!mDisplayReady) { 8281 // Not yet initialized, nothing to do. 8282 return; 8283 } 8284 8285 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 8286 mInLayout = true; 8287 boolean recoveringMemory = false; 8288 8289 try { 8290 if (mForceRemoves != null) { 8291 recoveringMemory = true; 8292 // Wait a little bit for things to settle down, and off we go. 8293 for (int i=0; i<mForceRemoves.size(); i++) { 8294 WindowState ws = mForceRemoves.get(i); 8295 Slog.i(TAG, "Force removing: " + ws); 8296 removeWindowInnerLocked(ws.mSession, ws); 8297 } 8298 mForceRemoves = null; 8299 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 8300 Object tmp = new Object(); 8301 synchronized (tmp) { 8302 try { 8303 tmp.wait(250); 8304 } catch (InterruptedException e) { 8305 } 8306 } 8307 } 8308 } catch (RuntimeException e) { 8309 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 8310 } 8311 8312 try { 8313 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 8314 8315 mInLayout = false; 8316 8317 if (needsLayout()) { 8318 if (++mLayoutRepeatCount < 6) { 8319 requestTraversalLocked(); 8320 } else { 8321 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 8322 mLayoutRepeatCount = 0; 8323 } 8324 } else { 8325 mLayoutRepeatCount = 0; 8326 } 8327 8328 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 8329 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 8330 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE); 8331 } 8332 } catch (RuntimeException e) { 8333 mInLayout = false; 8334 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 8335 } 8336 8337 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 8338 } 8339 8340 private final void performLayoutLockedInner(final DisplayContent displayContent, 8341 boolean initial, boolean updateInputWindows) { 8342 if (!displayContent.layoutNeeded) { 8343 return; 8344 } 8345 displayContent.layoutNeeded = false; 8346 WindowList windows = displayContent.getWindowList(); 8347 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 8348 8349 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8350 final int dw = displayInfo.logicalWidth; 8351 final int dh = displayInfo.logicalHeight; 8352 8353 final int NFW = mFakeWindows.size(); 8354 for (int i=0; i<NFW; i++) { 8355 mFakeWindows.get(i).layout(dw, dh); 8356 } 8357 8358 final int N = windows.size(); 8359 int i; 8360 8361 if (DEBUG_LAYOUT) { 8362 Slog.v(TAG, "-------------------------------------"); 8363 Slog.v(TAG, "performLayout: needed=" 8364 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 8365 } 8366 8367 WindowStateAnimator universeBackground = null; 8368 8369 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); 8370 if (isDefaultDisplay) { 8371 // Not needed on non-default displays. 8372 mSystemDecorLayer = mPolicy.getSystemDecorLayerLw(); 8373 mScreenRect.set(0, 0, dw, dh); 8374 } 8375 8376 mPolicy.getContentRectLw(mTmpContentRect); 8377 displayContent.resize(mTmpContentRect); 8378 8379 int seq = mLayoutSeq+1; 8380 if (seq < 0) seq = 0; 8381 mLayoutSeq = seq; 8382 8383 boolean behindDream = false; 8384 8385 // First perform layout of any root windows (not attached 8386 // to another window). 8387 int topAttached = -1; 8388 for (i = N-1; i >= 0; i--) { 8389 final WindowState win = windows.get(i); 8390 8391 // Don't do layout of a window if it is not visible, or 8392 // soon won't be visible, to avoid wasting time and funky 8393 // changes while a window is animating away. 8394 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) 8395 || win.isGoneForLayoutLw(); 8396 8397 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 8398 Slog.v(TAG, "1ST PASS " + win 8399 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 8400 + " mLayoutAttached=" + win.mLayoutAttached 8401 + " screen changed=" + win.isConfigChanged()); 8402 final AppWindowToken atoken = win.mAppToken; 8403 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 8404 + win.mViewVisibility + " mRelayoutCalled=" 8405 + win.mRelayoutCalled + " hidden=" 8406 + win.mRootToken.hidden + " hiddenRequested=" 8407 + (atoken != null && atoken.hiddenRequested) 8408 + " mAttachedHidden=" + win.mAttachedHidden); 8409 else Slog.v(TAG, " VIS: mViewVisibility=" 8410 + win.mViewVisibility + " mRelayoutCalled=" 8411 + win.mRelayoutCalled + " hidden=" 8412 + win.mRootToken.hidden + " hiddenRequested=" 8413 + (atoken != null && atoken.hiddenRequested) 8414 + " mAttachedHidden=" + win.mAttachedHidden); 8415 } 8416 8417 // If this view is GONE, then skip it -- keep the current 8418 // frame, and let the caller know so they can ignore it 8419 // if they want. (We do the normal layout for INVISIBLE 8420 // windows, since that means "perform layout as normal, 8421 // just don't display"). 8422 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 8423 || ((win.isConfigChanged() || win.setInsetsChanged()) && 8424 ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || 8425 win.mAppToken != null && win.mAppToken.layoutConfigChanges)) 8426 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8427 if (!win.mLayoutAttached) { 8428 if (initial) { 8429 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8430 win.mContentChanged = false; 8431 } 8432 if (win.mAttrs.type == TYPE_DREAM) { 8433 // Don't layout windows behind a dream, so that if it 8434 // does stuff like hide the status bar we won't get a 8435 // bad transition when it goes away. 8436 behindDream = true; 8437 } 8438 win.mLayoutNeeded = false; 8439 win.prelayout(); 8440 mPolicy.layoutWindowLw(win, null); 8441 win.mLayoutSeq = seq; 8442 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8443 + win.mFrame + " mContainingFrame=" 8444 + win.mContainingFrame + " mDisplayFrame=" 8445 + win.mDisplayFrame); 8446 } else { 8447 if (topAttached < 0) topAttached = i; 8448 } 8449 } 8450 if (win.mViewVisibility == View.VISIBLE 8451 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 8452 && universeBackground == null) { 8453 universeBackground = win.mWinAnimator; 8454 } 8455 } 8456 8457 if (mAnimator.mUniverseBackground != universeBackground) { 8458 mFocusMayChange = true; 8459 mAnimator.mUniverseBackground = universeBackground; 8460 } 8461 8462 boolean attachedBehindDream = false; 8463 8464 // Now perform layout of attached windows, which usually 8465 // depend on the position of the window they are attached to. 8466 // XXX does not deal with windows that are attached to windows 8467 // that are themselves attached. 8468 for (i = topAttached; i >= 0; i--) { 8469 final WindowState win = windows.get(i); 8470 8471 if (win.mLayoutAttached) { 8472 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 8473 + " mHaveFrame=" + win.mHaveFrame 8474 + " mViewVisibility=" + win.mViewVisibility 8475 + " mRelayoutCalled=" + win.mRelayoutCalled); 8476 // If this view is GONE, then skip it -- keep the current 8477 // frame, and let the caller know so they can ignore it 8478 // if they want. (We do the normal layout for INVISIBLE 8479 // windows, since that means "perform layout as normal, 8480 // just don't display"). 8481 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) { 8482 continue; 8483 } 8484 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8485 || !win.mHaveFrame || win.mLayoutNeeded) { 8486 if (initial) { 8487 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8488 win.mContentChanged = false; 8489 } 8490 win.mLayoutNeeded = false; 8491 win.prelayout(); 8492 mPolicy.layoutWindowLw(win, win.mAttachedWindow); 8493 win.mLayoutSeq = seq; 8494 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8495 + win.mFrame + " mContainingFrame=" 8496 + win.mContainingFrame + " mDisplayFrame=" 8497 + win.mDisplayFrame); 8498 } 8499 } else if (win.mAttrs.type == TYPE_DREAM) { 8500 // Don't layout windows behind a dream, so that if it 8501 // does stuff like hide the status bar we won't get a 8502 // bad transition when it goes away. 8503 attachedBehindDream = behindDream; 8504 } 8505 } 8506 8507 // Window frames may have changed. Tell the input dispatcher about it. 8508 mInputMonitor.setUpdateInputWindowsNeededLw(); 8509 if (updateInputWindows) { 8510 mInputMonitor.updateInputWindowsLw(false /*force*/); 8511 } 8512 8513 mPolicy.finishLayoutLw(); 8514 } 8515 8516 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8517 // If the screen is currently frozen or off, then keep 8518 // it frozen/off until this window draws at its new 8519 // orientation. 8520 if (!okToDisplay()) { 8521 if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w); 8522 w.mOrientationChanging = true; 8523 w.mLastFreezeDuration = 0; 8524 mInnerFields.mOrientationChangeComplete = false; 8525 if (!mWindowsFreezingScreen) { 8526 mWindowsFreezingScreen = true; 8527 // XXX should probably keep timeout from 8528 // when we first froze the display. 8529 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8530 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 8531 WINDOW_FREEZE_TIMEOUT_DURATION); 8532 } 8533 } 8534 } 8535 8536 /** 8537 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8538 * @param windows List of windows on default display. 8539 * @return bitmap indicating if another pass through layout must be made. 8540 */ 8541 public int handleAppTransitionReadyLocked(WindowList windows) { 8542 int changes = 0; 8543 int i; 8544 int NN = mOpeningApps.size(); 8545 boolean goodToGo = true; 8546 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8547 "Checking " + NN + " opening apps (frozen=" 8548 + mDisplayFrozen + " timeout=" 8549 + mAppTransition.isTimeout() + ")..."); 8550 if (!mDisplayFrozen && !mAppTransition.isTimeout()) { 8551 // If the display isn't frozen, wait to do anything until 8552 // all of the apps are ready. Otherwise just go because 8553 // we'll unfreeze the display when everyone is ready. 8554 for (i=0; i<NN && goodToGo; i++) { 8555 AppWindowToken wtoken = mOpeningApps.get(i); 8556 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8557 "Check opening app=" + wtoken + ": allDrawn=" 8558 + wtoken.allDrawn + " startingDisplayed=" 8559 + wtoken.startingDisplayed + " startingMoved=" 8560 + wtoken.startingMoved); 8561 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8562 && !wtoken.startingMoved) { 8563 goodToGo = false; 8564 } 8565 } 8566 } 8567 if (goodToGo) { 8568 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8569 int transit = mAppTransition.getAppTransition(); 8570 if (mSkipAppTransitionAnimation) { 8571 transit = AppTransition.TRANSIT_UNSET; 8572 } 8573 mAppTransition.goodToGo(); 8574 mStartingIconInTransition = false; 8575 mSkipAppTransitionAnimation = false; 8576 8577 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8578 8579 rebuildAppWindowListLocked(); 8580 8581 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8582 WindowState oldWallpaper = 8583 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8584 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8585 ? null : mWallpaperTarget; 8586 8587 mInnerFields.mWallpaperMayChange = false; 8588 8589 // The top-most window will supply the layout params, 8590 // and we will determine it below. 8591 LayoutParams animLp = null; 8592 int bestAnimLayer = -1; 8593 boolean fullscreenAnim = false; 8594 boolean voiceInteraction = false; 8595 8596 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8597 "New wallpaper target=" + mWallpaperTarget 8598 + ", oldWallpaper=" + oldWallpaper 8599 + ", lower target=" + mLowerWallpaperTarget 8600 + ", upper target=" + mUpperWallpaperTarget); 8601 8602 boolean openingAppHasWallpaper = false; 8603 boolean closingAppHasWallpaper = false; 8604 final AppWindowToken lowerWallpaperAppToken; 8605 final AppWindowToken upperWallpaperAppToken; 8606 if (mLowerWallpaperTarget == null) { 8607 lowerWallpaperAppToken = upperWallpaperAppToken = null; 8608 } else { 8609 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken; 8610 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken; 8611 } 8612 8613 // Do a first pass through the tokens for two 8614 // things: 8615 // (1) Determine if both the closing and opening 8616 // app token sets are wallpaper targets, in which 8617 // case special animations are needed 8618 // (since the wallpaper needs to stay static 8619 // behind them). 8620 // (2) Find the layout params of the top-most 8621 // application window in the tokens, which is 8622 // what will control the animation theme. 8623 final int NC = mClosingApps.size(); 8624 NN = NC + mOpeningApps.size(); 8625 for (i=0; i<NN; i++) { 8626 final AppWindowToken wtoken; 8627 if (i < NC) { 8628 wtoken = mClosingApps.get(i); 8629 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8630 closingAppHasWallpaper = true; 8631 } 8632 } else { 8633 wtoken = mOpeningApps.get(i - NC); 8634 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8635 openingAppHasWallpaper = true; 8636 } 8637 } 8638 8639 voiceInteraction |= wtoken.voiceInteraction; 8640 8641 if (wtoken.appFullscreen) { 8642 WindowState ws = wtoken.findMainWindow(); 8643 if (ws != null) { 8644 animLp = ws.mAttrs; 8645 bestAnimLayer = ws.mLayer; 8646 fullscreenAnim = true; 8647 } 8648 } else if (!fullscreenAnim) { 8649 WindowState ws = wtoken.findMainWindow(); 8650 if (ws != null) { 8651 if (ws.mLayer > bestAnimLayer) { 8652 animLp = ws.mAttrs; 8653 bestAnimLayer = ws.mLayer; 8654 } 8655 } 8656 } 8657 } 8658 8659 mAnimateWallpaperWithTarget = false; 8660 if (closingAppHasWallpaper && openingAppHasWallpaper) { 8661 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!"); 8662 switch (transit) { 8663 case AppTransition.TRANSIT_ACTIVITY_OPEN: 8664 case AppTransition.TRANSIT_TASK_OPEN: 8665 case AppTransition.TRANSIT_TASK_TO_FRONT: 8666 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN; 8667 break; 8668 case AppTransition.TRANSIT_ACTIVITY_CLOSE: 8669 case AppTransition.TRANSIT_TASK_CLOSE: 8670 case AppTransition.TRANSIT_TASK_TO_BACK: 8671 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; 8672 break; 8673 } 8674 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); 8675 } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty() 8676 && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 8677 // We are transitioning from an activity with 8678 // a wallpaper to one without. 8679 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; 8680 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8681 "New transit away from wallpaper: " + transit); 8682 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) { 8683 // We are transitioning from an activity without 8684 // a wallpaper to now showing the wallpaper 8685 transit = AppTransition.TRANSIT_WALLPAPER_OPEN; 8686 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8687 "New transit into wallpaper: " + transit); 8688 } else { 8689 mAnimateWallpaperWithTarget = true; 8690 } 8691 8692 // If all closing windows are obscured, then there is 8693 // no need to do an animation. This is the case, for 8694 // example, when this transition is being done behind 8695 // the lock screen. 8696 if (!mPolicy.allowAppAnimationsLw()) { 8697 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8698 "Animations disallowed by keyguard or dream."); 8699 animLp = null; 8700 } 8701 8702 AppWindowToken topOpeningApp = null; 8703 int topOpeningLayer = 0; 8704 8705 NN = mOpeningApps.size(); 8706 for (i=0; i<NN; i++) { 8707 AppWindowToken wtoken = mOpeningApps.get(i); 8708 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 8709 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 8710 appAnimator.clearThumbnail(); 8711 wtoken.inPendingTransaction = false; 8712 appAnimator.animation = null; 8713 setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction); 8714 wtoken.updateReportedVisibilityLocked(); 8715 wtoken.waitingToShow = false; 8716 8717 appAnimator.mAllAppWinAnimators.clear(); 8718 final int N = wtoken.allAppWindows.size(); 8719 for (int j = 0; j < N; j++) { 8720 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 8721 } 8722 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 8723 8724 if (animLp != null) { 8725 int layer = -1; 8726 for (int j=0; j<wtoken.windows.size(); j++) { 8727 WindowState win = wtoken.windows.get(j); 8728 if (win.mWinAnimator.mAnimLayer > layer) { 8729 layer = win.mWinAnimator.mAnimLayer; 8730 } 8731 } 8732 if (topOpeningApp == null || layer > topOpeningLayer) { 8733 topOpeningApp = wtoken; 8734 topOpeningLayer = layer; 8735 } 8736 } 8737 } 8738 NN = mClosingApps.size(); 8739 for (i=0; i<NN; i++) { 8740 AppWindowToken wtoken = mClosingApps.get(i); 8741 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken); 8742 wtoken.mAppAnimator.clearThumbnail(); 8743 wtoken.inPendingTransaction = false; 8744 wtoken.mAppAnimator.animation = null; 8745 setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction); 8746 wtoken.updateReportedVisibilityLocked(); 8747 wtoken.waitingToHide = false; 8748 // Force the allDrawn flag, because we want to start 8749 // this guy's animations regardless of whether it's 8750 // gotten drawn. 8751 wtoken.allDrawn = true; 8752 wtoken.deferClearAllDrawn = false; 8753 } 8754 8755 boolean useAlternateThumbnailAnimation = true; 8756 AppWindowAnimator appAnimator = 8757 topOpeningApp == null ? null : topOpeningApp.mAppAnimator; 8758 Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail(); 8759 if (!useAlternateThumbnailAnimation && nextAppTransitionThumbnail != null 8760 && appAnimator != null && appAnimator.animation != null) { 8761 // This thumbnail animation is very special, we need to have 8762 // an extra surface with the thumbnail included with the animation. 8763 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(), 8764 nextAppTransitionThumbnail.getHeight()); 8765 try { 8766 // TODO(multi-display): support other displays 8767 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8768 final Display display = displayContent.getDisplay(); 8769 SurfaceControl surfaceControl = new SurfaceControl(mFxSession, 8770 "thumbnail anim", 8771 dirty.width(), dirty.height(), 8772 PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 8773 surfaceControl.setLayerStack(display.getLayerStack()); 8774 appAnimator.thumbnail = surfaceControl; 8775 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE"); 8776 Surface drawSurface = new Surface(); 8777 drawSurface.copyFrom(surfaceControl); 8778 Canvas c = drawSurface.lockCanvas(dirty); 8779 c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null); 8780 drawSurface.unlockCanvasAndPost(c); 8781 drawSurface.release(); 8782 appAnimator.thumbnailLayer = topOpeningLayer; 8783 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 8784 Animation anim = mAppTransition.createThumbnailScaleAnimationLocked( 8785 displayInfo.appWidth, displayInfo.appHeight, transit); 8786 appAnimator.thumbnailAnimation = anim; 8787 anim.restrictDuration(MAX_ANIMATION_DURATION); 8788 anim.scaleCurrentDuration(getTransitionAnimationScaleLocked()); 8789 Point p = new Point(); 8790 mAppTransition.getStartingPoint(p); 8791 appAnimator.thumbnailX = p.x; 8792 appAnimator.thumbnailY = p.y; 8793 } catch (OutOfResourcesException e) { 8794 Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width() 8795 + " h=" + dirty.height(), e); 8796 appAnimator.clearThumbnail(); 8797 } 8798 } 8799 8800 mAppTransition.postAnimationCallback(); 8801 mAppTransition.clear(); 8802 8803 mOpeningApps.clear(); 8804 mClosingApps.clear(); 8805 8806 // This has changed the visibility of windows, so perform 8807 // a new layout to get them all up-to-date. 8808 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT 8809 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 8810 getDefaultDisplayContentLocked().layoutNeeded = true; 8811 8812 // TODO(multidisplay): IMEs are only supported on the default display. 8813 if (windows == getDefaultWindowListLocked() 8814 && !moveInputMethodWindowsIfNeededLocked(true)) { 8815 assignLayersLocked(windows); 8816 } 8817 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/); 8818 mFocusMayChange = false; 8819 } 8820 8821 return changes; 8822 } 8823 8824 /** 8825 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8826 * @return bitmap indicating if another pass through layout must be made. 8827 */ 8828 private int handleAnimatingStoppedAndTransitionLocked() { 8829 int changes = 0; 8830 8831 mAppTransition.setIdle(); 8832 // Restore window app tokens to the ActivityManager views 8833 ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks(); 8834 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 8835 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8836 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 8837 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8838 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 8839 tokens.get(tokenNdx).sendingToBottom = false; 8840 } 8841 } 8842 } 8843 rebuildAppWindowListLocked(); 8844 8845 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8846 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 8847 "Wallpaper layer changed: assigning layers + relayout"); 8848 moveInputMethodWindowsIfNeededLocked(true); 8849 mInnerFields.mWallpaperMayChange = true; 8850 // Since the window list has been rebuilt, focus might 8851 // have to be recomputed since the actual order of windows 8852 // might have changed again. 8853 mFocusMayChange = true; 8854 8855 return changes; 8856 } 8857 8858 private void updateResizingWindows(final WindowState w) { 8859 final WindowStateAnimator winAnimator = w.mWinAnimator; 8860 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { 8861 w.setInsetsChanged(); 8862 boolean configChanged = w.isConfigChanged(); 8863 if (DEBUG_CONFIGURATION && configChanged) { 8864 Slog.v(TAG, "Win " + w + " config changed: " 8865 + mCurConfiguration); 8866 } 8867 if (localLOGV) Slog.v(TAG, "Resizing " + w 8868 + ": configChanged=" + configChanged 8869 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8870 w.mLastFrame.set(w.mFrame); 8871 if (w.mContentInsetsChanged 8872 || w.mVisibleInsetsChanged 8873 || winAnimator.mSurfaceResized 8874 || configChanged) { 8875 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8876 Slog.v(TAG, "Resize reasons for w=" + w + ": " 8877 + " contentInsetsChanged=" + w.mContentInsetsChanged 8878 + " " + w.mContentInsets.toShortString() 8879 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8880 + " " + w.mVisibleInsets.toShortString() 8881 + " surfaceResized=" + winAnimator.mSurfaceResized 8882 + " configChanged=" + configChanged); 8883 } 8884 8885 w.mLastOverscanInsets.set(w.mOverscanInsets); 8886 w.mLastContentInsets.set(w.mContentInsets); 8887 w.mLastVisibleInsets.set(w.mVisibleInsets); 8888 makeWindowFreezingScreenIfNeededLocked(w); 8889 // If the orientation is changing, then we need to 8890 // hold off on unfreezing the display until this 8891 // window has been redrawn; to do that, we need 8892 // to go through the process of getting informed 8893 // by the application when it has finished drawing. 8894 if (w.mOrientationChanging) { 8895 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 8896 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 8897 + w + ", surface " + winAnimator.mSurfaceControl); 8898 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 8899 if (w.mAppToken != null) { 8900 w.mAppToken.allDrawn = false; 8901 w.mAppToken.deferClearAllDrawn = false; 8902 } 8903 } 8904 if (!mResizingWindows.contains(w)) { 8905 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8906 "Resizing window " + w + " to " + winAnimator.mSurfaceW 8907 + "x" + winAnimator.mSurfaceH); 8908 mResizingWindows.add(w); 8909 } 8910 } else if (w.mOrientationChanging) { 8911 if (w.isDrawnLw()) { 8912 if (DEBUG_ORIENTATION) Slog.v(TAG, 8913 "Orientation not waiting for draw in " 8914 + w + ", surface " + winAnimator.mSurfaceControl); 8915 w.mOrientationChanging = false; 8916 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 8917 - mDisplayFreezeTime); 8918 } 8919 } 8920 } 8921 } 8922 8923 /** 8924 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8925 * 8926 * @param w WindowState this method is applied to. 8927 * @param currentTime The time which animations use for calculating transitions. 8928 * @param innerDw Width of app window. 8929 * @param innerDh Height of app window. 8930 */ 8931 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 8932 final int innerDw, final int innerDh) { 8933 final WindowManager.LayoutParams attrs = w.mAttrs; 8934 final int attrFlags = attrs.flags; 8935 final boolean canBeSeen = w.isDisplayedLw(); 8936 final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8937 8938 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8939 // This window completely covers everything behind it, 8940 // so we want to leave all of them as undimmed (for 8941 // performance reasons). 8942 mInnerFields.mObscured = true; 8943 } 8944 8945 if (w.mHasSurface) { 8946 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8947 mInnerFields.mHoldScreen = w.mSession; 8948 } 8949 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 8950 && mInnerFields.mScreenBrightness < 0) { 8951 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 8952 } 8953 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 8954 && mInnerFields.mButtonBrightness < 0) { 8955 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 8956 } 8957 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0 8958 && mInnerFields.mUserActivityTimeout < 0) { 8959 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout; 8960 } 8961 8962 final int type = attrs.type; 8963 if (canBeSeen 8964 && (type == TYPE_SYSTEM_DIALOG 8965 || type == TYPE_RECENTS_OVERLAY 8966 || type == TYPE_SYSTEM_ERROR 8967 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) { 8968 mInnerFields.mSyswin = true; 8969 } 8970 8971 if (canBeSeen) { 8972 // This function assumes that the contents of the default display are 8973 // processed first before secondary displays. 8974 final DisplayContent displayContent = w.getDisplayContent(); 8975 if (displayContent != null && displayContent.isDefaultDisplay) { 8976 // While a dream or keyguard is showing, obscure ordinary application 8977 // content on secondary displays (by forcibly enabling mirroring unless 8978 // there is other content we want to show) but still allow opaque 8979 // keyguard dialogs to be shown. 8980 if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 8981 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true; 8982 } 8983 mInnerFields.mDisplayHasContent = true; 8984 } else if (displayContent != null && 8985 (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays 8986 || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) { 8987 // Allow full screen keyguard presentation dialogs to be seen. 8988 mInnerFields.mDisplayHasContent = true; 8989 } 8990 } 8991 } 8992 } 8993 8994 private void handleFlagDimBehind(WindowState w) { 8995 final WindowManager.LayoutParams attrs = w.mAttrs; 8996 if ((attrs.flags & FLAG_DIM_BEHIND) != 0 8997 && w.isDisplayedLw() 8998 && !w.mExiting) { 8999 final WindowStateAnimator winAnimator = w.mWinAnimator; 9000 final TaskStack stack = w.getStack(); 9001 stack.setDimmingTag(); 9002 if (!stack.isDimming(winAnimator)) { 9003 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming."); 9004 stack.startDimmingIfNeeded(winAnimator); 9005 } 9006 } 9007 } 9008 9009 private void updateAllDrawnLocked(DisplayContent displayContent) { 9010 // See if any windows have been drawn, so they (and others 9011 // associated with them) can now be shown. 9012 ArrayList<TaskStack> stacks = displayContent.getStacks(); 9013 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 9014 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9015 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9016 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9017 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9018 final AppWindowToken wtoken = tokens.get(tokenNdx); 9019 if (!wtoken.allDrawn) { 9020 int numInteresting = wtoken.numInterestingWindows; 9021 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 9022 if (DEBUG_VISIBILITY) Slog.v(TAG, 9023 "allDrawn: " + wtoken 9024 + " interesting=" + numInteresting 9025 + " drawn=" + wtoken.numDrawnWindows); 9026 wtoken.allDrawn = true; 9027 mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget(); 9028 } 9029 } 9030 } 9031 } 9032 } 9033 } 9034 9035 // "Something has changed! Let's make it correct now." 9036 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 9037 if (DEBUG_WINDOW_TRACE) { 9038 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 9039 + Debug.getCallers(3)); 9040 } 9041 9042 final long currentTime = SystemClock.uptimeMillis(); 9043 9044 int i; 9045 9046 if (mFocusMayChange) { 9047 mFocusMayChange = false; 9048 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 9049 false /*updateInputWindows*/); 9050 } 9051 9052 // Initialize state of exiting tokens. 9053 final int numDisplays = mDisplayContents.size(); 9054 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9055 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9056 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) { 9057 displayContent.mExitingTokens.get(i).hasVisible = false; 9058 } 9059 } 9060 9061 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9062 // Initialize state of exiting applications. 9063 final AppTokenList exitingAppTokens = 9064 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9065 for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9066 exitingAppTokens.get(tokenNdx).hasVisible = false; 9067 } 9068 } 9069 9070 mInnerFields.mHoldScreen = null; 9071 mInnerFields.mScreenBrightness = -1; 9072 mInnerFields.mButtonBrightness = -1; 9073 mInnerFields.mUserActivityTimeout = -1; 9074 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false; 9075 9076 mTransactionSequence++; 9077 9078 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked(); 9079 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 9080 final int defaultDw = defaultInfo.logicalWidth; 9081 final int defaultDh = defaultInfo.logicalHeight; 9082 9083 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9084 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 9085 SurfaceControl.openTransaction(); 9086 try { 9087 9088 if (mWatermark != null) { 9089 mWatermark.positionSurface(defaultDw, defaultDh); 9090 } 9091 if (mStrictModeFlash != null) { 9092 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 9093 } 9094 9095 boolean focusDisplayed = false; 9096 9097 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9098 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9099 boolean updateAllDrawn = false; 9100 WindowList windows = displayContent.getWindowList(); 9101 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9102 final int displayId = displayContent.getDisplayId(); 9103 final int dw = displayInfo.logicalWidth; 9104 final int dh = displayInfo.logicalHeight; 9105 final int innerDw = displayInfo.appWidth; 9106 final int innerDh = displayInfo.appHeight; 9107 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 9108 9109 // Reset for each display. 9110 mInnerFields.mDisplayHasContent = false; 9111 9112 int repeats = 0; 9113 do { 9114 repeats++; 9115 if (repeats > 6) { 9116 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 9117 displayContent.layoutNeeded = false; 9118 break; 9119 } 9120 9121 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 9122 displayContent.pendingLayoutChanges); 9123 9124 if ((displayContent.pendingLayoutChanges & 9125 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 && 9126 (adjustWallpaperWindowsLocked() & 9127 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 9128 assignLayersLocked(windows); 9129 displayContent.layoutNeeded = true; 9130 } 9131 9132 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 9133 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 9134 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 9135 if (updateOrientationFromAppTokensLocked(true)) { 9136 displayContent.layoutNeeded = true; 9137 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9138 } 9139 } 9140 9141 if ((displayContent.pendingLayoutChanges 9142 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9143 displayContent.layoutNeeded = true; 9144 } 9145 9146 // FIRST LOOP: Perform a layout, if needed. 9147 if (repeats < 4) { 9148 performLayoutLockedInner(displayContent, repeats == 1, 9149 false /*updateInputWindows*/); 9150 } else { 9151 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 9152 } 9153 9154 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 9155 // it is animating. 9156 displayContent.pendingLayoutChanges = 0; 9157 9158 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 9159 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 9160 9161 if (isDefaultDisplay) { 9162 mPolicy.beginPostLayoutPolicyLw(dw, dh); 9163 for (i = windows.size() - 1; i >= 0; i--) { 9164 WindowState w = windows.get(i); 9165 if (w.mHasSurface) { 9166 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); 9167 } 9168 } 9169 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 9170 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 9171 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges); 9172 } 9173 } while (displayContent.pendingLayoutChanges != 0); 9174 9175 mInnerFields.mObscured = false; 9176 mInnerFields.mSyswin = false; 9177 displayContent.resetDimming(); 9178 9179 // Only used if default window 9180 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 9181 9182 final int N = windows.size(); 9183 for (i=N-1; i>=0; i--) { 9184 WindowState w = windows.get(i); 9185 final TaskStack stack = w.getStack(); 9186 if (stack == null) { 9187 continue; 9188 } 9189 9190 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 9191 9192 // Update effect. 9193 w.mObscured = mInnerFields.mObscured; 9194 if (!mInnerFields.mObscured) { 9195 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 9196 } 9197 9198 if (!stack.testDimmingTag()) { 9199 handleFlagDimBehind(w); 9200 } 9201 9202 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 9203 && w.isVisibleLw()) { 9204 // This is the wallpaper target and its obscured state 9205 // changed... make sure the current wallaper's visibility 9206 // has been updated accordingly. 9207 updateWallpaperVisibilityLocked(); 9208 } 9209 9210 final WindowStateAnimator winAnimator = w.mWinAnimator; 9211 9212 // If the window has moved due to its containing 9213 // content frame changing, then we'd like to animate 9214 // it. 9215 if (w.mHasSurface && w.shouldAnimateMove()) { 9216 // Frame has moved, containing content frame 9217 // has also moved, and we're not currently animating... 9218 // let's do something. 9219 Animation a = AnimationUtils.loadAnimation(mContext, 9220 com.android.internal.R.anim.window_move_from_decor); 9221 winAnimator.setAnimation(a); 9222 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 9223 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 9224 9225 //TODO (multidisplay): Accessibility supported only for the default display. 9226 if (mAccessibilityController != null 9227 && displayId == Display.DEFAULT_DISPLAY) { 9228 mAccessibilityController.onSomeWindowResizedOrMovedLocked(); 9229 } 9230 9231 try { 9232 w.mClient.moved(w.mFrame.left, w.mFrame.top); 9233 } catch (RemoteException e) { 9234 } 9235 } 9236 9237 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 9238 w.mContentChanged = false; 9239 9240 // Moved from updateWindowsAndWallpaperLocked(). 9241 if (w.mHasSurface) { 9242 // Take care of the window being ready to display. 9243 final boolean committed = 9244 winAnimator.commitFinishDrawingLocked(currentTime); 9245 if (isDefaultDisplay && committed) { 9246 if (w.mAttrs.type == TYPE_DREAM) { 9247 // HACK: When a dream is shown, it may at that 9248 // point hide the lock screen. So we need to 9249 // redo the layout to let the phone window manager 9250 // make this happen. 9251 displayContent.pendingLayoutChanges |= 9252 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9253 if (DEBUG_LAYOUT_REPEATS) { 9254 debugLayoutRepeats( 9255 "dream and commitFinishDrawingLocked true", 9256 displayContent.pendingLayoutChanges); 9257 } 9258 } 9259 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 9260 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 9261 "First draw done in potential wallpaper target " + w); 9262 mInnerFields.mWallpaperMayChange = true; 9263 displayContent.pendingLayoutChanges |= 9264 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9265 if (DEBUG_LAYOUT_REPEATS) { 9266 debugLayoutRepeats( 9267 "wallpaper and commitFinishDrawingLocked true", 9268 displayContent.pendingLayoutChanges); 9269 } 9270 } 9271 } 9272 9273 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 9274 9275 final AppWindowToken atoken = w.mAppToken; 9276 if (DEBUG_STARTING_WINDOW && atoken != null 9277 && w == atoken.startingWindow) { 9278 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 9279 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 9280 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 9281 } 9282 if (atoken != null 9283 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 9284 if (atoken.lastTransactionSequence != mTransactionSequence) { 9285 atoken.lastTransactionSequence = mTransactionSequence; 9286 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 9287 atoken.startingDisplayed = false; 9288 } 9289 if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 9290 && !w.mExiting && !w.mDestroying) { 9291 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 9292 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 9293 + ", isAnimating=" + winAnimator.isAnimating()); 9294 if (!w.isDrawnLw()) { 9295 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl 9296 + " pv=" + w.mPolicyVisibility 9297 + " mDrawState=" + winAnimator.mDrawState 9298 + " ah=" + w.mAttachedHidden 9299 + " th=" + atoken.hiddenRequested 9300 + " a=" + winAnimator.mAnimating); 9301 } 9302 } 9303 if (w != atoken.startingWindow) { 9304 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 9305 atoken.numInterestingWindows++; 9306 if (w.isDrawnLw()) { 9307 atoken.numDrawnWindows++; 9308 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 9309 "tokenMayBeDrawn: " + atoken 9310 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 9311 + " mAppFreezing=" + w.mAppFreezing); 9312 updateAllDrawn = true; 9313 } 9314 } 9315 } else if (w.isDrawnLw()) { 9316 atoken.startingDisplayed = true; 9317 } 9318 } 9319 } 9320 } 9321 9322 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 9323 && w.isDisplayedLw()) { 9324 focusDisplayed = true; 9325 } 9326 9327 updateResizingWindows(w); 9328 } 9329 9330 mDisplayManagerInternal.setDisplayHasContent(displayId, 9331 mInnerFields.mDisplayHasContent, 9332 true /* inTraversal, must call performTraversalInTrans... below */); 9333 9334 getDisplayContentLocked(displayId).stopDimmingIfNeeded(); 9335 9336 if (updateAllDrawn) { 9337 updateAllDrawnLocked(displayContent); 9338 } 9339 } 9340 9341 if (focusDisplayed) { 9342 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 9343 } 9344 9345 // Give the display manager a chance to adjust properties 9346 // like display rotation if it needs to. 9347 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 9348 9349 } catch (RuntimeException e) { 9350 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 9351 } finally { 9352 SurfaceControl.closeTransaction(); 9353 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9354 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 9355 } 9356 9357 final WindowList defaultWindows = defaultDisplay.getWindowList(); 9358 9359 // If we are ready to perform an app transition, check through 9360 // all of the app tokens to be shown and see if they are ready 9361 // to go. 9362 if (mAppTransition.isReady()) { 9363 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 9364 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 9365 defaultDisplay.pendingLayoutChanges); 9366 } 9367 9368 if (!mAnimator.mAnimating && mAppTransition.isRunning()) { 9369 // We have finished the animation of an app transition. To do 9370 // this, we have delayed a lot of operations like showing and 9371 // hiding apps, moving apps in Z-order, etc. The app token list 9372 // reflects the correct Z-order, but the window list may now 9373 // be out of sync with it. So here we will just rebuild the 9374 // entire app window list. Fun! 9375 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 9376 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 9377 defaultDisplay.pendingLayoutChanges); 9378 } 9379 9380 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 9381 && !mAppTransition.isReady()) { 9382 // At this point, there was a window with a wallpaper that 9383 // was force hiding other windows behind it, but now it 9384 // is going away. This may be simple -- just animate 9385 // away the wallpaper and its window -- or it may be 9386 // hard -- the wallpaper now needs to be shown behind 9387 // something that was hidden. 9388 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9389 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 9390 defaultDisplay.pendingLayoutChanges); 9391 } 9392 mInnerFields.mWallpaperForceHidingChanged = false; 9393 9394 if (mInnerFields.mWallpaperMayChange) { 9395 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting"); 9396 defaultDisplay.pendingLayoutChanges |= 9397 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9398 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange", 9399 defaultDisplay.pendingLayoutChanges); 9400 } 9401 9402 if (mFocusMayChange) { 9403 mFocusMayChange = false; 9404 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 9405 false /*updateInputWindows*/)) { 9406 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 9407 } 9408 } 9409 9410 if (needsLayout()) { 9411 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9412 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 9413 defaultDisplay.pendingLayoutChanges); 9414 } 9415 9416 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 9417 WindowState win = mResizingWindows.get(i); 9418 if (win.mAppFreezing) { 9419 // Don't remove this window until rotation has completed. 9420 continue; 9421 } 9422 win.reportResized(); 9423 mResizingWindows.remove(i); 9424 } 9425 9426 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 9427 "With display frozen, orientationChangeComplete=" 9428 + mInnerFields.mOrientationChangeComplete); 9429 if (mInnerFields.mOrientationChangeComplete) { 9430 if (mWindowsFreezingScreen) { 9431 mWindowsFreezingScreen = false; 9432 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource; 9433 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9434 } 9435 stopFreezingDisplayLocked(); 9436 } 9437 9438 // Destroy the surface of any windows that are no longer visible. 9439 boolean wallpaperDestroyed = false; 9440 i = mDestroySurface.size(); 9441 if (i > 0) { 9442 do { 9443 i--; 9444 WindowState win = mDestroySurface.get(i); 9445 win.mDestroying = false; 9446 if (mInputMethodWindow == win) { 9447 mInputMethodWindow = null; 9448 } 9449 if (win == mWallpaperTarget) { 9450 wallpaperDestroyed = true; 9451 } 9452 win.mWinAnimator.destroySurfaceLocked(); 9453 } while (i > 0); 9454 mDestroySurface.clear(); 9455 } 9456 9457 // Time to remove any exiting tokens? 9458 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9459 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9460 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens; 9461 for (i = exitingTokens.size() - 1; i >= 0; i--) { 9462 WindowToken token = exitingTokens.get(i); 9463 if (!token.hasVisible) { 9464 exitingTokens.remove(i); 9465 if (token.windowType == TYPE_WALLPAPER) { 9466 mWallpaperTokens.remove(token); 9467 } 9468 } 9469 } 9470 } 9471 9472 // Time to remove any exiting applications? 9473 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9474 // Initialize state of exiting applications. 9475 final AppTokenList exitingAppTokens = 9476 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9477 for (i = exitingAppTokens.size() - 1; i >= 0; i--) { 9478 AppWindowToken token = exitingAppTokens.get(i); 9479 if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) { 9480 // Make sure there is no animation running on this token, 9481 // so any windows associated with it will be removed as 9482 // soon as their animations are complete 9483 token.mAppAnimator.clearAnimation(); 9484 token.mAppAnimator.animating = false; 9485 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 9486 "performLayout: App token exiting now removed" + token); 9487 removeAppFromTaskLocked(token); 9488 exitingAppTokens.remove(i); 9489 } 9490 } 9491 } 9492 9493 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 9494 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 9495 try { 9496 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 9497 } catch (RemoteException e) { 9498 } 9499 } 9500 mRelayoutWhileAnimating.clear(); 9501 } 9502 9503 if (wallpaperDestroyed) { 9504 defaultDisplay.pendingLayoutChanges |= 9505 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9506 defaultDisplay.layoutNeeded = true; 9507 } 9508 9509 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9510 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9511 if (displayContent.pendingLayoutChanges != 0) { 9512 displayContent.layoutNeeded = true; 9513 } 9514 } 9515 9516 // Finally update all input windows now that the window changes have stabilized. 9517 mInputMonitor.updateInputWindowsLw(true /*force*/); 9518 9519 setHoldScreenLocked(mInnerFields.mHoldScreen); 9520 if (!mDisplayFrozen) { 9521 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 9522 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1); 9523 } else { 9524 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager( 9525 toBrightnessOverride(mInnerFields.mScreenBrightness)); 9526 } 9527 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 9528 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1); 9529 } else { 9530 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager( 9531 toBrightnessOverride(mInnerFields.mButtonBrightness)); 9532 } 9533 mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager( 9534 mInnerFields.mUserActivityTimeout); 9535 } 9536 9537 if (mTurnOnScreen) { 9538 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 9539 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 9540 mTurnOnScreen = false; 9541 } 9542 9543 if (mInnerFields.mUpdateRotation) { 9544 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9545 if (updateRotationUncheckedLocked(false)) { 9546 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9547 } else { 9548 mInnerFields.mUpdateRotation = false; 9549 } 9550 } 9551 9552 if (mWaitingForDrawnCallback != null || 9553 (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded && 9554 !mInnerFields.mUpdateRotation)) { 9555 checkDrawnWindowsLocked(); 9556 } 9557 9558 final int N = mPendingRemove.size(); 9559 if (N > 0) { 9560 if (mPendingRemoveTmp.length < N) { 9561 mPendingRemoveTmp = new WindowState[N+10]; 9562 } 9563 mPendingRemove.toArray(mPendingRemoveTmp); 9564 mPendingRemove.clear(); 9565 DisplayContentList displayList = new DisplayContentList(); 9566 for (i = 0; i < N; i++) { 9567 WindowState w = mPendingRemoveTmp[i]; 9568 removeWindowInnerLocked(w.mSession, w); 9569 final DisplayContent displayContent = w.getDisplayContent(); 9570 if (displayContent != null && !displayList.contains(displayContent)) { 9571 displayList.add(displayContent); 9572 } 9573 } 9574 9575 for (DisplayContent displayContent : displayList) { 9576 assignLayersLocked(displayContent.getWindowList()); 9577 displayContent.layoutNeeded = true; 9578 } 9579 } 9580 9581 // Remove all deferred displays stacks, tasks, and activities. 9582 for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) { 9583 mDisplayContents.valueAt(displayNdx).checkForDeferredActions(); 9584 } 9585 9586 setFocusedStackFrame(); 9587 9588 // Check to see if we are now in a state where the screen should 9589 // be enabled, because the window obscured flags have changed. 9590 enableScreenIfNeededLocked(); 9591 9592 scheduleAnimationLocked(); 9593 9594 if (DEBUG_WINDOW_TRACE) { 9595 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" 9596 + mAnimator.mAnimating); 9597 } 9598 } 9599 9600 private int toBrightnessOverride(float value) { 9601 return (int)(value * PowerManager.BRIGHTNESS_ON); 9602 } 9603 9604 void checkDrawnWindowsLocked() { 9605 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { 9606 return; 9607 } 9608 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { 9609 WindowState win = mWaitingForDrawn.get(j); 9610 if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win + 9611 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() + 9612 " mHasSurface=" + win.mHasSurface + 9613 " drawState=" + win.mWinAnimator.mDrawState); 9614 if (win.mRemoved || !win.mHasSurface) { 9615 // Window has been removed; no draw will now happen, so stop waiting. 9616 if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win); 9617 mWaitingForDrawn.remove(win); 9618 } else if (win.hasDrawnLw()) { 9619 // Window is now drawn (and shown). 9620 if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win); 9621 mWaitingForDrawn.remove(win); 9622 } 9623 } 9624 if (mWaitingForDrawn.isEmpty()) { 9625 if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!"); 9626 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 9627 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); 9628 } 9629 } 9630 9631 void setHoldScreenLocked(final Session newHoldScreen) { 9632 final boolean hold = newHoldScreen != null; 9633 9634 if (hold && mHoldingScreenOn != newHoldScreen) { 9635 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 9636 } 9637 mHoldingScreenOn = newHoldScreen; 9638 9639 final boolean state = mHoldingScreenWakeLock.isHeld(); 9640 if (hold != state) { 9641 if (hold) { 9642 mHoldingScreenWakeLock.acquire(); 9643 mPolicy.keepScreenOnStartedLw(); 9644 } else { 9645 mPolicy.keepScreenOnStoppedLw(); 9646 mHoldingScreenWakeLock.release(); 9647 } 9648 } 9649 } 9650 9651 void requestTraversal() { 9652 synchronized (mWindowMap) { 9653 requestTraversalLocked(); 9654 } 9655 } 9656 9657 void requestTraversalLocked() { 9658 if (!mTraversalScheduled) { 9659 mTraversalScheduled = true; 9660 mH.sendEmptyMessage(H.DO_TRAVERSAL); 9661 } 9662 } 9663 9664 /** Note that Locked in this case is on mLayoutToAnim */ 9665 void scheduleAnimationLocked() { 9666 if (!mAnimationScheduled) { 9667 mAnimationScheduled = true; 9668 mChoreographer.postCallback( 9669 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 9670 } 9671 } 9672 9673 private boolean needsLayout() { 9674 final int numDisplays = mDisplayContents.size(); 9675 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9676 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9677 if (displayContent.layoutNeeded) { 9678 return true; 9679 } 9680 } 9681 return false; 9682 } 9683 9684 boolean copyAnimToLayoutParamsLocked() { 9685 boolean doRequest = false; 9686 9687 final int bulkUpdateParams = mAnimator.mBulkUpdateParams; 9688 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 9689 mInnerFields.mUpdateRotation = true; 9690 doRequest = true; 9691 } 9692 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 9693 mInnerFields.mWallpaperMayChange = true; 9694 doRequest = true; 9695 } 9696 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 9697 mInnerFields.mWallpaperForceHidingChanged = true; 9698 doRequest = true; 9699 } 9700 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 9701 mInnerFields.mOrientationChangeComplete = false; 9702 } else { 9703 mInnerFields.mOrientationChangeComplete = true; 9704 mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource; 9705 if (mWindowsFreezingScreen) { 9706 doRequest = true; 9707 } 9708 } 9709 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 9710 mTurnOnScreen = true; 9711 } 9712 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) { 9713 mInnerFields.mWallpaperActionPending = true; 9714 } 9715 9716 return doRequest; 9717 } 9718 9719 /** If a window that has an animation specifying a colored background and the current wallpaper 9720 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 9721 * suddenly disappear. */ 9722 int adjustAnimationBackground(WindowStateAnimator winAnimator) { 9723 WindowList windows = winAnimator.mWin.getWindowList(); 9724 for (int i = windows.size() - 1; i >= 0; --i) { 9725 WindowState testWin = windows.get(i); 9726 if (testWin.mIsWallpaper && testWin.isVisibleNow()) { 9727 return testWin.mWinAnimator.mAnimLayer; 9728 } 9729 } 9730 return winAnimator.mAnimLayer; 9731 } 9732 9733 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9734 boolean secure) { 9735 final SurfaceControl surface = winAnimator.mSurfaceControl; 9736 boolean leakedSurface = false; 9737 boolean killedApps = false; 9738 9739 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9740 winAnimator.mSession.mPid, operation); 9741 9742 if (mForceRemoves == null) { 9743 mForceRemoves = new ArrayList<WindowState>(); 9744 } 9745 9746 long callingIdentity = Binder.clearCallingIdentity(); 9747 try { 9748 // There was some problem... first, do a sanity check of the 9749 // window list to make sure we haven't left any dangling surfaces 9750 // around. 9751 9752 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 9753 final int numDisplays = mDisplayContents.size(); 9754 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9755 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9756 final int numWindows = windows.size(); 9757 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9758 final WindowState ws = windows.get(winNdx); 9759 WindowStateAnimator wsa = ws.mWinAnimator; 9760 if (wsa.mSurfaceControl != null) { 9761 if (!mSessions.contains(wsa.mSession)) { 9762 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 9763 + ws + " surface=" + wsa.mSurfaceControl 9764 + " token=" + ws.mToken 9765 + " pid=" + ws.mSession.mPid 9766 + " uid=" + ws.mSession.mUid); 9767 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9768 wsa.mSurfaceControl.destroy(); 9769 wsa.mSurfaceShown = false; 9770 wsa.mSurfaceControl = null; 9771 ws.mHasSurface = false; 9772 mForceRemoves.add(ws); 9773 leakedSurface = true; 9774 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9775 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 9776 + ws + " surface=" + wsa.mSurfaceControl 9777 + " token=" + ws.mAppToken); 9778 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9779 wsa.mSurfaceControl.destroy(); 9780 wsa.mSurfaceShown = false; 9781 wsa.mSurfaceControl = null; 9782 ws.mHasSurface = false; 9783 leakedSurface = true; 9784 } 9785 } 9786 } 9787 } 9788 9789 if (!leakedSurface) { 9790 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 9791 SparseIntArray pidCandidates = new SparseIntArray(); 9792 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9793 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9794 final int numWindows = windows.size(); 9795 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9796 final WindowState ws = windows.get(winNdx); 9797 if (mForceRemoves.contains(ws)) { 9798 continue; 9799 } 9800 WindowStateAnimator wsa = ws.mWinAnimator; 9801 if (wsa.mSurfaceControl != null) { 9802 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9803 } 9804 } 9805 if (pidCandidates.size() > 0) { 9806 int[] pids = new int[pidCandidates.size()]; 9807 for (int i=0; i<pids.length; i++) { 9808 pids[i] = pidCandidates.keyAt(i); 9809 } 9810 try { 9811 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9812 killedApps = true; 9813 } 9814 } catch (RemoteException e) { 9815 } 9816 } 9817 } 9818 } 9819 9820 if (leakedSurface || killedApps) { 9821 // We managed to reclaim some memory, so get rid of the trouble 9822 // surface and ask the app to request another one. 9823 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 9824 if (surface != null) { 9825 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9826 "RECOVER DESTROY", null); 9827 surface.destroy(); 9828 winAnimator.mSurfaceShown = false; 9829 winAnimator.mSurfaceControl = null; 9830 winAnimator.mWin.mHasSurface = false; 9831 scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken); 9832 } 9833 9834 try { 9835 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9836 } catch (RemoteException e) { 9837 } 9838 } 9839 } finally { 9840 Binder.restoreCallingIdentity(callingIdentity); 9841 } 9842 9843 return leakedSurface || killedApps; 9844 } 9845 9846 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9847 WindowState newFocus = computeFocusedWindowLocked(); 9848 if (mCurrentFocus != newFocus) { 9849 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9850 // This check makes sure that we don't already have the focus 9851 // change message pending. 9852 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9853 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9854 // TODO(multidisplay): Focused windows on default display only. 9855 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9856 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked( 9857 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 9858 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES); 9859 if (imWindowChanged) { 9860 displayContent.layoutNeeded = true; 9861 newFocus = computeFocusedWindowLocked(); 9862 } 9863 9864 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " + 9865 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 9866 final WindowState oldFocus = mCurrentFocus; 9867 mCurrentFocus = newFocus; 9868 mLosingFocus.remove(newFocus); 9869 9870 // TODO(multidisplay): Accessibilty supported only of default desiplay. 9871 if (mAccessibilityController != null 9872 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 9873 mAccessibilityController.onWindowFocusChangedLocked(); 9874 } 9875 9876 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9877 9878 if (imWindowChanged && oldFocus != mInputMethodWindow) { 9879 // Focus of the input method window changed. Perform layout if needed. 9880 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9881 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9882 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9883 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9884 // Client will do the layout, but we need to assign layers 9885 // for handleNewWindowLocked() below. 9886 assignLayersLocked(displayContent.getWindowList()); 9887 } 9888 } 9889 9890 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9891 // The change in focus caused us to need to do a layout. Okay. 9892 displayContent.layoutNeeded = true; 9893 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9894 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9895 } 9896 } 9897 9898 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9899 // If we defer assigning layers, then the caller is responsible for 9900 // doing this part. 9901 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 9902 } 9903 9904 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9905 return true; 9906 } 9907 return false; 9908 } 9909 9910 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 9911 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9912 } 9913 9914 private WindowState computeFocusedWindowLocked() { 9915 if (mAnimator.mUniverseBackground != null 9916 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 9917 return mAnimator.mUniverseBackground.mWin; 9918 } 9919 9920 final int displayCount = mDisplayContents.size(); 9921 for (int i = 0; i < displayCount; i++) { 9922 final DisplayContent displayContent = mDisplayContents.valueAt(i); 9923 WindowState win = findFocusedWindowLocked(displayContent); 9924 if (win != null) { 9925 return win; 9926 } 9927 } 9928 return null; 9929 } 9930 9931 private WindowState findFocusedWindowLocked(DisplayContent displayContent) { 9932 final WindowList windows = displayContent.getWindowList(); 9933 for (int i = windows.size() - 1; i >= 0; i--) { 9934 final WindowState win = windows.get(i); 9935 9936 if (localLOGV || DEBUG_FOCUS) Slog.v( 9937 TAG, "Looking for focus: " + i 9938 + " = " + win 9939 + ", flags=" + win.mAttrs.flags 9940 + ", canReceive=" + win.canReceiveKeys()); 9941 9942 AppWindowToken wtoken = win.mAppToken; 9943 9944 // If this window's application has been removed, just skip it. 9945 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 9946 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because " 9947 + (wtoken.removed ? "removed" : "sendingToBottom")); 9948 continue; 9949 } 9950 9951 if (!win.canReceiveKeys()) { 9952 continue; 9953 } 9954 9955 // Descend through all of the app tokens and find the first that either matches 9956 // win.mAppToken (return win) or mFocusedApp (return null). 9957 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && 9958 mFocusedApp != null) { 9959 ArrayList<Task> tasks = displayContent.getTasks(); 9960 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9961 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9962 int tokenNdx = tokens.size() - 1; 9963 for ( ; tokenNdx >= 0; --tokenNdx) { 9964 final AppWindowToken token = tokens.get(tokenNdx); 9965 if (wtoken == token) { 9966 break; 9967 } 9968 if (mFocusedApp == token) { 9969 // Whoops, we are below the focused app... no focus for you! 9970 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG, 9971 "findFocusedWindow: Reached focused app=" + mFocusedApp); 9972 return null; 9973 } 9974 } 9975 if (tokenNdx >= 0) { 9976 // Early exit from loop, must have found the matching token. 9977 break; 9978 } 9979 } 9980 } 9981 9982 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i + 9983 " = " + win); 9984 return win; 9985 } 9986 9987 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows."); 9988 return null; 9989 } 9990 9991 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 9992 if (mDisplayFrozen) { 9993 return; 9994 } 9995 9996 if (!mDisplayReady || !mPolicy.isScreenOnFully()) { 9997 // No need to freeze the screen before the system is ready or if 9998 // the screen is off. 9999 return; 10000 } 10001 10002 mScreenFrozenLock.acquire(); 10003 10004 mDisplayFrozen = true; 10005 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 10006 mLastFinishedFreezeSource = null; 10007 10008 mInputMonitor.freezeInputDispatchingLw(); 10009 10010 // Clear the last input window -- that is just used for 10011 // clean transitions between IMEs, and if we are freezing 10012 // the screen then the whole world is changing behind the scenes. 10013 mPolicy.setLastInputMethodWindowLw(null, null); 10014 10015 if (mAppTransition.isTransitionSet()) { 10016 mAppTransition.freeze(); 10017 } 10018 10019 if (PROFILE_ORIENTATION) { 10020 File file = new File("/data/system/frozen"); 10021 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 10022 } 10023 10024 if (CUSTOM_SCREEN_ROTATION) { 10025 mExitAnimId = exitAnim; 10026 mEnterAnimId = enterAnim; 10027 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10028 final int displayId = displayContent.getDisplayId(); 10029 ScreenRotationAnimation screenRotationAnimation = 10030 mAnimator.getScreenRotationAnimationLocked(displayId); 10031 if (screenRotationAnimation != null) { 10032 screenRotationAnimation.kill(); 10033 } 10034 10035 // Check whether the current screen contains any secure content. 10036 boolean isSecure = false; 10037 final WindowList windows = getDefaultWindowListLocked(); 10038 final int N = windows.size(); 10039 for (int i = 0; i < N; i++) { 10040 WindowState ws = windows.get(i); 10041 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) { 10042 isSecure = true; 10043 break; 10044 } 10045 } 10046 10047 // TODO(multidisplay): rotation on main screen only. 10048 displayContent.updateDisplayInfo(); 10049 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 10050 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure); 10051 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10052 } 10053 } 10054 10055 private void stopFreezingDisplayLocked() { 10056 if (!mDisplayFrozen) { 10057 return; 10058 } 10059 10060 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen 10061 || mClientFreezingScreen) { 10062 if (DEBUG_ORIENTATION) Slog.d(TAG, 10063 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 10064 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 10065 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 10066 + ", mClientFreezingScreen=" + mClientFreezingScreen); 10067 return; 10068 } 10069 10070 mDisplayFrozen = false; 10071 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 10072 StringBuilder sb = new StringBuilder(128); 10073 sb.append("Screen frozen for "); 10074 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 10075 if (mLastFinishedFreezeSource != null) { 10076 sb.append(" due to "); 10077 sb.append(mLastFinishedFreezeSource); 10078 } 10079 Slog.i(TAG, sb.toString()); 10080 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 10081 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 10082 if (PROFILE_ORIENTATION) { 10083 Debug.stopMethodTracing(); 10084 } 10085 10086 boolean updateRotation = false; 10087 10088 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10089 final int displayId = displayContent.getDisplayId(); 10090 ScreenRotationAnimation screenRotationAnimation = 10091 mAnimator.getScreenRotationAnimationLocked(displayId); 10092 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 10093 && screenRotationAnimation.hasScreenshot()) { 10094 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 10095 // TODO(multidisplay): rotation on main screen only. 10096 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10097 // Get rotation animation again, with new top window 10098 boolean isDimming = displayContent.isDimming(); 10099 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 10100 mExitAnimId = mEnterAnimId = 0; 10101 } 10102 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 10103 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, 10104 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 10105 scheduleAnimationLocked(); 10106 } else { 10107 screenRotationAnimation.kill(); 10108 screenRotationAnimation = null; 10109 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10110 updateRotation = true; 10111 } 10112 } else { 10113 if (screenRotationAnimation != null) { 10114 screenRotationAnimation.kill(); 10115 screenRotationAnimation = null; 10116 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10117 } 10118 updateRotation = true; 10119 } 10120 10121 mInputMonitor.thawInputDispatchingLw(); 10122 10123 boolean configChanged; 10124 10125 // While the display is frozen we don't re-compute the orientation 10126 // to avoid inconsistent states. However, something interesting 10127 // could have actually changed during that time so re-evaluate it 10128 // now to catch that. 10129 configChanged = updateOrientationFromAppTokensLocked(false); 10130 10131 // A little kludge: a lot could have happened while the 10132 // display was frozen, so now that we are coming back we 10133 // do a gc so that any remote references the system 10134 // processes holds on others can be released if they are 10135 // no longer needed. 10136 mH.removeMessages(H.FORCE_GC); 10137 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 10138 10139 mScreenFrozenLock.release(); 10140 10141 if (updateRotation) { 10142 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 10143 configChanged |= updateRotationUncheckedLocked(false); 10144 } 10145 10146 if (configChanged) { 10147 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10148 } 10149 } 10150 10151 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 10152 DisplayMetrics dm) { 10153 if (index < tokens.length) { 10154 String str = tokens[index]; 10155 if (str != null && str.length() > 0) { 10156 try { 10157 int val = Integer.parseInt(str); 10158 return val; 10159 } catch (Exception e) { 10160 } 10161 } 10162 } 10163 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 10164 return defDps; 10165 } 10166 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 10167 return val; 10168 } 10169 10170 void createWatermarkInTransaction() { 10171 if (mWatermark != null) { 10172 return; 10173 } 10174 10175 File file = new File("/system/etc/setup.conf"); 10176 FileInputStream in = null; 10177 DataInputStream ind = null; 10178 try { 10179 in = new FileInputStream(file); 10180 ind = new DataInputStream(in); 10181 String line = ind.readLine(); 10182 if (line != null) { 10183 String[] toks = line.split("%"); 10184 if (toks != null && toks.length > 0) { 10185 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 10186 mRealDisplayMetrics, mFxSession, toks); 10187 } 10188 } 10189 } catch (FileNotFoundException e) { 10190 } catch (IOException e) { 10191 } finally { 10192 if (ind != null) { 10193 try { 10194 ind.close(); 10195 } catch (IOException e) { 10196 } 10197 } else if (in != null) { 10198 try { 10199 in.close(); 10200 } catch (IOException e) { 10201 } 10202 } 10203 } 10204 } 10205 10206 @Override 10207 public void statusBarVisibilityChanged(int visibility) { 10208 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10209 != PackageManager.PERMISSION_GRANTED) { 10210 throw new SecurityException("Caller does not hold permission " 10211 + android.Manifest.permission.STATUS_BAR); 10212 } 10213 10214 synchronized (mWindowMap) { 10215 mLastStatusBarVisibility = visibility; 10216 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 10217 updateStatusBarVisibilityLocked(visibility); 10218 } 10219 } 10220 10221 // TOOD(multidisplay): StatusBar on multiple screens? 10222 void updateStatusBarVisibilityLocked(int visibility) { 10223 mInputManager.setSystemUiVisibility(visibility); 10224 final WindowList windows = getDefaultWindowListLocked(); 10225 final int N = windows.size(); 10226 for (int i = 0; i < N; i++) { 10227 WindowState ws = windows.get(i); 10228 try { 10229 int curValue = ws.mSystemUiVisibility; 10230 int diff = curValue ^ visibility; 10231 // We are only interested in differences of one of the 10232 // clearable flags... 10233 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 10234 // ...if it has actually been cleared. 10235 diff &= ~visibility; 10236 int newValue = (curValue&~diff) | (visibility&diff); 10237 if (newValue != curValue) { 10238 ws.mSeq++; 10239 ws.mSystemUiVisibility = newValue; 10240 } 10241 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 10242 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 10243 visibility, newValue, diff); 10244 } 10245 } catch (RemoteException e) { 10246 // so sorry 10247 } 10248 } 10249 } 10250 10251 @Override 10252 public void reevaluateStatusBarVisibility() { 10253 synchronized (mWindowMap) { 10254 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 10255 updateStatusBarVisibilityLocked(visibility); 10256 performLayoutAndPlaceSurfacesLocked(); 10257 } 10258 } 10259 10260 @Override 10261 public FakeWindow addFakeWindow(Looper looper, 10262 InputEventReceiver.Factory inputEventReceiverFactory, 10263 String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags, 10264 boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) { 10265 synchronized (mWindowMap) { 10266 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 10267 name, windowType, 10268 layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys, 10269 hasFocus, touchFullscreen); 10270 int i=0; 10271 while (i<mFakeWindows.size()) { 10272 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 10273 break; 10274 } 10275 } 10276 mFakeWindows.add(i, fw); 10277 mInputMonitor.updateInputWindowsLw(true); 10278 return fw; 10279 } 10280 } 10281 10282 boolean removeFakeWindowLocked(FakeWindow window) { 10283 synchronized (mWindowMap) { 10284 if (mFakeWindows.remove(window)) { 10285 mInputMonitor.updateInputWindowsLw(true); 10286 return true; 10287 } 10288 return false; 10289 } 10290 } 10291 10292 // It is assumed that this method is called only by InputMethodManagerService. 10293 public void saveLastInputMethodWindowForTransition() { 10294 synchronized (mWindowMap) { 10295 // TODO(multidisplay): Pass in the displayID. 10296 DisplayContent displayContent = getDefaultDisplayContentLocked(); 10297 if (mInputMethodWindow != null) { 10298 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 10299 } 10300 } 10301 } 10302 10303 public int getInputMethodWindowVisibleHeight() { 10304 synchronized (mWindowMap) { 10305 return mPolicy.getInputMethodWindowVisibleHeightLw(); 10306 } 10307 } 10308 10309 @Override 10310 public boolean hasNavigationBar() { 10311 return mPolicy.hasNavigationBar(); 10312 } 10313 10314 @Override 10315 public void lockNow(Bundle options) { 10316 mPolicy.lockNow(options); 10317 } 10318 10319 @Override 10320 public boolean isSafeModeEnabled() { 10321 return mSafeMode; 10322 } 10323 10324 @Override 10325 public boolean clearWindowContentFrameStats(IBinder token) { 10326 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10327 "clearWindowContentFrameStats()")) { 10328 throw new SecurityException("Requires FRAME_STATS permission"); 10329 } 10330 synchronized (mWindowMap) { 10331 WindowState windowState = mWindowMap.get(token); 10332 if (windowState == null) { 10333 return false; 10334 } 10335 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10336 if (surfaceControl == null) { 10337 return false; 10338 } 10339 return surfaceControl.clearContentFrameStats(); 10340 } 10341 } 10342 10343 @Override 10344 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) { 10345 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10346 "getWindowContentFrameStats()")) { 10347 throw new SecurityException("Requires FRAME_STATS permission"); 10348 } 10349 synchronized (mWindowMap) { 10350 WindowState windowState = mWindowMap.get(token); 10351 if (windowState == null) { 10352 return null; 10353 } 10354 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10355 if (surfaceControl == null) { 10356 return null; 10357 } 10358 if (mTempWindowRenderStats == null) { 10359 mTempWindowRenderStats = new WindowContentFrameStats(); 10360 } 10361 WindowContentFrameStats stats = mTempWindowRenderStats; 10362 if (!surfaceControl.getContentFrameStats(stats)) { 10363 return null; 10364 } 10365 return stats; 10366 } 10367 } 10368 10369 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10370 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 10371 mPolicy.dump(" ", pw, args); 10372 } 10373 10374 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10375 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 10376 mAnimator.dumpLocked(pw, " ", dumpAll); 10377 } 10378 10379 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 10380 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 10381 if (mTokenMap.size() > 0) { 10382 pw.println(" All tokens:"); 10383 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10384 while (it.hasNext()) { 10385 WindowToken token = it.next(); 10386 pw.print(" "); pw.print(token); 10387 if (dumpAll) { 10388 pw.println(':'); 10389 token.dump(pw, " "); 10390 } else { 10391 pw.println(); 10392 } 10393 } 10394 } 10395 if (mWallpaperTokens.size() > 0) { 10396 pw.println(); 10397 pw.println(" Wallpaper tokens:"); 10398 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 10399 WindowToken token = mWallpaperTokens.get(i); 10400 pw.print(" Wallpaper #"); pw.print(i); 10401 pw.print(' '); pw.print(token); 10402 if (dumpAll) { 10403 pw.println(':'); 10404 token.dump(pw, " "); 10405 } else { 10406 pw.println(); 10407 } 10408 } 10409 } 10410 if (mFinishedStarting.size() > 0) { 10411 pw.println(); 10412 pw.println(" Finishing start of application tokens:"); 10413 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10414 WindowToken token = mFinishedStarting.get(i); 10415 pw.print(" Finished Starting #"); pw.print(i); 10416 pw.print(' '); pw.print(token); 10417 if (dumpAll) { 10418 pw.println(':'); 10419 token.dump(pw, " "); 10420 } else { 10421 pw.println(); 10422 } 10423 } 10424 } 10425 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 10426 pw.println(); 10427 if (mOpeningApps.size() > 0) { 10428 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10429 } 10430 if (mClosingApps.size() > 0) { 10431 pw.print(" mClosingApps="); pw.println(mClosingApps); 10432 } 10433 } 10434 } 10435 10436 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 10437 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 10438 for (int i=0; i<mSessions.size(); i++) { 10439 Session s = mSessions.valueAt(i); 10440 pw.print(" Session "); pw.print(s); pw.println(':'); 10441 s.dump(pw, " "); 10442 } 10443 } 10444 10445 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 10446 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 10447 if (mDisplayReady) { 10448 final int numDisplays = mDisplayContents.size(); 10449 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10450 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10451 displayContent.dump(" ", pw); 10452 } 10453 } else { 10454 pw.println(" NO DISPLAY"); 10455 } 10456 } 10457 10458 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 10459 ArrayList<WindowState> windows) { 10460 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 10461 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 10462 } 10463 10464 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 10465 ArrayList<WindowState> windows) { 10466 final int numDisplays = mDisplayContents.size(); 10467 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10468 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); 10469 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10470 final WindowState w = windowList.get(winNdx); 10471 if (windows == null || windows.contains(w)) { 10472 pw.print(" Window #"); pw.print(winNdx); pw.print(' '); 10473 pw.print(w); pw.println(":"); 10474 w.dump(pw, " ", dumpAll || windows != null); 10475 } 10476 } 10477 } 10478 if (mInputMethodDialogs.size() > 0) { 10479 pw.println(); 10480 pw.println(" Input method dialogs:"); 10481 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 10482 WindowState w = mInputMethodDialogs.get(i); 10483 if (windows == null || windows.contains(w)) { 10484 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 10485 } 10486 } 10487 } 10488 if (mPendingRemove.size() > 0) { 10489 pw.println(); 10490 pw.println(" Remove pending for:"); 10491 for (int i=mPendingRemove.size()-1; i>=0; i--) { 10492 WindowState w = mPendingRemove.get(i); 10493 if (windows == null || windows.contains(w)) { 10494 pw.print(" Remove #"); pw.print(i); pw.print(' '); 10495 pw.print(w); 10496 if (dumpAll) { 10497 pw.println(":"); 10498 w.dump(pw, " ", true); 10499 } else { 10500 pw.println(); 10501 } 10502 } 10503 } 10504 } 10505 if (mForceRemoves != null && mForceRemoves.size() > 0) { 10506 pw.println(); 10507 pw.println(" Windows force removing:"); 10508 for (int i=mForceRemoves.size()-1; i>=0; i--) { 10509 WindowState w = mForceRemoves.get(i); 10510 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10511 pw.print(w); 10512 if (dumpAll) { 10513 pw.println(":"); 10514 w.dump(pw, " ", true); 10515 } else { 10516 pw.println(); 10517 } 10518 } 10519 } 10520 if (mDestroySurface.size() > 0) { 10521 pw.println(); 10522 pw.println(" Windows waiting to destroy their surface:"); 10523 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10524 WindowState w = mDestroySurface.get(i); 10525 if (windows == null || windows.contains(w)) { 10526 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10527 pw.print(w); 10528 if (dumpAll) { 10529 pw.println(":"); 10530 w.dump(pw, " ", true); 10531 } else { 10532 pw.println(); 10533 } 10534 } 10535 } 10536 } 10537 if (mLosingFocus.size() > 0) { 10538 pw.println(); 10539 pw.println(" Windows losing focus:"); 10540 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10541 WindowState w = mLosingFocus.get(i); 10542 if (windows == null || windows.contains(w)) { 10543 pw.print(" Losing #"); pw.print(i); pw.print(' '); 10544 pw.print(w); 10545 if (dumpAll) { 10546 pw.println(":"); 10547 w.dump(pw, " ", true); 10548 } else { 10549 pw.println(); 10550 } 10551 } 10552 } 10553 } 10554 if (mResizingWindows.size() > 0) { 10555 pw.println(); 10556 pw.println(" Windows waiting to resize:"); 10557 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10558 WindowState w = mResizingWindows.get(i); 10559 if (windows == null || windows.contains(w)) { 10560 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 10561 pw.print(w); 10562 if (dumpAll) { 10563 pw.println(":"); 10564 w.dump(pw, " ", true); 10565 } else { 10566 pw.println(); 10567 } 10568 } 10569 } 10570 } 10571 if (mWaitingForDrawn.size() > 0) { 10572 pw.println(); 10573 pw.println(" Clients waiting for these windows to be drawn:"); 10574 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10575 WindowState win = mWaitingForDrawn.get(i); 10576 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); 10577 } 10578 } 10579 pw.println(); 10580 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10581 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10582 if (mLastFocus != mCurrentFocus) { 10583 pw.print(" mLastFocus="); pw.println(mLastFocus); 10584 } 10585 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10586 if (mInputMethodTarget != null) { 10587 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10588 } 10589 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10590 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10591 pw.print(" mLastDisplayFreezeDuration="); 10592 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 10593 if ( mLastFinishedFreezeSource != null) { 10594 pw.print(" due to "); 10595 pw.print(mLastFinishedFreezeSource); 10596 } 10597 pw.println(); 10598 if (dumpAll) { 10599 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 10600 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 10601 if (mLastStatusBarVisibility != 0) { 10602 pw.print(" mLastStatusBarVisibility=0x"); 10603 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 10604 } 10605 if (mInputMethodWindow != null) { 10606 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10607 } 10608 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 10609 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) { 10610 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 10611 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 10612 } 10613 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 10614 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 10615 if (mInputMethodAnimLayerAdjustment != 0 || 10616 mWallpaperAnimLayerAdjustment != 0) { 10617 pw.print(" mInputMethodAnimLayerAdjustment="); 10618 pw.print(mInputMethodAnimLayerAdjustment); 10619 pw.print(" mWallpaperAnimLayerAdjustment="); 10620 pw.println(mWallpaperAnimLayerAdjustment); 10621 } 10622 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10623 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10624 if (needsLayout()) { 10625 pw.print(" layoutNeeded on displays="); 10626 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10627 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10628 if (displayContent.layoutNeeded) { 10629 pw.print(displayContent.getDisplayId()); 10630 } 10631 } 10632 pw.println(); 10633 } 10634 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 10635 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10636 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 10637 pw.print(" client="); pw.print(mClientFreezingScreen); 10638 pw.print(" apps="); pw.print(mAppsFreezingScreen); 10639 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 10640 pw.print(" mRotation="); pw.print(mRotation); 10641 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 10642 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 10643 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 10644 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 10645 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled); 10646 pw.print(" window="); pw.print(mWindowAnimationScaleSetting); 10647 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); 10648 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); 10649 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); 10650 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 10651 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 10652 pw.println(" mLayoutToAnim:"); 10653 mAppTransition.dump(pw); 10654 } 10655 } 10656 10657 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10658 int opti, boolean dumpAll) { 10659 WindowList windows = new WindowList(); 10660 if ("visible".equals(name)) { 10661 synchronized(mWindowMap) { 10662 final int numDisplays = mDisplayContents.size(); 10663 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10664 final WindowList windowList = 10665 mDisplayContents.valueAt(displayNdx).getWindowList(); 10666 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10667 final WindowState w = windowList.get(winNdx); 10668 if (w.mWinAnimator.mSurfaceShown) { 10669 windows.add(w); 10670 } 10671 } 10672 } 10673 } 10674 } else { 10675 int objectId = 0; 10676 // See if this is an object ID. 10677 try { 10678 objectId = Integer.parseInt(name, 16); 10679 name = null; 10680 } catch (RuntimeException e) { 10681 } 10682 synchronized(mWindowMap) { 10683 final int numDisplays = mDisplayContents.size(); 10684 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10685 final WindowList windowList = 10686 mDisplayContents.valueAt(displayNdx).getWindowList(); 10687 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10688 final WindowState w = windowList.get(winNdx); 10689 if (name != null) { 10690 if (w.mAttrs.getTitle().toString().contains(name)) { 10691 windows.add(w); 10692 } 10693 } else if (System.identityHashCode(w) == objectId) { 10694 windows.add(w); 10695 } 10696 } 10697 } 10698 } 10699 } 10700 10701 if (windows.size() <= 0) { 10702 return false; 10703 } 10704 10705 synchronized(mWindowMap) { 10706 dumpWindowsLocked(pw, dumpAll, windows); 10707 } 10708 return true; 10709 } 10710 10711 void dumpLastANRLocked(PrintWriter pw) { 10712 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10713 if (mLastANRState == null) { 10714 pw.println(" <no ANR has occurred since boot>"); 10715 } else { 10716 pw.println(mLastANRState); 10717 } 10718 } 10719 10720 /** 10721 * Saves information about the state of the window manager at 10722 * the time an ANR occurred before anything else in the system changes 10723 * in response. 10724 * 10725 * @param appWindowToken The application that ANR'd, may be null. 10726 * @param windowState The window that ANR'd, may be null. 10727 * @param reason The reason for the ANR, may be null. 10728 */ 10729 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, 10730 String reason) { 10731 StringWriter sw = new StringWriter(); 10732 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 10733 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10734 if (appWindowToken != null) { 10735 pw.println(" Application at fault: " + appWindowToken.stringName); 10736 } 10737 if (windowState != null) { 10738 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10739 } 10740 if (reason != null) { 10741 pw.println(" Reason: " + reason); 10742 } 10743 pw.println(); 10744 dumpWindowsNoHeaderLocked(pw, true, null); 10745 pw.close(); 10746 mLastANRState = sw.toString(); 10747 } 10748 10749 @Override 10750 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10751 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10752 != PackageManager.PERMISSION_GRANTED) { 10753 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10754 + Binder.getCallingPid() 10755 + ", uid=" + Binder.getCallingUid()); 10756 return; 10757 } 10758 10759 boolean dumpAll = false; 10760 10761 int opti = 0; 10762 while (opti < args.length) { 10763 String opt = args[opti]; 10764 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10765 break; 10766 } 10767 opti++; 10768 if ("-a".equals(opt)) { 10769 dumpAll = true; 10770 } else if ("-h".equals(opt)) { 10771 pw.println("Window manager dump options:"); 10772 pw.println(" [-a] [-h] [cmd] ..."); 10773 pw.println(" cmd may be one of:"); 10774 pw.println(" l[astanr]: last ANR information"); 10775 pw.println(" p[policy]: policy state"); 10776 pw.println(" a[animator]: animator state"); 10777 pw.println(" s[essions]: active sessions"); 10778 pw.println(" d[isplays]: active display contents"); 10779 pw.println(" t[okens]: token list"); 10780 pw.println(" w[indows]: window list"); 10781 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10782 pw.println(" be a partial substring in a window name, a"); 10783 pw.println(" Window hex object identifier, or"); 10784 pw.println(" \"all\" for all windows, or"); 10785 pw.println(" \"visible\" for the visible windows."); 10786 pw.println(" -a: include all available server state."); 10787 return; 10788 } else { 10789 pw.println("Unknown argument: " + opt + "; use -h for help"); 10790 } 10791 } 10792 10793 // Is the caller requesting to dump a particular piece of data? 10794 if (opti < args.length) { 10795 String cmd = args[opti]; 10796 opti++; 10797 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10798 synchronized(mWindowMap) { 10799 dumpLastANRLocked(pw); 10800 } 10801 return; 10802 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10803 synchronized(mWindowMap) { 10804 dumpPolicyLocked(pw, args, true); 10805 } 10806 return; 10807 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 10808 synchronized(mWindowMap) { 10809 dumpAnimatorLocked(pw, args, true); 10810 } 10811 return; 10812 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10813 synchronized(mWindowMap) { 10814 dumpSessionsLocked(pw, true); 10815 } 10816 return; 10817 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 10818 synchronized(mWindowMap) { 10819 dumpDisplayContentsLocked(pw, true); 10820 } 10821 return; 10822 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10823 synchronized(mWindowMap) { 10824 dumpTokensLocked(pw, true); 10825 } 10826 return; 10827 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10828 synchronized(mWindowMap) { 10829 dumpWindowsLocked(pw, true, null); 10830 } 10831 return; 10832 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10833 synchronized(mWindowMap) { 10834 dumpWindowsLocked(pw, true, null); 10835 } 10836 return; 10837 } else { 10838 // Dumping a single name? 10839 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10840 pw.println("Bad window command, or no windows match: " + cmd); 10841 pw.println("Use -h for help."); 10842 } 10843 return; 10844 } 10845 } 10846 10847 synchronized(mWindowMap) { 10848 pw.println(); 10849 if (dumpAll) { 10850 pw.println("-------------------------------------------------------------------------------"); 10851 } 10852 dumpLastANRLocked(pw); 10853 pw.println(); 10854 if (dumpAll) { 10855 pw.println("-------------------------------------------------------------------------------"); 10856 } 10857 dumpPolicyLocked(pw, args, dumpAll); 10858 pw.println(); 10859 if (dumpAll) { 10860 pw.println("-------------------------------------------------------------------------------"); 10861 } 10862 dumpAnimatorLocked(pw, args, dumpAll); 10863 pw.println(); 10864 if (dumpAll) { 10865 pw.println("-------------------------------------------------------------------------------"); 10866 } 10867 dumpSessionsLocked(pw, dumpAll); 10868 pw.println(); 10869 if (dumpAll) { 10870 pw.println("-------------------------------------------------------------------------------"); 10871 } 10872 dumpDisplayContentsLocked(pw, dumpAll); 10873 pw.println(); 10874 if (dumpAll) { 10875 pw.println("-------------------------------------------------------------------------------"); 10876 } 10877 dumpTokensLocked(pw, dumpAll); 10878 pw.println(); 10879 if (dumpAll) { 10880 pw.println("-------------------------------------------------------------------------------"); 10881 } 10882 dumpWindowsLocked(pw, dumpAll, null); 10883 } 10884 } 10885 10886 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10887 @Override 10888 public void monitor() { 10889 synchronized (mWindowMap) { } 10890 } 10891 10892 public interface OnHardKeyboardStatusChangeListener { 10893 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 10894 } 10895 10896 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 10897 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 10898 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 10899 Integer.toHexString(pendingLayoutChanges)); 10900 } 10901 } 10902 10903 private DisplayContent newDisplayContentLocked(final Display display) { 10904 DisplayContent displayContent = new DisplayContent(display, this); 10905 final int displayId = display.getDisplayId(); 10906 if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display); 10907 mDisplayContents.put(displayId, displayContent); 10908 10909 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10910 final Rect rect = new Rect(); 10911 mDisplaySettings.getOverscanLocked(displayInfo.name, rect); 10912 synchronized (displayContent.mDisplaySizeLock) { 10913 displayInfo.overscanLeft = rect.left; 10914 displayInfo.overscanTop = rect.top; 10915 displayInfo.overscanRight = rect.right; 10916 displayInfo.overscanBottom = rect.bottom; 10917 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 10918 displayId, displayInfo); 10919 } 10920 configureDisplayPolicyLocked(displayContent); 10921 10922 // TODO: Create an input channel for each display with touch capability. 10923 if (displayId == Display.DEFAULT_DISPLAY) { 10924 displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent); 10925 registerPointerEventListener(displayContent.mTapDetector); 10926 } 10927 10928 return displayContent; 10929 } 10930 10931 public void createDisplayContentLocked(final Display display) { 10932 if (display == null) { 10933 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 10934 } 10935 getDisplayContentLocked(display.getDisplayId()); 10936 } 10937 10938 /** 10939 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 10940 * there is a Display for the displayId. 10941 * @param displayId The display the caller is interested in. 10942 * @return The DisplayContent associated with displayId or null if there is no Display for it. 10943 */ 10944 public DisplayContent getDisplayContentLocked(final int displayId) { 10945 DisplayContent displayContent = mDisplayContents.get(displayId); 10946 if (displayContent == null) { 10947 final Display display = mDisplayManager.getDisplay(displayId); 10948 if (display != null) { 10949 displayContent = newDisplayContentLocked(display); 10950 } 10951 } 10952 return displayContent; 10953 } 10954 10955 // There is an inherent assumption that this will never return null. 10956 public DisplayContent getDefaultDisplayContentLocked() { 10957 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 10958 } 10959 10960 public WindowList getDefaultWindowListLocked() { 10961 return getDefaultDisplayContentLocked().getWindowList(); 10962 } 10963 10964 public DisplayInfo getDefaultDisplayInfoLocked() { 10965 return getDefaultDisplayContentLocked().getDisplayInfo(); 10966 } 10967 10968 /** 10969 * Return the list of WindowStates associated on the passed display. 10970 * @param display The screen to return windows from. 10971 * @return The list of WindowStates on the screen, or null if the there is no screen. 10972 */ 10973 public WindowList getWindowListLocked(final Display display) { 10974 return getWindowListLocked(display.getDisplayId()); 10975 } 10976 10977 /** 10978 * Return the list of WindowStates associated on the passed display. 10979 * @param displayId The screen to return windows from. 10980 * @return The list of WindowStates on the screen, or null if the there is no screen. 10981 */ 10982 public WindowList getWindowListLocked(final int displayId) { 10983 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10984 return displayContent != null ? displayContent.getWindowList() : null; 10985 } 10986 10987 public void onDisplayAdded(int displayId) { 10988 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 10989 } 10990 10991 public void handleDisplayAdded(int displayId) { 10992 synchronized (mWindowMap) { 10993 final Display display = mDisplayManager.getDisplay(displayId); 10994 if (display != null) { 10995 createDisplayContentLocked(display); 10996 displayReady(displayId); 10997 } 10998 } 10999 } 11000 11001 public void onDisplayRemoved(int displayId) { 11002 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 11003 } 11004 11005 private void handleDisplayRemovedLocked(int displayId) { 11006 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11007 if (displayContent != null) { 11008 if (displayContent.isAnimating()) { 11009 displayContent.mDeferredRemoval = true; 11010 return; 11011 } 11012 if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent); 11013 mDisplayContents.delete(displayId); 11014 displayContent.close(); 11015 if (displayId == Display.DEFAULT_DISPLAY) { 11016 unregisterPointerEventListener(displayContent.mTapDetector); 11017 } 11018 } 11019 mAnimator.removeDisplayLocked(displayId); 11020 } 11021 11022 public void onDisplayChanged(int displayId) { 11023 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 11024 } 11025 11026 private void handleDisplayChangedLocked(int displayId) { 11027 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11028 if (displayContent != null) { 11029 displayContent.updateDisplayInfo(); 11030 } 11031 } 11032 11033 @Override 11034 public Object getWindowManagerLock() { 11035 return mWindowMap; 11036 } 11037 11038 private final class LocalService extends WindowManagerInternal { 11039 @Override 11040 public void requestTraversalFromDisplayManager() { 11041 requestTraversal(); 11042 } 11043 11044 @Override 11045 public void setMagnificationSpec(MagnificationSpec spec) { 11046 synchronized (mWindowMap) { 11047 if (mAccessibilityController != null) { 11048 mAccessibilityController.setMagnificationSpecLocked(spec); 11049 } else { 11050 throw new IllegalStateException("Magnification callbacks not set!"); 11051 } 11052 } 11053 if (Binder.getCallingPid() != android.os.Process.myPid()) { 11054 spec.recycle(); 11055 } 11056 } 11057 11058 @Override 11059 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { 11060 synchronized (mWindowMap) { 11061 WindowState windowState = mWindowMap.get(windowToken); 11062 if (windowState == null) { 11063 return null; 11064 } 11065 MagnificationSpec spec = null; 11066 if (mAccessibilityController != null) { 11067 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState); 11068 } 11069 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) { 11070 return null; 11071 } 11072 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec); 11073 spec.scale *= windowState.mGlobalScale; 11074 return spec; 11075 } 11076 } 11077 11078 @Override 11079 public void setMagnificationCallbacks(MagnificationCallbacks callbacks) { 11080 synchronized (mWindowMap) { 11081 if (mAccessibilityController == null) { 11082 mAccessibilityController = new AccessibilityController( 11083 WindowManagerService.this); 11084 } 11085 mAccessibilityController.setMagnificationCallbacksLocked(callbacks); 11086 if (!mAccessibilityController.hasCallbacksLocked()) { 11087 mAccessibilityController = null; 11088 } 11089 } 11090 } 11091 11092 @Override 11093 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) { 11094 synchronized (mWindowMap) { 11095 if (mAccessibilityController == null) { 11096 mAccessibilityController = new AccessibilityController( 11097 WindowManagerService.this); 11098 } 11099 mAccessibilityController.setWindowsForAccessibilityCallback(callback); 11100 if (!mAccessibilityController.hasCallbacksLocked()) { 11101 mAccessibilityController = null; 11102 } 11103 } 11104 } 11105 11106 @Override 11107 public void setInputFilter(IInputFilter filter) { 11108 mInputManager.setInputFilter(filter); 11109 } 11110 11111 @Override 11112 public IBinder getFocusedWindowToken() { 11113 synchronized (mWindowMap) { 11114 WindowState windowState = getFocusedWindowLocked(); 11115 if (windowState != null) { 11116 return windowState.mClient.asBinder(); 11117 } 11118 return null; 11119 } 11120 } 11121 11122 @Override 11123 public boolean isKeyguardLocked() { 11124 return isKeyguardLocked(); 11125 } 11126 11127 @Override 11128 public void getWindowFrame(IBinder token, Rect outBounds) { 11129 synchronized (mWindowMap) { 11130 WindowState windowState = mWindowMap.get(token); 11131 if (windowState != null) { 11132 outBounds.set(windowState.mFrame); 11133 } else { 11134 outBounds.setEmpty(); 11135 } 11136 } 11137 } 11138 11139 public void waitForAllWindowsDrawn(Runnable callback, long timeout) { 11140 synchronized (mWindowMap) { 11141 mWaitingForDrawnCallback = callback; 11142 final WindowList windows = getDefaultWindowListLocked(); 11143 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 11144 final WindowState win = windows.get(winNdx); 11145 if (win.mHasSurface && win.isWinVisibleLw()) { 11146 if (!win.mIsWallpaper) { 11147 // Don't force wallpaper to redraw. 11148 win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 11149 } 11150 // Force add to mResizingWindows. 11151 win.mLastContentInsets.set(-1, -1, -1, -1); 11152 mWaitingForDrawn.add(win); 11153 } 11154 } 11155 requestTraversalLocked(); 11156 } 11157 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 11158 if (mWaitingForDrawn.isEmpty()) { 11159 callback.run(); 11160 } else { 11161 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); 11162 checkDrawnWindowsLocked(); 11163 } 11164 } 11165 } 11166} 11167