WindowManagerService.java revision bb742462781a73bb25516067c8fe6311c1c8a93e
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 ArraySet<AppWindowToken> mOpeningApps = new ArraySet<AppWindowToken>(); 501 final ArraySet<AppWindowToken> mClosingApps = new ArraySet<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, Rect outStableInsets, Configuration outConfig, 2839 Surface outSurface) { 2840 boolean toBeDisplayed = false; 2841 boolean inTouchMode; 2842 boolean configChanged; 2843 boolean surfaceChanged = false; 2844 boolean animating; 2845 boolean hasStatusBarPermission = 2846 mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 2847 == PackageManager.PERMISSION_GRANTED; 2848 2849 long origId = Binder.clearCallingIdentity(); 2850 2851 synchronized(mWindowMap) { 2852 WindowState win = windowForClientLocked(session, client, false); 2853 if (win == null) { 2854 return 0; 2855 } 2856 WindowStateAnimator winAnimator = win.mWinAnimator; 2857 if (win.mRequestedWidth != requestedWidth 2858 || win.mRequestedHeight != requestedHeight) { 2859 win.mLayoutNeeded = true; 2860 win.mRequestedWidth = requestedWidth; 2861 win.mRequestedHeight = requestedHeight; 2862 } 2863 2864 if (attrs != null) { 2865 mPolicy.adjustWindowParamsLw(attrs); 2866 } 2867 2868 // if they don't have the permission, mask out the status bar bits 2869 int systemUiVisibility = 0; 2870 if (attrs != null) { 2871 systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility); 2872 if ((systemUiVisibility & StatusBarManager.DISABLE_MASK) != 0) { 2873 if (!hasStatusBarPermission) { 2874 systemUiVisibility &= ~StatusBarManager.DISABLE_MASK; 2875 } 2876 } 2877 } 2878 2879 if (attrs != null && seq == win.mSeq) { 2880 win.mSystemUiVisibility = systemUiVisibility; 2881 } 2882 2883 winAnimator.mSurfaceDestroyDeferred = 2884 (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0; 2885 2886 int attrChanges = 0; 2887 int flagChanges = 0; 2888 if (attrs != null) { 2889 if (win.mAttrs.type != attrs.type) { 2890 throw new IllegalArgumentException( 2891 "Window type can not be changed after the window is added."); 2892 } 2893 flagChanges = win.mAttrs.flags ^= attrs.flags; 2894 attrChanges = win.mAttrs.copyFrom(attrs); 2895 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED 2896 | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) { 2897 win.mLayoutNeeded = true; 2898 } 2899 } 2900 2901 if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility 2902 + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs); 2903 2904 win.mEnforceSizeCompat = 2905 (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0; 2906 2907 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) { 2908 winAnimator.mAlpha = attrs.alpha; 2909 } 2910 2911 final boolean scaledWindow = 2912 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0); 2913 2914 if (scaledWindow) { 2915 // requested{Width|Height} Surface's physical size 2916 // attrs.{width|height} Size on screen 2917 win.mHScale = (attrs.width != requestedWidth) ? 2918 (attrs.width / (float)requestedWidth) : 1.0f; 2919 win.mVScale = (attrs.height != requestedHeight) ? 2920 (attrs.height / (float)requestedHeight) : 1.0f; 2921 } else { 2922 win.mHScale = win.mVScale = 1; 2923 } 2924 2925 boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0; 2926 2927 final boolean isDefaultDisplay = win.isDefaultDisplay(); 2928 boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility 2929 || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0) 2930 || (!win.mRelayoutCalled)); 2931 2932 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility 2933 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0; 2934 wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0; 2935 2936 win.mRelayoutCalled = true; 2937 final int oldVisibility = win.mViewVisibility; 2938 win.mViewVisibility = viewVisibility; 2939 if (DEBUG_SCREEN_ON) { 2940 RuntimeException stack = new RuntimeException(); 2941 stack.fillInStackTrace(); 2942 Slog.i(TAG, "Relayout " + win + ": oldVis=" + oldVisibility 2943 + " newVis=" + viewVisibility, stack); 2944 } 2945 if (viewVisibility == View.VISIBLE && 2946 (win.mAppToken == null || !win.mAppToken.clientHidden)) { 2947 toBeDisplayed = !win.isVisibleLw(); 2948 if (win.mExiting) { 2949 winAnimator.cancelExitAnimationForNextAnimationLocked(); 2950 win.mExiting = false; 2951 } 2952 if (win.mDestroying) { 2953 win.mDestroying = false; 2954 mDestroySurface.remove(win); 2955 } 2956 if (oldVisibility == View.GONE) { 2957 winAnimator.mEnterAnimationPending = true; 2958 } 2959 if (toBeDisplayed) { 2960 if (win.isDrawnLw() && okToDisplay()) { 2961 winAnimator.applyEnterAnimationLocked(); 2962 } 2963 if ((win.mAttrs.flags 2964 & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) { 2965 if (DEBUG_VISIBILITY) Slog.v(TAG, 2966 "Relayout window turning screen on: " + win); 2967 win.mTurnOnScreen = true; 2968 } 2969 if (win.isConfigChanged()) { 2970 if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win 2971 + " visible with new config: " + mCurConfiguration); 2972 outConfig.setTo(mCurConfiguration); 2973 } 2974 } 2975 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) { 2976 // To change the format, we need to re-build the surface. 2977 winAnimator.destroySurfaceLocked(); 2978 toBeDisplayed = true; 2979 surfaceChanged = true; 2980 } 2981 try { 2982 if (!win.mHasSurface) { 2983 surfaceChanged = true; 2984 } 2985 SurfaceControl surfaceControl = winAnimator.createSurfaceLocked(); 2986 if (surfaceControl != null) { 2987 outSurface.copyFrom(surfaceControl); 2988 if (SHOW_TRANSACTIONS) Slog.i(TAG, 2989 " OUT SURFACE " + outSurface + ": copied"); 2990 } else { 2991 // For some reason there isn't a surface. Clear the 2992 // caller's object so they see the same state. 2993 outSurface.release(); 2994 } 2995 } catch (Exception e) { 2996 mInputMonitor.updateInputWindowsLw(true /*force*/); 2997 2998 Slog.w(TAG, "Exception thrown when creating surface for client " 2999 + client + " (" + win.mAttrs.getTitle() + ")", 3000 e); 3001 Binder.restoreCallingIdentity(origId); 3002 return 0; 3003 } 3004 if (toBeDisplayed) { 3005 focusMayChange = isDefaultDisplay; 3006 } 3007 if (win.mAttrs.type == TYPE_INPUT_METHOD 3008 && mInputMethodWindow == null) { 3009 mInputMethodWindow = win; 3010 imMayMove = true; 3011 } 3012 if (win.mAttrs.type == TYPE_BASE_APPLICATION 3013 && win.mAppToken != null 3014 && win.mAppToken.startingWindow != null) { 3015 // Special handling of starting window over the base 3016 // window of the app: propagate lock screen flags to it, 3017 // to provide the correct semantics while starting. 3018 final int mask = 3019 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED 3020 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD 3021 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; 3022 WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs; 3023 sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask); 3024 } 3025 } else { 3026 winAnimator.mEnterAnimationPending = false; 3027 if (winAnimator.mSurfaceControl != null) { 3028 if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win 3029 + ": mExiting=" + win.mExiting); 3030 // If we are not currently running the exit animation, we 3031 // need to see about starting one. 3032 if (!win.mExiting) { 3033 surfaceChanged = true; 3034 // Try starting an animation; if there isn't one, we 3035 // can destroy the surface right away. 3036 int transit = WindowManagerPolicy.TRANSIT_EXIT; 3037 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 3038 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 3039 } 3040 if (win.isWinVisibleLw() && 3041 winAnimator.applyAnimationLocked(transit, false)) { 3042 focusMayChange = isDefaultDisplay; 3043 win.mExiting = true; 3044 } else if (win.mWinAnimator.isAnimating()) { 3045 // Currently in a hide animation... turn this into 3046 // an exit. 3047 win.mExiting = true; 3048 } else if (win == mWallpaperTarget) { 3049 // If the wallpaper is currently behind this 3050 // window, we need to change both of them inside 3051 // of a transaction to avoid artifacts. 3052 win.mExiting = true; 3053 win.mWinAnimator.mAnimating = true; 3054 } else { 3055 if (mInputMethodWindow == win) { 3056 mInputMethodWindow = null; 3057 } 3058 winAnimator.destroySurfaceLocked(); 3059 } 3060 //TODO (multidisplay): Magnification is supported only for the default 3061 if (mAccessibilityController != null 3062 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 3063 mAccessibilityController.onWindowTransitionLocked(win, transit); 3064 } 3065 } 3066 } 3067 3068 outSurface.release(); 3069 if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win); 3070 } 3071 3072 if (focusMayChange) { 3073 //System.out.println("Focus may change: " + win.mAttrs.getTitle()); 3074 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 3075 false /*updateInputWindows*/)) { 3076 imMayMove = false; 3077 } 3078 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus); 3079 } 3080 3081 // updateFocusedWindowLocked() already assigned layers so we only need to 3082 // reassign them at this point if the IM window state gets shuffled 3083 if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) { 3084 // Little hack here -- we -should- be able to rely on the 3085 // function to return true if the IME has moved and needs 3086 // its layer recomputed. However, if the IME was hidden 3087 // and isn't actually moved in the list, its layer may be 3088 // out of data so we make sure to recompute it. 3089 assignLayersLocked(win.getWindowList()); 3090 } 3091 3092 if (wallpaperMayMove) { 3093 getDefaultDisplayContentLocked().pendingLayoutChanges |= 3094 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 3095 } 3096 3097 final DisplayContent displayContent = win.getDisplayContent(); 3098 if (displayContent != null) { 3099 displayContent.layoutNeeded = true; 3100 } 3101 win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0; 3102 configChanged = updateOrientationFromAppTokensLocked(false); 3103 performLayoutAndPlaceSurfacesLocked(); 3104 if (toBeDisplayed && win.mIsWallpaper) { 3105 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 3106 updateWallpaperOffsetLocked(win, 3107 displayInfo.logicalWidth, displayInfo.logicalHeight, false); 3108 } 3109 if (win.mAppToken != null) { 3110 win.mAppToken.updateReportedVisibilityLocked(); 3111 } 3112 outFrame.set(win.mCompatFrame); 3113 outOverscanInsets.set(win.mOverscanInsets); 3114 outContentInsets.set(win.mContentInsets); 3115 outVisibleInsets.set(win.mVisibleInsets); 3116 outStableInsets.set(win.mStableInsets); 3117 if (localLOGV) Slog.v( 3118 TAG, "Relayout given client " + client.asBinder() 3119 + ", requestedWidth=" + requestedWidth 3120 + ", requestedHeight=" + requestedHeight 3121 + ", viewVisibility=" + viewVisibility 3122 + "\nRelayout returning frame=" + outFrame 3123 + ", surface=" + outSurface); 3124 3125 if (localLOGV || DEBUG_FOCUS) Slog.v( 3126 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange); 3127 3128 inTouchMode = mInTouchMode; 3129 animating = mAnimator.mAnimating && win.mWinAnimator.isAnimating(); 3130 if (animating && !mRelayoutWhileAnimating.contains(win)) { 3131 mRelayoutWhileAnimating.add(win); 3132 } 3133 3134 mInputMonitor.updateInputWindowsLw(true /*force*/); 3135 3136 if (DEBUG_LAYOUT) { 3137 Slog.v(TAG, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString()); 3138 } 3139 } 3140 3141 if (configChanged) { 3142 sendNewConfiguration(); 3143 } 3144 3145 Binder.restoreCallingIdentity(origId); 3146 3147 return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0) 3148 | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0) 3149 | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0) 3150 | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0); 3151 } 3152 3153 public void performDeferredDestroyWindow(Session session, IWindow client) { 3154 long origId = Binder.clearCallingIdentity(); 3155 3156 try { 3157 synchronized (mWindowMap) { 3158 WindowState win = windowForClientLocked(session, client, false); 3159 if (win == null) { 3160 return; 3161 } 3162 win.mWinAnimator.destroyDeferredSurfaceLocked(); 3163 } 3164 } finally { 3165 Binder.restoreCallingIdentity(origId); 3166 } 3167 } 3168 3169 public boolean outOfMemoryWindow(Session session, IWindow client) { 3170 long origId = Binder.clearCallingIdentity(); 3171 3172 try { 3173 synchronized (mWindowMap) { 3174 WindowState win = windowForClientLocked(session, client, false); 3175 if (win == null) { 3176 return false; 3177 } 3178 return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false); 3179 } 3180 } finally { 3181 Binder.restoreCallingIdentity(origId); 3182 } 3183 } 3184 3185 public void finishDrawingWindow(Session session, IWindow client) { 3186 final long origId = Binder.clearCallingIdentity(); 3187 try { 3188 synchronized (mWindowMap) { 3189 WindowState win = windowForClientLocked(session, client, false); 3190 if (win != null && win.mWinAnimator.finishDrawingLocked()) { 3191 if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 3192 getDefaultDisplayContentLocked().pendingLayoutChanges |= 3193 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 3194 } 3195 final DisplayContent displayContent = win.getDisplayContent(); 3196 if (displayContent != null) { 3197 displayContent.layoutNeeded = true; 3198 } 3199 requestTraversalLocked(); 3200 } 3201 } 3202 } finally { 3203 Binder.restoreCallingIdentity(origId); 3204 } 3205 } 3206 3207 private boolean applyAnimationLocked(AppWindowToken atoken, 3208 WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction) { 3209 // Only apply an animation if the display isn't frozen. If it is 3210 // frozen, there is no reason to animate and it can cause strange 3211 // artifacts when we unfreeze the display if some different animation 3212 // is running. 3213 if (okToDisplay()) { 3214 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 3215 final int width = displayInfo.appWidth; 3216 final int height = displayInfo.appHeight; 3217 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation: atoken=" 3218 + atoken); 3219 3220 // Determine the visible rect to calculate the thumbnail clip 3221 WindowState win = atoken.findMainWindow(); 3222 Rect containingFrame = new Rect(0, 0, width, height); 3223 Rect contentInsets = new Rect(); 3224 boolean isFullScreen = true; 3225 if (win != null) { 3226 if (win.mContainingFrame != null) { 3227 containingFrame.set(win.mContainingFrame); 3228 } 3229 if (win.mContentInsets != null) { 3230 contentInsets.set(win.mContentInsets); 3231 } 3232 isFullScreen = 3233 ((win.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN) == 3234 SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN); 3235 } 3236 3237 if (atoken.mLaunchTaskBehind) { 3238 // Differentiate the two animations. This one which is briefly on the screen 3239 // gets the !enter animation, and the other activity which remains on the 3240 // screen gets the enter animation. Both appear in the mOpeningApps set. 3241 enter = false; 3242 } 3243 Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height, 3244 mCurConfiguration.orientation, containingFrame, contentInsets, isFullScreen, 3245 isVoiceInteraction); 3246 if (a != null) { 3247 if (DEBUG_ANIM) { 3248 RuntimeException e = null; 3249 if (!HIDE_STACK_CRAWLS) { 3250 e = new RuntimeException(); 3251 e.fillInStackTrace(); 3252 } 3253 Slog.v(TAG, "Loaded animation " + a + " for " + atoken, e); 3254 } 3255 atoken.mAppAnimator.setAnimation(a, width, height); 3256 } 3257 } else { 3258 atoken.mAppAnimator.clearAnimation(); 3259 } 3260 3261 return atoken.mAppAnimator.animation != null; 3262 } 3263 3264 // ------------------------------------------------------------- 3265 // Application Window Tokens 3266 // ------------------------------------------------------------- 3267 3268 public void validateAppTokens(int stackId, List<TaskGroup> tasks) { 3269 synchronized (mWindowMap) { 3270 int t = tasks.size() - 1; 3271 if (t < 0) { 3272 Slog.w(TAG, "validateAppTokens: empty task list"); 3273 return; 3274 } 3275 3276 TaskGroup task = tasks.get(0); 3277 int taskId = task.taskId; 3278 Task targetTask = mTaskIdToTask.get(taskId); 3279 DisplayContent displayContent = targetTask.getDisplayContent(); 3280 if (displayContent == null) { 3281 Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId); 3282 return; 3283 } 3284 3285 final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks(); 3286 int taskNdx; 3287 for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) { 3288 AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens; 3289 task = tasks.get(t); 3290 List<IApplicationToken> tokens = task.tokens; 3291 3292 DisplayContent lastDisplayContent = displayContent; 3293 displayContent = mTaskIdToTask.get(taskId).getDisplayContent(); 3294 if (displayContent != lastDisplayContent) { 3295 Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!"); 3296 return; 3297 } 3298 3299 int tokenNdx; 3300 int v; 3301 for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1; 3302 tokenNdx >= 0 && v >= 0; ) { 3303 final AppWindowToken atoken = localTokens.get(tokenNdx); 3304 if (atoken.removed) { 3305 --tokenNdx; 3306 continue; 3307 } 3308 if (tokens.get(v) != atoken.token) { 3309 break; 3310 } 3311 --tokenNdx; 3312 v--; 3313 } 3314 3315 if (tokenNdx >= 0 || v >= 0) { 3316 break; 3317 } 3318 } 3319 3320 if (taskNdx >= 0 || t >= 0) { 3321 Slog.w(TAG, "validateAppTokens: Mismatch! ActivityManager=" + tasks); 3322 Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager=" + localTasks); 3323 Slog.w(TAG, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4)); 3324 } 3325 } 3326 } 3327 3328 public void validateStackOrder(Integer[] remoteStackIds) { 3329 // TODO: 3330 } 3331 3332 boolean checkCallingPermission(String permission, String func) { 3333 // Quick check: if the calling permission is me, it's all okay. 3334 if (Binder.getCallingPid() == Process.myPid()) { 3335 return true; 3336 } 3337 3338 if (mContext.checkCallingPermission(permission) 3339 == PackageManager.PERMISSION_GRANTED) { 3340 return true; 3341 } 3342 String msg = "Permission Denial: " + func + " from pid=" 3343 + Binder.getCallingPid() 3344 + ", uid=" + Binder.getCallingUid() 3345 + " requires " + permission; 3346 Slog.w(TAG, msg); 3347 return false; 3348 } 3349 3350 boolean okToDisplay() { 3351 return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully(); 3352 } 3353 3354 AppWindowToken findAppWindowToken(IBinder token) { 3355 WindowToken wtoken = mTokenMap.get(token); 3356 if (wtoken == null) { 3357 return null; 3358 } 3359 return wtoken.appWindowToken; 3360 } 3361 3362 @Override 3363 public void addWindowToken(IBinder token, int type) { 3364 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3365 "addWindowToken()")) { 3366 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3367 } 3368 3369 synchronized(mWindowMap) { 3370 WindowToken wtoken = mTokenMap.get(token); 3371 if (wtoken != null) { 3372 Slog.w(TAG, "Attempted to add existing input method token: " + token); 3373 return; 3374 } 3375 wtoken = new WindowToken(this, token, type, true); 3376 mTokenMap.put(token, wtoken); 3377 if (type == TYPE_WALLPAPER) { 3378 mWallpaperTokens.add(wtoken); 3379 } 3380 } 3381 } 3382 3383 @Override 3384 public void removeWindowToken(IBinder token) { 3385 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3386 "removeWindowToken()")) { 3387 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3388 } 3389 3390 final long origId = Binder.clearCallingIdentity(); 3391 synchronized(mWindowMap) { 3392 DisplayContent displayContent = null; 3393 WindowToken wtoken = mTokenMap.remove(token); 3394 if (wtoken != null) { 3395 boolean delayed = false; 3396 if (!wtoken.hidden) { 3397 final int N = wtoken.windows.size(); 3398 boolean changed = false; 3399 3400 for (int i=0; i<N; i++) { 3401 WindowState win = wtoken.windows.get(i); 3402 displayContent = win.getDisplayContent(); 3403 3404 if (win.mWinAnimator.isAnimating()) { 3405 delayed = true; 3406 } 3407 3408 if (win.isVisibleNow()) { 3409 win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, 3410 false); 3411 //TODO (multidisplay): Magnification is supported only for the default 3412 if (mAccessibilityController != null && win.isDefaultDisplay()) { 3413 mAccessibilityController.onWindowTransitionLocked(win, 3414 WindowManagerPolicy.TRANSIT_EXIT); 3415 } 3416 changed = true; 3417 if (displayContent != null) { 3418 displayContent.layoutNeeded = true; 3419 } 3420 } 3421 } 3422 3423 wtoken.hidden = true; 3424 3425 if (changed) { 3426 performLayoutAndPlaceSurfacesLocked(); 3427 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, 3428 false /*updateInputWindows*/); 3429 } 3430 3431 if (delayed) { 3432 if (displayContent != null) { 3433 displayContent.mExitingTokens.add(wtoken); 3434 } 3435 } else if (wtoken.windowType == TYPE_WALLPAPER) { 3436 mWallpaperTokens.remove(wtoken); 3437 } 3438 } 3439 3440 mInputMonitor.updateInputWindowsLw(true /*force*/); 3441 } else { 3442 Slog.w(TAG, "Attempted to remove non-existing token: " + token); 3443 } 3444 } 3445 Binder.restoreCallingIdentity(origId); 3446 } 3447 3448 private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) { 3449 if (DEBUG_STACK) Slog.i(TAG, "createTask: taskId=" + taskId + " stackId=" + stackId 3450 + " atoken=" + atoken); 3451 final TaskStack stack = mStackIdToStack.get(stackId); 3452 if (stack == null) { 3453 throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId); 3454 } 3455 EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId); 3456 Task task = new Task(atoken, stack, userId); 3457 mTaskIdToTask.put(taskId, task); 3458 stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */); 3459 return task; 3460 } 3461 3462 @Override 3463 public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId, 3464 int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId, 3465 int configChanges, boolean voiceInteraction, boolean launchTaskBehind) { 3466 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3467 "addAppToken()")) { 3468 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3469 } 3470 3471 // Get the dispatching timeout here while we are not holding any locks so that it 3472 // can be cached by the AppWindowToken. The timeout value is used later by the 3473 // input dispatcher in code that does hold locks. If we did not cache the value 3474 // here we would run the chance of introducing a deadlock between the window manager 3475 // (which holds locks while updating the input dispatcher state) and the activity manager 3476 // (which holds locks while querying the application token). 3477 long inputDispatchingTimeoutNanos; 3478 try { 3479 inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L; 3480 } catch (RemoteException ex) { 3481 Slog.w(TAG, "Could not get dispatching timeout.", ex); 3482 inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 3483 } 3484 3485 synchronized(mWindowMap) { 3486 AppWindowToken atoken = findAppWindowToken(token.asBinder()); 3487 if (atoken != null) { 3488 Slog.w(TAG, "Attempted to add existing app token: " + token); 3489 return; 3490 } 3491 atoken = new AppWindowToken(this, token, voiceInteraction); 3492 atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos; 3493 atoken.groupId = taskId; 3494 atoken.appFullscreen = fullscreen; 3495 atoken.showWhenLocked = showWhenLocked; 3496 atoken.requestedOrientation = requestedOrientation; 3497 atoken.layoutConfigChanges = (configChanges & 3498 (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0; 3499 atoken.mLaunchTaskBehind = launchTaskBehind; 3500 if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken 3501 + " to stack=" + stackId + " task=" + taskId + " at " + addPos); 3502 3503 Task task = mTaskIdToTask.get(taskId); 3504 if (task == null) { 3505 createTask(taskId, stackId, userId, atoken); 3506 } else { 3507 task.addAppToken(addPos, atoken); 3508 } 3509 3510 mTokenMap.put(token.asBinder(), atoken); 3511 3512 // Application tokens start out hidden. 3513 atoken.hidden = true; 3514 atoken.hiddenRequested = true; 3515 3516 //dump(); 3517 } 3518 } 3519 3520 @Override 3521 public void setAppGroupId(IBinder token, int groupId) { 3522 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3523 "setAppGroupId()")) { 3524 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3525 } 3526 3527 synchronized(mWindowMap) { 3528 final AppWindowToken atoken = findAppWindowToken(token); 3529 if (atoken == null) { 3530 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token); 3531 return; 3532 } 3533 final Task oldTask = mTaskIdToTask.get(atoken.groupId); 3534 removeAppFromTaskLocked(atoken); 3535 3536 atoken.groupId = groupId; 3537 Task newTask = mTaskIdToTask.get(groupId); 3538 if (newTask == null) { 3539 newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken); 3540 } else { 3541 newTask.mAppTokens.add(atoken); 3542 } 3543 } 3544 } 3545 3546 public int getOrientationFromWindowsLocked() { 3547 if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 3548 // If the display is frozen, some activities may be in the middle 3549 // of restarting, and thus have removed their old window. If the 3550 // window has the flag to hide the lock screen, then the lock screen 3551 // can re-appear and inflict its own orientation on us. Keep the 3552 // orientation stable until this all settles down. 3553 return mLastWindowForcedOrientation; 3554 } 3555 3556 // TODO(multidisplay): Change to the correct display. 3557 final WindowList windows = getDefaultWindowListLocked(); 3558 int pos = windows.size() - 1; 3559 while (pos >= 0) { 3560 WindowState win = windows.get(pos); 3561 pos--; 3562 if (win.mAppToken != null) { 3563 // We hit an application window. so the orientation will be determined by the 3564 // app window. No point in continuing further. 3565 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3566 } 3567 if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) { 3568 continue; 3569 } 3570 int req = win.mAttrs.screenOrientation; 3571 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) || 3572 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){ 3573 continue; 3574 } 3575 3576 if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req); 3577 return (mLastWindowForcedOrientation=req); 3578 } 3579 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3580 } 3581 3582 public int getOrientationFromAppTokensLocked() { 3583 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3584 boolean findingBehind = false; 3585 boolean lastFullscreen = false; 3586 // TODO: Multi window. 3587 DisplayContent displayContent = getDefaultDisplayContentLocked(); 3588 final ArrayList<Task> tasks = displayContent.getTasks(); 3589 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 3590 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 3591 final int firstToken = tokens.size() - 1; 3592 for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) { 3593 final AppWindowToken atoken = tokens.get(tokenNdx); 3594 3595 if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken); 3596 3597 // if we're about to tear down this window and not seek for 3598 // the behind activity, don't use it for orientation 3599 if (!findingBehind 3600 && (!atoken.hidden && atoken.hiddenRequested)) { 3601 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken 3602 + " -- going to hide"); 3603 continue; 3604 } 3605 3606 if (tokenNdx == firstToken) { 3607 // If we have hit a new Task, and the bottom 3608 // of the previous group didn't explicitly say to use 3609 // the orientation behind it, and the last app was 3610 // full screen, then we'll stick with the 3611 // user's orientation. 3612 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND 3613 && lastFullscreen) { 3614 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3615 + " -- end of group, return " + lastOrientation); 3616 return lastOrientation; 3617 } 3618 } 3619 3620 // We ignore any hidden applications on the top. 3621 if (atoken.hiddenRequested || atoken.willBeHidden) { 3622 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken 3623 + " -- hidden on top"); 3624 continue; 3625 } 3626 3627 if (tokenNdx == 0) { 3628 // Last token in this task. 3629 lastOrientation = atoken.requestedOrientation; 3630 } 3631 3632 int or = atoken.requestedOrientation; 3633 // If this application is fullscreen, and didn't explicitly say 3634 // to use the orientation behind it, then just take whatever 3635 // orientation it has and ignores whatever is under it. 3636 lastFullscreen = atoken.appFullscreen; 3637 if (lastFullscreen 3638 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { 3639 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3640 + " -- full screen, return " + or); 3641 return or; 3642 } 3643 // If this application has requested an explicit orientation, 3644 // then use it. 3645 if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 3646 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { 3647 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3648 + " -- explicitly set, return " + or); 3649 return or; 3650 } 3651 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND); 3652 } 3653 } 3654 if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation"); 3655 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3656 } 3657 3658 @Override 3659 public Configuration updateOrientationFromAppTokens( 3660 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3661 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3662 "updateOrientationFromAppTokens()")) { 3663 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3664 } 3665 3666 Configuration config = null; 3667 long ident = Binder.clearCallingIdentity(); 3668 3669 synchronized(mWindowMap) { 3670 config = updateOrientationFromAppTokensLocked(currentConfig, 3671 freezeThisOneIfNeeded); 3672 } 3673 3674 Binder.restoreCallingIdentity(ident); 3675 return config; 3676 } 3677 3678 private Configuration updateOrientationFromAppTokensLocked( 3679 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3680 Configuration config = null; 3681 3682 if (updateOrientationFromAppTokensLocked(false)) { 3683 if (freezeThisOneIfNeeded != null) { 3684 AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded); 3685 if (atoken != null) { 3686 startAppFreezingScreenLocked(atoken); 3687 } 3688 } 3689 config = computeNewConfigurationLocked(); 3690 3691 } else if (currentConfig != null) { 3692 // No obvious action we need to take, but if our current 3693 // state mismatches the activity manager's, update it, 3694 // disregarding font scale, which should remain set to 3695 // the value of the previous configuration. 3696 mTempConfiguration.setToDefaults(); 3697 mTempConfiguration.fontScale = currentConfig.fontScale; 3698 if (computeScreenConfigurationLocked(mTempConfiguration)) { 3699 if (currentConfig.diff(mTempConfiguration) != 0) { 3700 mWaitingForConfig = true; 3701 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 3702 displayContent.layoutNeeded = true; 3703 int anim[] = new int[2]; 3704 if (displayContent.isDimming()) { 3705 anim[0] = anim[1] = 0; 3706 } else { 3707 mPolicy.selectRotationAnimationLw(anim); 3708 } 3709 startFreezingDisplayLocked(false, anim[0], anim[1]); 3710 config = new Configuration(mTempConfiguration); 3711 } 3712 } 3713 } 3714 3715 return config; 3716 } 3717 3718 /* 3719 * Determine the new desired orientation of the display, returning 3720 * a non-null new Configuration if it has changed from the current 3721 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL 3722 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE 3723 * SCREEN. This will typically be done for you if you call 3724 * sendNewConfiguration(). 3725 * 3726 * The orientation is computed from non-application windows first. If none of 3727 * the non-application windows specify orientation, the orientation is computed from 3728 * application tokens. 3729 * @see android.view.IWindowManager#updateOrientationFromAppTokens( 3730 * android.os.IBinder) 3731 */ 3732 boolean updateOrientationFromAppTokensLocked(boolean inTransaction) { 3733 long ident = Binder.clearCallingIdentity(); 3734 try { 3735 int req = getOrientationFromWindowsLocked(); 3736 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) { 3737 req = getOrientationFromAppTokensLocked(); 3738 } 3739 3740 if (req != mForcedAppOrientation) { 3741 mForcedAppOrientation = req; 3742 //send a message to Policy indicating orientation change to take 3743 //action like disabling/enabling sensors etc., 3744 mPolicy.setCurrentOrientationLw(req); 3745 if (updateRotationUncheckedLocked(inTransaction)) { 3746 // changed 3747 return true; 3748 } 3749 } 3750 3751 return false; 3752 } finally { 3753 Binder.restoreCallingIdentity(ident); 3754 } 3755 } 3756 3757 @Override 3758 public void setNewConfiguration(Configuration config) { 3759 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3760 "setNewConfiguration()")) { 3761 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3762 } 3763 3764 synchronized(mWindowMap) { 3765 mCurConfiguration = new Configuration(config); 3766 if (mWaitingForConfig) { 3767 mWaitingForConfig = false; 3768 mLastFinishedFreezeSource = "new-config"; 3769 } 3770 performLayoutAndPlaceSurfacesLocked(); 3771 } 3772 } 3773 3774 @Override 3775 public void setAppOrientation(IApplicationToken token, int requestedOrientation) { 3776 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3777 "setAppOrientation()")) { 3778 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3779 } 3780 3781 synchronized(mWindowMap) { 3782 AppWindowToken atoken = findAppWindowToken(token.asBinder()); 3783 if (atoken == null) { 3784 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token); 3785 return; 3786 } 3787 3788 atoken.requestedOrientation = requestedOrientation; 3789 } 3790 } 3791 3792 @Override 3793 public int getAppOrientation(IApplicationToken token) { 3794 synchronized(mWindowMap) { 3795 AppWindowToken wtoken = findAppWindowToken(token.asBinder()); 3796 if (wtoken == null) { 3797 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3798 } 3799 3800 return wtoken.requestedOrientation; 3801 } 3802 } 3803 3804 /** Call while in a Surface transaction. */ 3805 void setFocusedStackLayer() { 3806 mFocusedStackLayer = 0; 3807 if (mFocusedApp != null) { 3808 final WindowList windows = mFocusedApp.allAppWindows; 3809 for (int i = windows.size() - 1; i >= 0; --i) { 3810 final WindowState win = windows.get(i); 3811 final int animLayer = win.mWinAnimator.mAnimLayer; 3812 if (win.mAttachedWindow == null && win.isVisibleLw() && 3813 animLayer > mFocusedStackLayer) { 3814 mFocusedStackLayer = animLayer + LAYER_OFFSET_FOCUSED_STACK; 3815 } 3816 } 3817 } 3818 if (DEBUG_LAYERS) Slog.v(TAG, "Setting FocusedStackFrame to layer=" + 3819 mFocusedStackLayer); 3820 mFocusedStackFrame.setLayer(mFocusedStackLayer); 3821 } 3822 3823 void setFocusedStackFrame() { 3824 final TaskStack stack; 3825 if (mFocusedApp != null) { 3826 Task task = mTaskIdToTask.get(mFocusedApp.groupId); 3827 stack = task.mStack; 3828 final DisplayContent displayContent = task.getDisplayContent(); 3829 if (displayContent != null) { 3830 displayContent.setTouchExcludeRegion(stack); 3831 } 3832 } else { 3833 stack = null; 3834 } 3835 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame"); 3836 SurfaceControl.openTransaction(); 3837 try { 3838 if (stack == null) { 3839 mFocusedStackFrame.setVisibility(false); 3840 } else { 3841 mFocusedStackFrame.setBounds(stack); 3842 final boolean multipleStacks = !stack.isFullscreen(); 3843 mFocusedStackFrame.setVisibility(multipleStacks); 3844 } 3845 } finally { 3846 SurfaceControl.closeTransaction(); 3847 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame"); 3848 } 3849 } 3850 3851 @Override 3852 public void setFocusedApp(IBinder token, boolean moveFocusNow) { 3853 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3854 "setFocusedApp()")) { 3855 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3856 } 3857 3858 synchronized(mWindowMap) { 3859 final AppWindowToken newFocus; 3860 if (token == null) { 3861 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp); 3862 newFocus = null; 3863 } else { 3864 newFocus = findAppWindowToken(token); 3865 if (newFocus == null) { 3866 Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token); 3867 } 3868 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus 3869 + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow); 3870 } 3871 3872 final boolean changed = mFocusedApp != newFocus; 3873 if (changed) { 3874 mFocusedApp = newFocus; 3875 mInputMonitor.setFocusedAppLw(null); 3876 } 3877 3878 if (moveFocusNow && changed) { 3879 final long origId = Binder.clearCallingIdentity(); 3880 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 3881 Binder.restoreCallingIdentity(origId); 3882 } 3883 } 3884 } 3885 3886 @Override 3887 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) { 3888 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3889 "prepareAppTransition()")) { 3890 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3891 } 3892 3893 synchronized(mWindowMap) { 3894 if (DEBUG_APP_TRANSITIONS) Slog.v( 3895 TAG, "Prepare app transition: transit=" + transit 3896 + " " + mAppTransition 3897 + " alwaysKeepCurrent=" + alwaysKeepCurrent 3898 + " Callers=" + Debug.getCallers(3)); 3899 if (!mAppTransition.isTransitionSet() || mAppTransition.isTransitionNone()) { 3900 mAppTransition.setAppTransition(transit); 3901 } else if (!alwaysKeepCurrent) { 3902 if (transit == AppTransition.TRANSIT_TASK_OPEN 3903 && mAppTransition.isTransitionEqual( 3904 AppTransition.TRANSIT_TASK_CLOSE)) { 3905 // Opening a new task always supersedes a close for the anim. 3906 mAppTransition.setAppTransition(transit); 3907 } else if (transit == AppTransition.TRANSIT_ACTIVITY_OPEN 3908 && mAppTransition.isTransitionEqual( 3909 AppTransition.TRANSIT_ACTIVITY_CLOSE)) { 3910 // Opening a new activity always supersedes a close for the anim. 3911 mAppTransition.setAppTransition(transit); 3912 } 3913 } 3914 if (okToDisplay()) { 3915 mAppTransition.prepare(); 3916 mStartingIconInTransition = false; 3917 mSkipAppTransitionAnimation = false; 3918 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 3919 mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000); 3920 } 3921 } 3922 } 3923 3924 @Override 3925 public int getPendingAppTransition() { 3926 return mAppTransition.getAppTransition(); 3927 } 3928 3929 @Override 3930 public void overridePendingAppTransition(String packageName, 3931 int enterAnim, int exitAnim, IRemoteCallback startedCallback) { 3932 synchronized(mWindowMap) { 3933 mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim, 3934 startedCallback); 3935 } 3936 } 3937 3938 @Override 3939 public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, 3940 int startHeight) { 3941 synchronized(mWindowMap) { 3942 mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth, 3943 startHeight); 3944 } 3945 } 3946 3947 @Override 3948 public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, 3949 int startY, IRemoteCallback startedCallback, boolean scaleUp) { 3950 synchronized(mWindowMap) { 3951 mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY, 3952 startedCallback, scaleUp); 3953 } 3954 } 3955 3956 @Override 3957 public void executeAppTransition() { 3958 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3959 "executeAppTransition()")) { 3960 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3961 } 3962 3963 synchronized(mWindowMap) { 3964 if (DEBUG_APP_TRANSITIONS) Slog.w(TAG, "Execute app transition: " + mAppTransition, 3965 new RuntimeException("here").fillInStackTrace()); 3966 if (mAppTransition.isTransitionSet()) { 3967 mAppTransition.setReady(); 3968 final long origId = Binder.clearCallingIdentity(); 3969 try { 3970 performLayoutAndPlaceSurfacesLocked(); 3971 } finally { 3972 Binder.restoreCallingIdentity(origId); 3973 } 3974 } 3975 } 3976 } 3977 3978 @Override 3979 public void setAppStartingWindow(IBinder token, String pkg, 3980 int theme, CompatibilityInfo compatInfo, 3981 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, 3982 int windowFlags, IBinder transferFrom, boolean createIfNeeded) { 3983 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3984 "setAppStartingWindow()")) { 3985 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3986 } 3987 3988 synchronized(mWindowMap) { 3989 if (DEBUG_STARTING_WINDOW) Slog.v( 3990 TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg 3991 + " transferFrom=" + transferFrom); 3992 3993 AppWindowToken wtoken = findAppWindowToken(token); 3994 if (wtoken == null) { 3995 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token); 3996 return; 3997 } 3998 3999 // If the display is frozen, we won't do anything until the 4000 // actual window is displayed so there is no reason to put in 4001 // the starting window. 4002 if (!okToDisplay()) { 4003 return; 4004 } 4005 4006 if (wtoken.startingData != null) { 4007 return; 4008 } 4009 4010 if (transferFrom != null) { 4011 AppWindowToken ttoken = findAppWindowToken(transferFrom); 4012 if (ttoken != null) { 4013 WindowState startingWindow = ttoken.startingWindow; 4014 if (startingWindow != null) { 4015 if (mStartingIconInTransition) { 4016 // In this case, the starting icon has already 4017 // been displayed, so start letting windows get 4018 // shown immediately without any more transitions. 4019 mSkipAppTransitionAnimation = true; 4020 } 4021 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4022 "Moving existing starting " + startingWindow + " from " + ttoken 4023 + " to " + wtoken); 4024 final long origId = Binder.clearCallingIdentity(); 4025 4026 // Transfer the starting window over to the new 4027 // token. 4028 wtoken.startingData = ttoken.startingData; 4029 wtoken.startingView = ttoken.startingView; 4030 wtoken.startingDisplayed = ttoken.startingDisplayed; 4031 ttoken.startingDisplayed = false; 4032 wtoken.startingWindow = startingWindow; 4033 wtoken.reportedVisible = ttoken.reportedVisible; 4034 ttoken.startingData = null; 4035 ttoken.startingView = null; 4036 ttoken.startingWindow = null; 4037 ttoken.startingMoved = true; 4038 startingWindow.mToken = wtoken; 4039 startingWindow.mRootToken = wtoken; 4040 startingWindow.mAppToken = wtoken; 4041 startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator; 4042 4043 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) { 4044 Slog.v(TAG, "Removing starting window: " + startingWindow); 4045 } 4046 startingWindow.getWindowList().remove(startingWindow); 4047 mWindowsChanged = true; 4048 if (DEBUG_ADD_REMOVE) Slog.v(TAG, 4049 "Removing starting " + startingWindow + " from " + ttoken); 4050 ttoken.windows.remove(startingWindow); 4051 ttoken.allAppWindows.remove(startingWindow); 4052 addWindowToListInOrderLocked(startingWindow, true); 4053 4054 // Propagate other interesting state between the 4055 // tokens. If the old token is displayed, we should 4056 // immediately force the new one to be displayed. If 4057 // it is animating, we need to move that animation to 4058 // the new one. 4059 if (ttoken.allDrawn) { 4060 wtoken.allDrawn = true; 4061 wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn; 4062 } 4063 if (ttoken.firstWindowDrawn) { 4064 wtoken.firstWindowDrawn = true; 4065 } 4066 if (!ttoken.hidden) { 4067 wtoken.hidden = false; 4068 wtoken.hiddenRequested = false; 4069 wtoken.willBeHidden = false; 4070 } 4071 if (wtoken.clientHidden != ttoken.clientHidden) { 4072 wtoken.clientHidden = ttoken.clientHidden; 4073 wtoken.sendAppVisibilityToClients(); 4074 } 4075 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4076 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4077 if (tAppAnimator.animation != null) { 4078 wAppAnimator.animation = tAppAnimator.animation; 4079 wAppAnimator.animating = tAppAnimator.animating; 4080 wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment; 4081 tAppAnimator.animation = null; 4082 tAppAnimator.animLayerAdjustment = 0; 4083 wAppAnimator.updateLayers(); 4084 tAppAnimator.updateLayers(); 4085 } 4086 4087 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4088 true /*updateInputWindows*/); 4089 getDefaultDisplayContentLocked().layoutNeeded = true; 4090 performLayoutAndPlaceSurfacesLocked(); 4091 Binder.restoreCallingIdentity(origId); 4092 return; 4093 } else if (ttoken.startingData != null) { 4094 // The previous app was getting ready to show a 4095 // starting window, but hasn't yet done so. Steal it! 4096 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4097 "Moving pending starting from " + ttoken 4098 + " to " + wtoken); 4099 wtoken.startingData = ttoken.startingData; 4100 ttoken.startingData = null; 4101 ttoken.startingMoved = true; 4102 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4103 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4104 // want to process the message ASAP, before any other queued 4105 // messages. 4106 mH.sendMessageAtFrontOfQueue(m); 4107 return; 4108 } 4109 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4110 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4111 if (tAppAnimator.thumbnail != null) { 4112 // The old token is animating with a thumbnail, transfer 4113 // that to the new token. 4114 if (wAppAnimator.thumbnail != null) { 4115 wAppAnimator.thumbnail.destroy(); 4116 } 4117 wAppAnimator.thumbnail = tAppAnimator.thumbnail; 4118 wAppAnimator.thumbnailX = tAppAnimator.thumbnailX; 4119 wAppAnimator.thumbnailY = tAppAnimator.thumbnailY; 4120 wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer; 4121 wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation; 4122 tAppAnimator.thumbnail = null; 4123 } 4124 } 4125 } 4126 4127 // There is no existing starting window, and the caller doesn't 4128 // want us to create one, so that's it! 4129 if (!createIfNeeded) { 4130 return; 4131 } 4132 4133 // If this is a translucent window, then don't 4134 // show a starting window -- the current effect (a full-screen 4135 // opaque starting window that fades away to the real contents 4136 // when it is ready) does not work for this. 4137 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x" 4138 + Integer.toHexString(theme)); 4139 if (theme != 0) { 4140 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme, 4141 com.android.internal.R.styleable.Window, mCurrentUserId); 4142 if (ent == null) { 4143 // Whoops! App doesn't exist. Um. Okay. We'll just 4144 // pretend like we didn't see that. 4145 return; 4146 } 4147 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent=" 4148 + ent.array.getBoolean( 4149 com.android.internal.R.styleable.Window_windowIsTranslucent, false) 4150 + " Floating=" 4151 + ent.array.getBoolean( 4152 com.android.internal.R.styleable.Window_windowIsFloating, false) 4153 + " ShowWallpaper=" 4154 + ent.array.getBoolean( 4155 com.android.internal.R.styleable.Window_windowShowWallpaper, false)); 4156 if (ent.array.getBoolean( 4157 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) { 4158 return; 4159 } 4160 if (ent.array.getBoolean( 4161 com.android.internal.R.styleable.Window_windowIsFloating, false)) { 4162 return; 4163 } 4164 if (ent.array.getBoolean( 4165 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) { 4166 if (mWallpaperTarget == null) { 4167 // If this theme is requesting a wallpaper, and the wallpaper 4168 // is not curently visible, then this effectively serves as 4169 // an opaque window and our starting window transition animation 4170 // can still work. We just need to make sure the starting window 4171 // is also showing the wallpaper. 4172 windowFlags |= FLAG_SHOW_WALLPAPER; 4173 } else { 4174 return; 4175 } 4176 } 4177 } 4178 4179 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData"); 4180 mStartingIconInTransition = true; 4181 wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel, 4182 labelRes, icon, logo, windowFlags); 4183 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4184 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4185 // want to process the message ASAP, before any other queued 4186 // messages. 4187 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING"); 4188 mH.sendMessageAtFrontOfQueue(m); 4189 } 4190 } 4191 4192 public void removeAppStartingWindow(IBinder token) { 4193 synchronized (mWindowMap) { 4194 AppWindowToken wtoken = mTokenMap.get(token).appWindowToken; 4195 if (wtoken.startingWindow != null) { 4196 scheduleRemoveStartingWindow(wtoken); 4197 } 4198 } 4199 } 4200 4201 @Override 4202 public void setAppWillBeHidden(IBinder token) { 4203 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4204 "setAppWillBeHidden()")) { 4205 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4206 } 4207 4208 AppWindowToken wtoken; 4209 4210 synchronized(mWindowMap) { 4211 wtoken = findAppWindowToken(token); 4212 if (wtoken == null) { 4213 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token); 4214 return; 4215 } 4216 wtoken.willBeHidden = true; 4217 } 4218 } 4219 4220 public void setAppFullscreen(IBinder token, boolean toOpaque) { 4221 AppWindowToken atoken = findAppWindowToken(token); 4222 if (atoken != null) { 4223 atoken.appFullscreen = toOpaque; 4224 // When making translucent, wait until windows below have been drawn. 4225 if (toOpaque) { 4226 // Making opaque so do it now. 4227 setWindowOpaque(token, true); 4228 } 4229 requestTraversal(); 4230 } 4231 } 4232 4233 public void setWindowOpaque(IBinder token, boolean isOpaque) { 4234 AppWindowToken wtoken = findAppWindowToken(token); 4235 if (wtoken != null) { 4236 WindowState win = wtoken.findMainWindow(); 4237 if (win != null) { 4238 win.mWinAnimator.setOpaque(isOpaque); 4239 } 4240 } 4241 } 4242 4243 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp, 4244 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) { 4245 boolean delayed = false; 4246 4247 if (wtoken.clientHidden == visible) { 4248 wtoken.clientHidden = !visible; 4249 wtoken.sendAppVisibilityToClients(); 4250 } 4251 4252 wtoken.willBeHidden = false; 4253 if (wtoken.hidden == visible) { 4254 boolean changed = false; 4255 if (DEBUG_APP_TRANSITIONS) Slog.v( 4256 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden 4257 + " performLayout=" + performLayout); 4258 4259 boolean runningAppAnimation = false; 4260 4261 if (transit != AppTransition.TRANSIT_UNSET) { 4262 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { 4263 wtoken.mAppAnimator.animation = null; 4264 } 4265 if (applyAnimationLocked(wtoken, lp, transit, visible, isVoiceInteraction)) { 4266 delayed = runningAppAnimation = true; 4267 } 4268 WindowState window = wtoken.findMainWindow(); 4269 //TODO (multidisplay): Magnification is supported only for the default display. 4270 if (window != null && mAccessibilityController != null 4271 && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 4272 mAccessibilityController.onAppWindowTransitionLocked(window, transit); 4273 } 4274 changed = true; 4275 } 4276 4277 final int N = wtoken.allAppWindows.size(); 4278 for (int i=0; i<N; i++) { 4279 WindowState win = wtoken.allAppWindows.get(i); 4280 if (win == wtoken.startingWindow) { 4281 continue; 4282 } 4283 4284 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible()); 4285 //win.dump(" "); 4286 if (visible) { 4287 if (!win.isVisibleNow()) { 4288 if (!runningAppAnimation) { 4289 win.mWinAnimator.applyAnimationLocked( 4290 WindowManagerPolicy.TRANSIT_ENTER, true); 4291 //TODO (multidisplay): Magnification is supported only for the default 4292 if (mAccessibilityController != null 4293 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4294 mAccessibilityController.onWindowTransitionLocked(win, 4295 WindowManagerPolicy.TRANSIT_ENTER); 4296 } 4297 } 4298 changed = true; 4299 final DisplayContent displayContent = win.getDisplayContent(); 4300 if (displayContent != null) { 4301 displayContent.layoutNeeded = true; 4302 } 4303 } 4304 } else if (win.isVisibleNow()) { 4305 if (!runningAppAnimation) { 4306 win.mWinAnimator.applyAnimationLocked( 4307 WindowManagerPolicy.TRANSIT_EXIT, false); 4308 //TODO (multidisplay): Magnification is supported only for the default 4309 if (mAccessibilityController != null 4310 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4311 mAccessibilityController.onWindowTransitionLocked(win, 4312 WindowManagerPolicy.TRANSIT_EXIT); 4313 } 4314 } 4315 changed = true; 4316 final DisplayContent displayContent = win.getDisplayContent(); 4317 if (displayContent != null) { 4318 displayContent.layoutNeeded = true; 4319 } 4320 } 4321 } 4322 4323 wtoken.hidden = wtoken.hiddenRequested = !visible; 4324 if (!visible) { 4325 unsetAppFreezingScreenLocked(wtoken, true, true); 4326 } else { 4327 // If we are being set visible, and the starting window is 4328 // not yet displayed, then make sure it doesn't get displayed. 4329 WindowState swin = wtoken.startingWindow; 4330 if (swin != null && !swin.isDrawnLw()) { 4331 swin.mPolicyVisibility = false; 4332 swin.mPolicyVisibilityAfterAnim = false; 4333 } 4334 } 4335 4336 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken 4337 + ": hidden=" + wtoken.hidden + " hiddenRequested=" 4338 + wtoken.hiddenRequested); 4339 4340 if (changed) { 4341 mInputMonitor.setUpdateInputWindowsNeededLw(); 4342 if (performLayout) { 4343 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4344 false /*updateInputWindows*/); 4345 performLayoutAndPlaceSurfacesLocked(); 4346 } 4347 mInputMonitor.updateInputWindowsLw(false /*force*/); 4348 } 4349 } 4350 4351 if (wtoken.mAppAnimator.animation != null) { 4352 delayed = true; 4353 } 4354 4355 for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) { 4356 if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) { 4357 delayed = true; 4358 } 4359 } 4360 4361 return delayed; 4362 } 4363 4364 @Override 4365 public void setAppVisibility(IBinder token, boolean visible) { 4366 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4367 "setAppVisibility()")) { 4368 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4369 } 4370 4371 AppWindowToken wtoken; 4372 4373 synchronized(mWindowMap) { 4374 wtoken = findAppWindowToken(token); 4375 if (wtoken == null) { 4376 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token); 4377 return; 4378 } 4379 4380 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG, "setAppVisibility(" + 4381 token + ", visible=" + visible + "): " + mAppTransition + 4382 " hidden=" + wtoken.hidden + " hiddenRequested=" + 4383 wtoken.hiddenRequested, HIDE_STACK_CRAWLS ? 4384 null : new RuntimeException("here").fillInStackTrace()); 4385 4386 // If we are preparing an app transition, then delay changing 4387 // the visibility of this token until we execute that transition. 4388 if (okToDisplay() && mAppTransition.isTransitionSet()) { 4389 wtoken.hiddenRequested = !visible; 4390 4391 if (!wtoken.startingDisplayed) { 4392 if (DEBUG_APP_TRANSITIONS) Slog.v( 4393 TAG, "Setting dummy animation on: " + wtoken); 4394 wtoken.mAppAnimator.setDummyAnimation(); 4395 } 4396 mOpeningApps.remove(wtoken); 4397 mClosingApps.remove(wtoken); 4398 wtoken.waitingToShow = wtoken.waitingToHide = false; 4399 wtoken.inPendingTransaction = true; 4400 if (visible) { 4401 mOpeningApps.add(wtoken); 4402 wtoken.startingMoved = false; 4403 4404 // If the token is currently hidden (should be the 4405 // common case), then we need to set up to wait for 4406 // its windows to be ready. 4407 if (wtoken.hidden) { 4408 wtoken.allDrawn = false; 4409 wtoken.deferClearAllDrawn = false; 4410 wtoken.waitingToShow = true; 4411 4412 if (wtoken.clientHidden) { 4413 // In the case where we are making an app visible 4414 // but holding off for a transition, we still need 4415 // to tell the client to make its windows visible so 4416 // they get drawn. Otherwise, we will wait on 4417 // performing the transition until all windows have 4418 // been drawn, they never will be, and we are sad. 4419 wtoken.clientHidden = false; 4420 wtoken.sendAppVisibilityToClients(); 4421 } 4422 } 4423 } else { 4424 mClosingApps.add(wtoken); 4425 4426 // If the token is currently visible (should be the 4427 // common case), then set up to wait for it to be hidden. 4428 if (!wtoken.hidden) { 4429 wtoken.waitingToHide = true; 4430 } 4431 } 4432 if (mAppTransition.getAppTransition() == AppTransition.TRANSIT_TASK_OPEN_BEHIND) { 4433 // We're launchingBehind, add the launching activity to mOpeningApps. 4434 final WindowState win = 4435 findFocusedWindowLocked(getDefaultDisplayContentLocked()); 4436 if (win != null) { 4437 final AppWindowToken focusedToken = win.mAppToken; 4438 if (focusedToken != null) { 4439 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "TRANSIT_TASK_OPEN_BEHIND, " + 4440 " adding " + focusedToken + " to mOpeningApps"); 4441 // Force animation to be loaded. 4442 focusedToken.hidden = true; 4443 mOpeningApps.add(focusedToken); 4444 } 4445 } 4446 } 4447 return; 4448 } 4449 4450 final long origId = Binder.clearCallingIdentity(); 4451 setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET, 4452 true, wtoken.voiceInteraction); 4453 wtoken.updateReportedVisibilityLocked(); 4454 Binder.restoreCallingIdentity(origId); 4455 } 4456 } 4457 4458 void unsetAppFreezingScreenLocked(AppWindowToken wtoken, 4459 boolean unfreezeSurfaceNow, boolean force) { 4460 if (wtoken.mAppAnimator.freezingScreen) { 4461 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken 4462 + " force=" + force); 4463 final int N = wtoken.allAppWindows.size(); 4464 boolean unfrozeWindows = false; 4465 for (int i=0; i<N; i++) { 4466 WindowState w = wtoken.allAppWindows.get(i); 4467 if (w.mAppFreezing) { 4468 w.mAppFreezing = false; 4469 if (w.mHasSurface && !w.mOrientationChanging) { 4470 if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w); 4471 w.mOrientationChanging = true; 4472 mInnerFields.mOrientationChangeComplete = false; 4473 } 4474 w.mLastFreezeDuration = 0; 4475 unfrozeWindows = true; 4476 final DisplayContent displayContent = w.getDisplayContent(); 4477 if (displayContent != null) { 4478 displayContent.layoutNeeded = true; 4479 } 4480 } 4481 } 4482 if (force || unfrozeWindows) { 4483 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken); 4484 wtoken.mAppAnimator.freezingScreen = false; 4485 wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime() 4486 - mDisplayFreezeTime); 4487 mAppsFreezingScreen--; 4488 mLastFinishedFreezeSource = wtoken; 4489 } 4490 if (unfreezeSurfaceNow) { 4491 if (unfrozeWindows) { 4492 performLayoutAndPlaceSurfacesLocked(); 4493 } 4494 stopFreezingDisplayLocked(); 4495 } 4496 } 4497 } 4498 4499 private void startAppFreezingScreenLocked(AppWindowToken wtoken) { 4500 if (DEBUG_ORIENTATION) { 4501 RuntimeException e = null; 4502 if (!HIDE_STACK_CRAWLS) { 4503 e = new RuntimeException(); 4504 e.fillInStackTrace(); 4505 } 4506 Slog.i(TAG, "Set freezing of " + wtoken.appToken 4507 + ": hidden=" + wtoken.hidden + " freezing=" 4508 + wtoken.mAppAnimator.freezingScreen, e); 4509 } 4510 if (!wtoken.hiddenRequested) { 4511 if (!wtoken.mAppAnimator.freezingScreen) { 4512 wtoken.mAppAnimator.freezingScreen = true; 4513 wtoken.mAppAnimator.lastFreezeDuration = 0; 4514 mAppsFreezingScreen++; 4515 if (mAppsFreezingScreen == 1) { 4516 startFreezingDisplayLocked(false, 0, 0); 4517 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 4518 mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000); 4519 } 4520 } 4521 final int N = wtoken.allAppWindows.size(); 4522 for (int i=0; i<N; i++) { 4523 WindowState w = wtoken.allAppWindows.get(i); 4524 w.mAppFreezing = true; 4525 } 4526 } 4527 } 4528 4529 @Override 4530 public void startAppFreezingScreen(IBinder token, int configChanges) { 4531 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4532 "setAppFreezingScreen()")) { 4533 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4534 } 4535 4536 synchronized(mWindowMap) { 4537 if (configChanges == 0 && okToDisplay()) { 4538 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token); 4539 return; 4540 } 4541 4542 AppWindowToken wtoken = findAppWindowToken(token); 4543 if (wtoken == null || wtoken.appToken == null) { 4544 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken); 4545 return; 4546 } 4547 final long origId = Binder.clearCallingIdentity(); 4548 startAppFreezingScreenLocked(wtoken); 4549 Binder.restoreCallingIdentity(origId); 4550 } 4551 } 4552 4553 @Override 4554 public void stopAppFreezingScreen(IBinder token, boolean force) { 4555 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4556 "setAppFreezingScreen()")) { 4557 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4558 } 4559 4560 synchronized(mWindowMap) { 4561 AppWindowToken wtoken = findAppWindowToken(token); 4562 if (wtoken == null || wtoken.appToken == null) { 4563 return; 4564 } 4565 final long origId = Binder.clearCallingIdentity(); 4566 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token 4567 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen); 4568 unsetAppFreezingScreenLocked(wtoken, true, force); 4569 Binder.restoreCallingIdentity(origId); 4570 } 4571 } 4572 4573 void removeAppFromTaskLocked(AppWindowToken wtoken) { 4574 final Task task = mTaskIdToTask.get(wtoken.groupId); 4575 if (task != null) { 4576 if (!task.removeAppToken(wtoken)) { 4577 Slog.e(TAG, "removeAppFromTaskLocked: token=" + wtoken + " not found."); 4578 } 4579 } 4580 } 4581 4582 @Override 4583 public void removeAppToken(IBinder token) { 4584 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4585 "removeAppToken()")) { 4586 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4587 } 4588 4589 AppWindowToken wtoken = null; 4590 AppWindowToken startingToken = null; 4591 boolean delayed = false; 4592 4593 final long origId = Binder.clearCallingIdentity(); 4594 synchronized(mWindowMap) { 4595 WindowToken basewtoken = mTokenMap.remove(token); 4596 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) { 4597 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken); 4598 delayed = setTokenVisibilityLocked(wtoken, null, false, 4599 AppTransition.TRANSIT_UNSET, true, wtoken.voiceInteraction); 4600 wtoken.inPendingTransaction = false; 4601 mOpeningApps.remove(wtoken); 4602 wtoken.waitingToShow = false; 4603 if (mClosingApps.contains(wtoken)) { 4604 delayed = true; 4605 } else if (mAppTransition.isTransitionSet()) { 4606 mClosingApps.add(wtoken); 4607 wtoken.waitingToHide = true; 4608 delayed = true; 4609 } 4610 if (DEBUG_APP_TRANSITIONS) Slog.v( 4611 TAG, "Removing app " + wtoken + " delayed=" + delayed 4612 + " animation=" + wtoken.mAppAnimator.animation 4613 + " animating=" + wtoken.mAppAnimator.animating); 4614 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: " 4615 + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4)); 4616 final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack; 4617 if (delayed) { 4618 // set the token aside because it has an active animation to be finished 4619 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4620 "removeAppToken make exiting: " + wtoken); 4621 stack.mExitingAppTokens.add(wtoken); 4622 wtoken.mDeferRemoval = true; 4623 } else { 4624 // Make sure there is no animation running on this token, 4625 // so any windows associated with it will be removed as 4626 // soon as their animations are complete 4627 wtoken.mAppAnimator.clearAnimation(); 4628 wtoken.mAppAnimator.animating = false; 4629 removeAppFromTaskLocked(wtoken); 4630 } 4631 4632 wtoken.removed = true; 4633 if (wtoken.startingData != null) { 4634 startingToken = wtoken; 4635 } 4636 unsetAppFreezingScreenLocked(wtoken, true, true); 4637 if (mFocusedApp == wtoken) { 4638 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Removing focused app token:" + wtoken); 4639 mFocusedApp = null; 4640 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 4641 mInputMonitor.setFocusedAppLw(null); 4642 } 4643 } else { 4644 Slog.w(TAG, "Attempted to remove non-existing app token: " + token); 4645 } 4646 4647 if (!delayed && wtoken != null) { 4648 wtoken.updateReportedVisibilityLocked(); 4649 } 4650 } 4651 Binder.restoreCallingIdentity(origId); 4652 4653 // Will only remove if startingToken non null. 4654 scheduleRemoveStartingWindow(startingToken); 4655 } 4656 4657 void scheduleRemoveStartingWindow(AppWindowToken wtoken) { 4658 if (wtoken != null && wtoken.startingWindow != null) { 4659 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) + 4660 ": Schedule remove starting " + wtoken + (wtoken != null ? 4661 " startingWindow=" + wtoken.startingWindow : "")); 4662 Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken); 4663 mH.sendMessage(m); 4664 } 4665 } 4666 4667 private boolean tmpRemoveAppWindowsLocked(WindowToken token) { 4668 WindowList windows = token.windows; 4669 final int NW = windows.size(); 4670 if (NW > 0) { 4671 mWindowsChanged = true; 4672 } 4673 for (int i = 0; i < NW; i++) { 4674 WindowState win = windows.get(i); 4675 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win); 4676 win.getWindowList().remove(win); 4677 int j = win.mChildWindows.size(); 4678 while (j > 0) { 4679 j--; 4680 WindowState cwin = win.mChildWindows.get(j); 4681 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 4682 "Tmp removing child window " + cwin); 4683 cwin.getWindowList().remove(cwin); 4684 } 4685 } 4686 return NW > 0; 4687 } 4688 4689 void dumpAppTokensLocked() { 4690 final int numStacks = mStackIdToStack.size(); 4691 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 4692 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 4693 Slog.v(TAG, " Stack #" + stack.mStackId + " tasks from bottom to top:"); 4694 final ArrayList<Task> tasks = stack.getTasks(); 4695 final int numTasks = tasks.size(); 4696 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4697 final Task task = tasks.get(taskNdx); 4698 Slog.v(TAG, " Task #" + task.taskId + " activities from bottom to top:"); 4699 AppTokenList tokens = task.mAppTokens; 4700 final int numTokens = tokens.size(); 4701 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 4702 Slog.v(TAG, " activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token); 4703 } 4704 } 4705 } 4706 } 4707 4708 void dumpWindowsLocked() { 4709 final int numDisplays = mDisplayContents.size(); 4710 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 4711 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 4712 Slog.v(TAG, " Display #" + displayContent.getDisplayId()); 4713 final WindowList windows = displayContent.getWindowList(); 4714 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 4715 Slog.v(TAG, " #" + winNdx + ": " + windows.get(winNdx)); 4716 } 4717 } 4718 } 4719 4720 private int findAppWindowInsertionPointLocked(AppWindowToken target) { 4721 final int taskId = target.groupId; 4722 Task targetTask = mTaskIdToTask.get(taskId); 4723 if (targetTask == null) { 4724 Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId=" 4725 + taskId); 4726 return 0; 4727 } 4728 DisplayContent displayContent = targetTask.getDisplayContent(); 4729 if (displayContent == null) { 4730 Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target); 4731 return 0; 4732 } 4733 final WindowList windows = displayContent.getWindowList(); 4734 final int NW = windows.size(); 4735 4736 boolean found = false; 4737 final ArrayList<Task> tasks = displayContent.getTasks(); 4738 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 4739 final Task task = tasks.get(taskNdx); 4740 if (!found && task.taskId != taskId) { 4741 continue; 4742 } 4743 AppTokenList tokens = task.mAppTokens; 4744 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 4745 final AppWindowToken wtoken = tokens.get(tokenNdx); 4746 if (!found && wtoken == target) { 4747 found = true; 4748 } 4749 if (found) { 4750 // Find the first app token below the new position that has 4751 // a window displayed. 4752 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token); 4753 if (wtoken.sendingToBottom) { 4754 if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom"); 4755 continue; 4756 } 4757 for (int i = wtoken.windows.size() - 1; i >= 0; --i) { 4758 WindowState win = wtoken.windows.get(i); 4759 for (int j = win.mChildWindows.size() - 1; j >= 0; --j) { 4760 WindowState cwin = win.mChildWindows.get(j); 4761 if (cwin.mSubLayer >= 0) { 4762 for (int pos = NW - 1; pos >= 0; pos--) { 4763 if (windows.get(pos) == cwin) { 4764 if (DEBUG_REORDER) Slog.v(TAG, 4765 "Found child win @" + (pos + 1)); 4766 return pos + 1; 4767 } 4768 } 4769 } 4770 } 4771 for (int pos = NW - 1; pos >= 0; pos--) { 4772 if (windows.get(pos) == win) { 4773 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1)); 4774 return pos + 1; 4775 } 4776 } 4777 } 4778 } 4779 } 4780 } 4781 // Never put an app window underneath wallpaper. 4782 for (int pos = NW - 1; pos >= 0; pos--) { 4783 if (windows.get(pos).mIsWallpaper) { 4784 if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos); 4785 return pos + 1; 4786 } 4787 } 4788 return 0; 4789 } 4790 4791 private final int reAddWindowLocked(int index, WindowState win) { 4792 final WindowList windows = win.getWindowList(); 4793 final int NCW = win.mChildWindows.size(); 4794 boolean added = false; 4795 for (int j=0; j<NCW; j++) { 4796 WindowState cwin = win.mChildWindows.get(j); 4797 if (!added && cwin.mSubLayer >= 0) { 4798 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at " 4799 + index + ": " + cwin); 4800 win.mRebuilding = false; 4801 windows.add(index, win); 4802 index++; 4803 added = true; 4804 } 4805 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4806 + index + ": " + cwin); 4807 cwin.mRebuilding = false; 4808 windows.add(index, cwin); 4809 index++; 4810 } 4811 if (!added) { 4812 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4813 + index + ": " + win); 4814 win.mRebuilding = false; 4815 windows.add(index, win); 4816 index++; 4817 } 4818 mWindowsChanged = true; 4819 return index; 4820 } 4821 4822 private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index, 4823 WindowToken token) { 4824 final int NW = token.windows.size(); 4825 for (int i=0; i<NW; i++) { 4826 final WindowState win = token.windows.get(i); 4827 final DisplayContent winDisplayContent = win.getDisplayContent(); 4828 if (winDisplayContent == displayContent || winDisplayContent == null) { 4829 win.mDisplayContent = displayContent; 4830 index = reAddWindowLocked(index, win); 4831 } 4832 } 4833 return index; 4834 } 4835 4836 void tmpRemoveTaskWindowsLocked(Task task) { 4837 AppTokenList tokens = task.mAppTokens; 4838 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 4839 tmpRemoveAppWindowsLocked(tokens.get(tokenNdx)); 4840 } 4841 } 4842 4843 void moveStackWindowsLocked(DisplayContent displayContent) { 4844 // First remove all of the windows from the list. 4845 final ArrayList<Task> tasks = displayContent.getTasks(); 4846 final int numTasks = tasks.size(); 4847 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4848 tmpRemoveTaskWindowsLocked(tasks.get(taskNdx)); 4849 } 4850 4851 // And now add them back at the correct place. 4852 // Where to start adding? 4853 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4854 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 4855 int pos = findAppWindowInsertionPointLocked(tokens.get(0)); 4856 final int numTokens = tokens.size(); 4857 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 4858 final AppWindowToken wtoken = tokens.get(tokenNdx); 4859 if (wtoken != null) { 4860 final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken); 4861 if (newPos != pos) { 4862 displayContent.layoutNeeded = true; 4863 } 4864 pos = newPos; 4865 } 4866 } 4867 } 4868 4869 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4870 false /*updateInputWindows*/)) { 4871 assignLayersLocked(displayContent.getWindowList()); 4872 } 4873 4874 mInputMonitor.setUpdateInputWindowsNeededLw(); 4875 performLayoutAndPlaceSurfacesLocked(); 4876 mInputMonitor.updateInputWindowsLw(false /*force*/); 4877 4878 //dump(); 4879 } 4880 4881 public void moveTaskToTop(int taskId) { 4882 final long origId = Binder.clearCallingIdentity(); 4883 try { 4884 synchronized(mWindowMap) { 4885 Task task = mTaskIdToTask.get(taskId); 4886 if (task == null) { 4887 // Normal behavior, addAppToken will be called next and task will be created. 4888 return; 4889 } 4890 final TaskStack stack = task.mStack; 4891 final DisplayContent displayContent = task.getDisplayContent(); 4892 displayContent.moveStack(stack, true); 4893 if (displayContent.isDefaultDisplay) { 4894 final TaskStack homeStack = displayContent.getHomeStack(); 4895 if (homeStack != stack) { 4896 // When a non-home stack moves to the top, the home stack moves to the 4897 // bottom. 4898 displayContent.moveStack(homeStack, false); 4899 } 4900 } 4901 stack.moveTaskToTop(task); 4902 } 4903 } finally { 4904 Binder.restoreCallingIdentity(origId); 4905 } 4906 } 4907 4908 public void moveTaskToBottom(int taskId) { 4909 final long origId = Binder.clearCallingIdentity(); 4910 try { 4911 synchronized(mWindowMap) { 4912 Task task = mTaskIdToTask.get(taskId); 4913 if (task == null) { 4914 Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId 4915 + " not found in mTaskIdToTask"); 4916 return; 4917 } 4918 final TaskStack stack = task.mStack; 4919 stack.moveTaskToBottom(task); 4920 moveStackWindowsLocked(stack.getDisplayContent()); 4921 } 4922 } finally { 4923 Binder.restoreCallingIdentity(origId); 4924 } 4925 } 4926 4927 /** 4928 * Create a new TaskStack and place it on a DisplayContent. 4929 * @param stackId The unique identifier of the new stack. 4930 * @param displayId The unique identifier of the DisplayContent. 4931 */ 4932 public void attachStack(int stackId, int displayId) { 4933 final long origId = Binder.clearCallingIdentity(); 4934 try { 4935 synchronized (mWindowMap) { 4936 final DisplayContent displayContent = mDisplayContents.get(displayId); 4937 if (displayContent != null) { 4938 TaskStack stack = mStackIdToStack.get(stackId); 4939 if (stack == null) { 4940 if (DEBUG_STACK) Slog.d(TAG, "attachStack: stackId=" + stackId); 4941 stack = new TaskStack(this, stackId); 4942 mStackIdToStack.put(stackId, stack); 4943 } 4944 stack.attachDisplayContent(displayContent); 4945 displayContent.attachStack(stack); 4946 moveStackWindowsLocked(displayContent); 4947 final WindowList windows = displayContent.getWindowList(); 4948 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 4949 windows.get(winNdx).reportResized(); 4950 } 4951 } 4952 } 4953 } finally { 4954 Binder.restoreCallingIdentity(origId); 4955 } 4956 } 4957 4958 void detachStackLocked(DisplayContent displayContent, TaskStack stack) { 4959 displayContent.detachStack(stack); 4960 stack.detachDisplay(); 4961 } 4962 4963 public void detachStack(int stackId) { 4964 synchronized (mWindowMap) { 4965 TaskStack stack = mStackIdToStack.get(stackId); 4966 if (stack != null) { 4967 final DisplayContent displayContent = stack.getDisplayContent(); 4968 if (displayContent != null) { 4969 if (stack.isAnimating()) { 4970 stack.mDeferDetach = true; 4971 return; 4972 } 4973 detachStackLocked(displayContent, stack); 4974 } 4975 } 4976 } 4977 } 4978 4979 public void removeStack(int stackId) { 4980 mStackIdToStack.remove(stackId); 4981 } 4982 4983 void removeTaskLocked(Task task) { 4984 final int taskId = task.taskId; 4985 final TaskStack stack = task.mStack; 4986 if (stack.isAnimating()) { 4987 if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId); 4988 task.mDeferRemoval = true; 4989 return; 4990 } 4991 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId); 4992 EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask"); 4993 task.mDeferRemoval = false; 4994 task.mStack.removeTask(task); 4995 mTaskIdToTask.delete(task.taskId); 4996 } 4997 4998 public void removeTask(int taskId) { 4999 synchronized (mWindowMap) { 5000 Task task = mTaskIdToTask.get(taskId); 5001 if (task == null) { 5002 if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId); 5003 return; 5004 } 5005 removeTaskLocked(task); 5006 } 5007 } 5008 5009 public void addTask(int taskId, int stackId, boolean toTop) { 5010 synchronized (mWindowMap) { 5011 if (DEBUG_STACK) Slog.i(TAG, "addTask: adding taskId=" + taskId 5012 + " to " + (toTop ? "top" : "bottom")); 5013 Task task = mTaskIdToTask.get(taskId); 5014 if (task == null) { 5015 return; 5016 } 5017 TaskStack stack = mStackIdToStack.get(stackId); 5018 stack.addTask(task, toTop); 5019 final DisplayContent displayContent = stack.getDisplayContent(); 5020 displayContent.layoutNeeded = true; 5021 performLayoutAndPlaceSurfacesLocked(); 5022 } 5023 } 5024 5025 public void resizeStack(int stackId, Rect bounds) { 5026 synchronized (mWindowMap) { 5027 final TaskStack stack = mStackIdToStack.get(stackId); 5028 if (stack == null) { 5029 throw new IllegalArgumentException("resizeStack: stackId " + stackId 5030 + " not found."); 5031 } 5032 if (stack.setBounds(bounds)) { 5033 stack.resizeWindows(); 5034 stack.getDisplayContent().layoutNeeded = true; 5035 performLayoutAndPlaceSurfacesLocked(); 5036 } 5037 } 5038 } 5039 5040 public void getStackBounds(int stackId, Rect bounds) { 5041 final TaskStack stack = mStackIdToStack.get(stackId); 5042 if (stack != null) { 5043 stack.getBounds(bounds); 5044 return; 5045 } 5046 bounds.setEmpty(); 5047 } 5048 5049 // ------------------------------------------------------------- 5050 // Misc IWindowSession methods 5051 // ------------------------------------------------------------- 5052 5053 @Override 5054 public void startFreezingScreen(int exitAnim, int enterAnim) { 5055 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5056 "startFreezingScreen()")) { 5057 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5058 } 5059 5060 synchronized(mWindowMap) { 5061 if (!mClientFreezingScreen) { 5062 mClientFreezingScreen = true; 5063 final long origId = Binder.clearCallingIdentity(); 5064 try { 5065 startFreezingDisplayLocked(false, exitAnim, enterAnim); 5066 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 5067 mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000); 5068 } finally { 5069 Binder.restoreCallingIdentity(origId); 5070 } 5071 } 5072 } 5073 } 5074 5075 @Override 5076 public void stopFreezingScreen() { 5077 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5078 "stopFreezingScreen()")) { 5079 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5080 } 5081 5082 synchronized(mWindowMap) { 5083 if (mClientFreezingScreen) { 5084 mClientFreezingScreen = false; 5085 mLastFinishedFreezeSource = "client"; 5086 final long origId = Binder.clearCallingIdentity(); 5087 try { 5088 stopFreezingDisplayLocked(); 5089 } finally { 5090 Binder.restoreCallingIdentity(origId); 5091 } 5092 } 5093 } 5094 } 5095 5096 @Override 5097 public void disableKeyguard(IBinder token, String tag) { 5098 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5099 != PackageManager.PERMISSION_GRANTED) { 5100 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5101 } 5102 5103 if (token == null) { 5104 throw new IllegalArgumentException("token == null"); 5105 } 5106 5107 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5108 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag))); 5109 } 5110 5111 @Override 5112 public void reenableKeyguard(IBinder token) { 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 (token == null) { 5119 throw new IllegalArgumentException("token == null"); 5120 } 5121 5122 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5123 KeyguardDisableHandler.KEYGUARD_REENABLE, token)); 5124 } 5125 5126 /** 5127 * @see android.app.KeyguardManager#exitKeyguardSecurely 5128 */ 5129 @Override 5130 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) { 5131 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5132 != PackageManager.PERMISSION_GRANTED) { 5133 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5134 } 5135 5136 if (callback == null) { 5137 throw new IllegalArgumentException("callback == null"); 5138 } 5139 5140 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() { 5141 @Override 5142 public void onKeyguardExitResult(boolean success) { 5143 try { 5144 callback.onKeyguardExitResult(success); 5145 } catch (RemoteException e) { 5146 // Client has died, we don't care. 5147 } 5148 } 5149 }); 5150 } 5151 5152 @Override 5153 public boolean inKeyguardRestrictedInputMode() { 5154 return mPolicy.inKeyguardRestrictedKeyInputMode(); 5155 } 5156 5157 @Override 5158 public boolean isKeyguardLocked() { 5159 return mPolicy.isKeyguardLocked(); 5160 } 5161 5162 @Override 5163 public boolean isKeyguardSecure() { 5164 return mPolicy.isKeyguardSecure(); 5165 } 5166 5167 @Override 5168 public void dismissKeyguard() { 5169 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5170 != PackageManager.PERMISSION_GRANTED) { 5171 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5172 } 5173 synchronized(mWindowMap) { 5174 mPolicy.dismissKeyguardLw(); 5175 } 5176 } 5177 5178 @Override 5179 public void keyguardGoingAway() { 5180 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5181 != PackageManager.PERMISSION_GRANTED) { 5182 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5183 } 5184 synchronized (mWindowMap) { 5185 mAnimator.mKeyguardGoingAway = true; 5186 requestTraversalLocked(); 5187 } 5188 } 5189 5190 void showGlobalActions() { 5191 mPolicy.showGlobalActions(); 5192 } 5193 5194 @Override 5195 public void closeSystemDialogs(String reason) { 5196 synchronized(mWindowMap) { 5197 final int numDisplays = mDisplayContents.size(); 5198 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5199 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5200 final int numWindows = windows.size(); 5201 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5202 final WindowState w = windows.get(winNdx); 5203 if (w.mHasSurface) { 5204 try { 5205 w.mClient.closeSystemDialogs(reason); 5206 } catch (RemoteException e) { 5207 } 5208 } 5209 } 5210 } 5211 } 5212 } 5213 5214 static float fixScale(float scale) { 5215 if (scale < 0) scale = 0; 5216 else if (scale > 20) scale = 20; 5217 return Math.abs(scale); 5218 } 5219 5220 @Override 5221 public void setAnimationScale(int which, float scale) { 5222 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5223 "setAnimationScale()")) { 5224 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5225 } 5226 5227 scale = fixScale(scale); 5228 switch (which) { 5229 case 0: mWindowAnimationScaleSetting = scale; break; 5230 case 1: mTransitionAnimationScaleSetting = scale; break; 5231 case 2: mAnimatorDurationScaleSetting = scale; break; 5232 } 5233 5234 // Persist setting 5235 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5236 } 5237 5238 @Override 5239 public void setAnimationScales(float[] scales) { 5240 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5241 "setAnimationScale()")) { 5242 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5243 } 5244 5245 if (scales != null) { 5246 if (scales.length >= 1) { 5247 mWindowAnimationScaleSetting = fixScale(scales[0]); 5248 } 5249 if (scales.length >= 2) { 5250 mTransitionAnimationScaleSetting = fixScale(scales[1]); 5251 } 5252 if (scales.length >= 3) { 5253 mAnimatorDurationScaleSetting = fixScale(scales[2]); 5254 dispatchNewAnimatorScaleLocked(null); 5255 } 5256 } 5257 5258 // Persist setting 5259 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5260 } 5261 5262 private void setAnimatorDurationScale(float scale) { 5263 mAnimatorDurationScaleSetting = scale; 5264 ValueAnimator.setDurationScale(scale); 5265 } 5266 5267 public float getWindowAnimationScaleLocked() { 5268 return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting; 5269 } 5270 5271 public float getTransitionAnimationScaleLocked() { 5272 return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting; 5273 } 5274 5275 @Override 5276 public float getAnimationScale(int which) { 5277 switch (which) { 5278 case 0: return mWindowAnimationScaleSetting; 5279 case 1: return mTransitionAnimationScaleSetting; 5280 case 2: return mAnimatorDurationScaleSetting; 5281 } 5282 return 0; 5283 } 5284 5285 @Override 5286 public float[] getAnimationScales() { 5287 return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting, 5288 mAnimatorDurationScaleSetting }; 5289 } 5290 5291 @Override 5292 public float getCurrentAnimatorScale() { 5293 synchronized(mWindowMap) { 5294 return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting; 5295 } 5296 } 5297 5298 void dispatchNewAnimatorScaleLocked(Session session) { 5299 mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget(); 5300 } 5301 5302 @Override 5303 public void registerPointerEventListener(PointerEventListener listener) { 5304 mPointerEventDispatcher.registerInputEventListener(listener); 5305 } 5306 5307 @Override 5308 public void unregisterPointerEventListener(PointerEventListener listener) { 5309 mPointerEventDispatcher.unregisterInputEventListener(listener); 5310 } 5311 5312 // Called by window manager policy. Not exposed externally. 5313 @Override 5314 public int getLidState() { 5315 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 5316 InputManagerService.SW_LID); 5317 if (sw > 0) { 5318 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 5319 return LID_CLOSED; 5320 } else if (sw == 0) { 5321 // Switch state: AKEY_STATE_UP. 5322 return LID_OPEN; 5323 } else { 5324 // Switch state: AKEY_STATE_UNKNOWN. 5325 return LID_ABSENT; 5326 } 5327 } 5328 5329 // Called by window manager policy. Not exposed externally. 5330 @Override 5331 public void switchKeyboardLayout(int deviceId, int direction) { 5332 mInputManager.switchKeyboardLayout(deviceId, direction); 5333 } 5334 5335 // Called by window manager policy. Not exposed externally. 5336 @Override 5337 public void shutdown(boolean confirm) { 5338 ShutdownThread.shutdown(mContext, confirm); 5339 } 5340 5341 // Called by window manager policy. Not exposed externally. 5342 @Override 5343 public void rebootSafeMode(boolean confirm) { 5344 ShutdownThread.rebootSafeMode(mContext, confirm); 5345 } 5346 5347 public void setCurrentProfileIds(final int[] currentProfileIds) { 5348 synchronized (mWindowMap) { 5349 mCurrentProfileIds = currentProfileIds; 5350 } 5351 } 5352 5353 public void setCurrentUser(final int newUserId, final int[] currentProfileIds) { 5354 synchronized (mWindowMap) { 5355 mCurrentUserId = newUserId; 5356 mCurrentProfileIds = currentProfileIds; 5357 mAppTransition.setCurrentUser(newUserId); 5358 mPolicy.setCurrentUserLw(newUserId); 5359 5360 // Hide windows that should not be seen by the new user. 5361 final int numDisplays = mDisplayContents.size(); 5362 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5363 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 5364 displayContent.switchUserStacks(newUserId); 5365 rebuildAppWindowListLocked(displayContent); 5366 } 5367 performLayoutAndPlaceSurfacesLocked(); 5368 } 5369 } 5370 5371 /* Called by WindowState */ 5372 boolean isCurrentProfileLocked(int userId) { 5373 if (userId == mCurrentUserId) return true; 5374 for (int i = 0; i < mCurrentProfileIds.length; i++) { 5375 if (mCurrentProfileIds[i] == userId) return true; 5376 } 5377 return false; 5378 } 5379 5380 public void enableScreenAfterBoot() { 5381 synchronized(mWindowMap) { 5382 if (DEBUG_BOOT) { 5383 RuntimeException here = new RuntimeException("here"); 5384 here.fillInStackTrace(); 5385 Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled 5386 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5387 + " mShowingBootMessages=" + mShowingBootMessages 5388 + " mSystemBooted=" + mSystemBooted, here); 5389 } 5390 if (mSystemBooted) { 5391 return; 5392 } 5393 mSystemBooted = true; 5394 hideBootMessagesLocked(); 5395 // If the screen still doesn't come up after 30 seconds, give 5396 // up and turn it on. 5397 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000); 5398 } 5399 5400 mPolicy.systemBooted(); 5401 5402 performEnableScreen(); 5403 } 5404 5405 @Override 5406 public void enableScreenIfNeeded() { 5407 synchronized (mWindowMap) { 5408 enableScreenIfNeededLocked(); 5409 } 5410 } 5411 5412 void enableScreenIfNeededLocked() { 5413 if (DEBUG_BOOT) { 5414 RuntimeException here = new RuntimeException("here"); 5415 here.fillInStackTrace(); 5416 Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled 5417 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5418 + " mShowingBootMessages=" + mShowingBootMessages 5419 + " mSystemBooted=" + mSystemBooted, here); 5420 } 5421 if (mDisplayEnabled) { 5422 return; 5423 } 5424 if (!mSystemBooted && !mShowingBootMessages) { 5425 return; 5426 } 5427 mH.sendEmptyMessage(H.ENABLE_SCREEN); 5428 } 5429 5430 public void performBootTimeout() { 5431 synchronized(mWindowMap) { 5432 if (mDisplayEnabled) { 5433 return; 5434 } 5435 Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled"); 5436 mForceDisplayEnabled = true; 5437 } 5438 performEnableScreen(); 5439 } 5440 5441 public void performEnableScreen() { 5442 synchronized(mWindowMap) { 5443 if (DEBUG_BOOT) { 5444 RuntimeException here = new RuntimeException("here"); 5445 here.fillInStackTrace(); 5446 Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled 5447 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5448 + " mShowingBootMessages=" + mShowingBootMessages 5449 + " mSystemBooted=" + mSystemBooted 5450 + " mOnlyCore=" + mOnlyCore, here); 5451 } 5452 if (mDisplayEnabled) { 5453 return; 5454 } 5455 if (!mSystemBooted && !mShowingBootMessages) { 5456 return; 5457 } 5458 5459 if (!mForceDisplayEnabled) { 5460 // Don't enable the screen until all existing windows 5461 // have been drawn. 5462 boolean haveBootMsg = false; 5463 boolean haveApp = false; 5464 // if the wallpaper service is disabled on the device, we're never going to have 5465 // wallpaper, don't bother waiting for it 5466 boolean haveWallpaper = false; 5467 boolean wallpaperEnabled = mContext.getResources().getBoolean( 5468 com.android.internal.R.bool.config_enableWallpaperService) 5469 && !mOnlyCore; 5470 boolean haveKeyguard = true; 5471 // TODO(multidisplay): Expand to all displays? 5472 final WindowList windows = getDefaultWindowListLocked(); 5473 final int N = windows.size(); 5474 for (int i=0; i<N; i++) { 5475 WindowState w = windows.get(i); 5476 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 5477 return; 5478 } 5479 if (w.isDrawnLw()) { 5480 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { 5481 haveBootMsg = true; 5482 } else if (w.mAttrs.type == TYPE_APPLICATION) { 5483 haveApp = true; 5484 } else if (w.mAttrs.type == TYPE_WALLPAPER) { 5485 haveWallpaper = true; 5486 } else if (w.mAttrs.type == TYPE_STATUS_BAR) { 5487 haveKeyguard = mPolicy.isKeyguardDrawnLw(); 5488 } 5489 } 5490 } 5491 5492 if (DEBUG_SCREEN_ON || DEBUG_BOOT) { 5493 Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages 5494 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp 5495 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled 5496 + " haveKeyguard=" + haveKeyguard); 5497 } 5498 5499 // If we are turning on the screen to show the boot message, 5500 // don't do it until the boot message is actually displayed. 5501 if (!mSystemBooted && !haveBootMsg) { 5502 return; 5503 } 5504 5505 // If we are turning on the screen after the boot is completed 5506 // normally, don't do so until we have the application and 5507 // wallpaper. 5508 if (mSystemBooted && ((!haveApp && !haveKeyguard) || 5509 (wallpaperEnabled && !haveWallpaper))) { 5510 return; 5511 } 5512 } 5513 5514 mDisplayEnabled = true; 5515 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!"); 5516 if (false) { 5517 StringWriter sw = new StringWriter(); 5518 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 5519 this.dump(null, pw, null); 5520 pw.flush(); 5521 Slog.i(TAG, sw.toString()); 5522 } 5523 try { 5524 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); 5525 if (surfaceFlinger != null) { 5526 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); 5527 Parcel data = Parcel.obtain(); 5528 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 5529 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED 5530 data, null, 0); 5531 data.recycle(); 5532 } 5533 } catch (RemoteException ex) { 5534 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); 5535 } 5536 5537 // Enable input dispatch. 5538 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled); 5539 } 5540 5541 mPolicy.enableScreenAfterBoot(); 5542 5543 // Make sure the last requested orientation has been applied. 5544 updateRotationUnchecked(false, false); 5545 } 5546 5547 public void showBootMessage(final CharSequence msg, final boolean always) { 5548 boolean first = false; 5549 synchronized(mWindowMap) { 5550 if (DEBUG_BOOT) { 5551 RuntimeException here = new RuntimeException("here"); 5552 here.fillInStackTrace(); 5553 Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always 5554 + " mAllowBootMessages=" + mAllowBootMessages 5555 + " mShowingBootMessages=" + mShowingBootMessages 5556 + " mSystemBooted=" + mSystemBooted, here); 5557 } 5558 if (!mAllowBootMessages) { 5559 return; 5560 } 5561 if (!mShowingBootMessages) { 5562 if (!always) { 5563 return; 5564 } 5565 first = true; 5566 } 5567 if (mSystemBooted) { 5568 return; 5569 } 5570 mShowingBootMessages = true; 5571 mPolicy.showBootMessage(msg, always); 5572 } 5573 if (first) { 5574 performEnableScreen(); 5575 } 5576 } 5577 5578 public void hideBootMessagesLocked() { 5579 if (DEBUG_BOOT) { 5580 RuntimeException here = new RuntimeException("here"); 5581 here.fillInStackTrace(); 5582 Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled 5583 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5584 + " mShowingBootMessages=" + mShowingBootMessages 5585 + " mSystemBooted=" + mSystemBooted, here); 5586 } 5587 if (mShowingBootMessages) { 5588 mShowingBootMessages = false; 5589 mPolicy.hideBootMessages(); 5590 } 5591 } 5592 5593 @Override 5594 public void setInTouchMode(boolean mode) { 5595 synchronized(mWindowMap) { 5596 mInTouchMode = mode; 5597 } 5598 } 5599 5600 // TODO: more accounting of which pid(s) turned it on, keep count, 5601 // only allow disables from pids which have count on, etc. 5602 @Override 5603 public void showStrictModeViolation(boolean on) { 5604 int pid = Binder.getCallingPid(); 5605 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid)); 5606 } 5607 5608 private void showStrictModeViolation(int arg, int pid) { 5609 final boolean on = arg != 0; 5610 synchronized(mWindowMap) { 5611 // Ignoring requests to enable the red border from clients 5612 // which aren't on screen. (e.g. Broadcast Receivers in 5613 // the background..) 5614 if (on) { 5615 boolean isVisible = false; 5616 final int numDisplays = mDisplayContents.size(); 5617 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5618 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5619 final int numWindows = windows.size(); 5620 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5621 final WindowState ws = windows.get(winNdx); 5622 if (ws.mSession.mPid == pid && ws.isVisibleLw()) { 5623 isVisible = true; 5624 break; 5625 } 5626 } 5627 } 5628 if (!isVisible) { 5629 return; 5630 } 5631 } 5632 5633 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5634 ">>> OPEN TRANSACTION showStrictModeViolation"); 5635 SurfaceControl.openTransaction(); 5636 try { 5637 // TODO(multi-display): support multiple displays 5638 if (mStrictModeFlash == null) { 5639 mStrictModeFlash = new StrictModeFlash( 5640 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 5641 } 5642 mStrictModeFlash.setVisibility(on); 5643 } finally { 5644 SurfaceControl.closeTransaction(); 5645 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5646 "<<< CLOSE TRANSACTION showStrictModeViolation"); 5647 } 5648 } 5649 } 5650 5651 @Override 5652 public void setStrictModeVisualIndicatorPreference(String value) { 5653 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 5654 } 5655 5656 /** 5657 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 5658 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 5659 * of the target image. 5660 * 5661 * @param displayId the Display to take a screenshot of. 5662 * @param width the width of the target bitmap 5663 * @param height the height of the target bitmap 5664 * @param force565 if true the returned bitmap will be RGB_565, otherwise it 5665 * will be the same config as the surface 5666 */ 5667 @Override 5668 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, 5669 int height, boolean force565) { 5670 if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, 5671 "screenshotApplications()")) { 5672 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 5673 } 5674 5675 Bitmap rawss = null; 5676 5677 int maxLayer = 0; 5678 final Rect frame = new Rect(); 5679 5680 float scale = 0; 5681 int dw, dh; 5682 int rot = Surface.ROTATION_0; 5683 5684 boolean screenshotReady; 5685 int minLayer; 5686 if (appToken == null) { 5687 screenshotReady = true; 5688 minLayer = 0; 5689 } else { 5690 screenshotReady = false; 5691 minLayer = Integer.MAX_VALUE; 5692 } 5693 5694 int retryCount = 0; 5695 WindowState appWin = null; 5696 5697 do { 5698 if (retryCount++ > 0) { 5699 try { 5700 Thread.sleep(100); 5701 } catch (InterruptedException e) { 5702 } 5703 } 5704 synchronized(mWindowMap) { 5705 final DisplayContent displayContent = getDisplayContentLocked(displayId); 5706 if (displayContent == null) { 5707 return null; 5708 } 5709 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 5710 dw = displayInfo.logicalWidth; 5711 dh = displayInfo.logicalHeight; 5712 5713 int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) 5714 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 5715 aboveAppLayer += TYPE_LAYER_MULTIPLIER; 5716 5717 boolean isImeTarget = mInputMethodTarget != null 5718 && mInputMethodTarget.mAppToken != null 5719 && mInputMethodTarget.mAppToken.appToken != null 5720 && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken; 5721 5722 // Figure out the part of the screen that is actually the app. 5723 boolean including = false; 5724 appWin = null; 5725 final WindowList windows = displayContent.getWindowList(); 5726 final Rect stackBounds = new Rect(); 5727 for (int i = windows.size() - 1; i >= 0; i--) { 5728 WindowState ws = windows.get(i); 5729 if (!ws.mHasSurface) { 5730 continue; 5731 } 5732 if (ws.mLayer >= aboveAppLayer) { 5733 continue; 5734 } 5735 // When we will skip windows: when we are not including 5736 // ones behind a window we didn't skip, and we are actually 5737 // taking a screenshot of a specific app. 5738 if (!including && appToken != null) { 5739 // Also, we can possibly skip this window if it is not 5740 // an IME target or the application for the screenshot 5741 // is not the current IME target. 5742 if (!ws.mIsImWindow || !isImeTarget) { 5743 // And finally, this window is of no interest if it 5744 // is not associated with the screenshot app. 5745 if (ws.mAppToken == null || ws.mAppToken.token != appToken) { 5746 continue; 5747 } 5748 appWin = ws; 5749 ws.getStackBounds(stackBounds); 5750 } 5751 } 5752 5753 // We keep on including windows until we go past a full-screen 5754 // window. 5755 including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh); 5756 5757 final WindowStateAnimator winAnim = ws.mWinAnimator; 5758 if (maxLayer < winAnim.mSurfaceLayer) { 5759 maxLayer = winAnim.mSurfaceLayer; 5760 } 5761 if (minLayer > winAnim.mSurfaceLayer) { 5762 minLayer = winAnim.mSurfaceLayer; 5763 } 5764 5765 // Don't include wallpaper in bounds calculation 5766 if (!ws.mIsWallpaper) { 5767 final Rect wf = ws.mFrame; 5768 final Rect cr = ws.mContentInsets; 5769 int left = wf.left + cr.left; 5770 int top = wf.top + cr.top; 5771 int right = wf.right - cr.right; 5772 int bottom = wf.bottom - cr.bottom; 5773 frame.union(left, top, right, bottom); 5774 frame.intersect(stackBounds); 5775 } 5776 5777 if (ws.mAppToken != null && ws.mAppToken.token == appToken && 5778 ws.isDisplayedLw()) { 5779 screenshotReady = true; 5780 } 5781 } 5782 5783 if (appToken != null && appWin == null) { 5784 // Can't find a window to snapshot. 5785 if (DEBUG_SCREENSHOT) Slog.i(TAG, 5786 "Screenshot: Couldn't find a surface matching " + appToken); 5787 return null; 5788 } 5789 if (!screenshotReady) { 5790 // Delay and hope that window gets drawn. 5791 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken 5792 + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState); 5793 continue; 5794 } 5795 5796 // Constrain frame to the screen size. 5797 frame.intersect(0, 0, dw, dh); 5798 5799 if (frame.isEmpty() || maxLayer == 0) { 5800 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 5801 + ": returning null frame=" + frame.toShortString() + " maxLayer=" 5802 + maxLayer); 5803 return null; 5804 } 5805 5806 // The screenshot API does not apply the current screen rotation. 5807 rot = getDefaultDisplayContentLocked().getDisplay().getRotation(); 5808 int fw = frame.width(); 5809 int fh = frame.height(); 5810 5811 // Constrain thumbnail to smaller of screen width or height. Assumes aspect 5812 // of thumbnail is the same as the screen (in landscape) or square. 5813 scale = Math.max(width / (float) fw, height / (float) fh); 5814 /* 5815 float targetWidthScale = width / (float) fw; 5816 float targetHeightScale = height / (float) fh; 5817 if (fw <= fh) { 5818 scale = targetWidthScale; 5819 // If aspect of thumbnail is the same as the screen (in landscape), 5820 // select the slightly larger value so we fill the entire bitmap 5821 if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) { 5822 scale = targetHeightScale; 5823 } 5824 } else { 5825 scale = targetHeightScale; 5826 // If aspect of thumbnail is the same as the screen (in landscape), 5827 // select the slightly larger value so we fill the entire bitmap 5828 if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) { 5829 scale = targetWidthScale; 5830 } 5831 } 5832 */ 5833 5834 // The screen shot will contain the entire screen. 5835 dw = (int)(dw*scale); 5836 dh = (int)(dh*scale); 5837 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 5838 int tmp = dw; 5839 dw = dh; 5840 dh = tmp; 5841 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; 5842 } 5843 if (DEBUG_SCREENSHOT) { 5844 Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 5845 + maxLayer + " appToken=" + appToken); 5846 for (int i = 0; i < windows.size(); i++) { 5847 WindowState win = windows.get(i); 5848 Slog.i(TAG, win + ": " + win.mLayer 5849 + " animLayer=" + win.mWinAnimator.mAnimLayer 5850 + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer); 5851 } 5852 } 5853 // TODO: Replace 'false' in the following line with a variable that indicates 5854 // whether the screenshot should use the identity transformation matrix 5855 // (e.g., enable it when taking a screenshot for recents, since we might be in 5856 // the middle of the rotation animation, but don't want a rotated recent image). 5857 // TODO: Replace 'new Rect()' with the portion of the screen to capture for the 5858 // screenshot. 5859 rawss = SurfaceControl.screenshot(new Rect(), dw, dh, minLayer, maxLayer, false); 5860 } 5861 } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES); 5862 if (retryCount > MAX_SCREENSHOT_RETRIES) Slog.i(TAG, "Screenshot max retries " + 5863 retryCount + " of " + appToken + " appWin=" + (appWin == null ? 5864 "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState))); 5865 5866 if (rawss == null) { 5867 Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh 5868 + ") to layer " + maxLayer); 5869 return null; 5870 } 5871 5872 Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig()); 5873 bm.eraseColor(0xFF000000); 5874 frame.scale(scale); 5875 Matrix matrix = new Matrix(); 5876 ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix); 5877 // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left 5878 matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top)); 5879 Canvas canvas = new Canvas(bm); 5880 canvas.drawBitmap(rawss, matrix, null); 5881 canvas.setBitmap(null); 5882 5883 if (DEBUG_SCREENSHOT) { 5884 // TEST IF IT's ALL BLACK 5885 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 5886 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 5887 boolean allBlack = true; 5888 final int firstColor = buffer[0]; 5889 for (int i = 0; i < buffer.length; i++) { 5890 if (buffer[i] != firstColor) { 5891 allBlack = false; 5892 break; 5893 } 5894 } 5895 if (allBlack) { 5896 Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" + 5897 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 5898 (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") + 5899 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 5900 } 5901 } 5902 5903 rawss.recycle(); 5904 return bm; 5905 } 5906 5907 /** 5908 * Freeze rotation changes. (Enable "rotation lock".) 5909 * Persists across reboots. 5910 * @param rotation The desired rotation to freeze to, or -1 to use the 5911 * current rotation. 5912 */ 5913 @Override 5914 public void freezeRotation(int rotation) { 5915 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5916 "freezeRotation()")) { 5917 throw new SecurityException("Requires SET_ORIENTATION permission"); 5918 } 5919 if (rotation < -1 || rotation > Surface.ROTATION_270) { 5920 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 5921 + "rotation constant."); 5922 } 5923 5924 if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); 5925 5926 long origId = Binder.clearCallingIdentity(); 5927 try { 5928 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, 5929 rotation == -1 ? mRotation : rotation); 5930 } finally { 5931 Binder.restoreCallingIdentity(origId); 5932 } 5933 5934 updateRotationUnchecked(false, false); 5935 } 5936 5937 /** 5938 * Thaw rotation changes. (Disable "rotation lock".) 5939 * Persists across reboots. 5940 */ 5941 @Override 5942 public void thawRotation() { 5943 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5944 "thawRotation()")) { 5945 throw new SecurityException("Requires SET_ORIENTATION permission"); 5946 } 5947 5948 if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); 5949 5950 long origId = Binder.clearCallingIdentity(); 5951 try { 5952 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 5953 777); // rot not used 5954 } finally { 5955 Binder.restoreCallingIdentity(origId); 5956 } 5957 5958 updateRotationUnchecked(false, false); 5959 } 5960 5961 /** 5962 * Recalculate the current rotation. 5963 * 5964 * Called by the window manager policy whenever the state of the system changes 5965 * such that the current rotation might need to be updated, such as when the 5966 * device is docked or rotated into a new posture. 5967 */ 5968 @Override 5969 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 5970 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 5971 } 5972 5973 /** 5974 * Temporarily pauses rotation changes until resumed. 5975 * 5976 * This can be used to prevent rotation changes from occurring while the user is 5977 * performing certain operations, such as drag and drop. 5978 * 5979 * This call nests and must be matched by an equal number of calls to 5980 * {@link #resumeRotationLocked}. 5981 */ 5982 void pauseRotationLocked() { 5983 mDeferredRotationPauseCount += 1; 5984 } 5985 5986 /** 5987 * Resumes normal rotation changes after being paused. 5988 */ 5989 void resumeRotationLocked() { 5990 if (mDeferredRotationPauseCount > 0) { 5991 mDeferredRotationPauseCount -= 1; 5992 if (mDeferredRotationPauseCount == 0) { 5993 boolean changed = updateRotationUncheckedLocked(false); 5994 if (changed) { 5995 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 5996 } 5997 } 5998 } 5999 } 6000 6001 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 6002 if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" 6003 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); 6004 6005 long origId = Binder.clearCallingIdentity(); 6006 boolean changed; 6007 synchronized(mWindowMap) { 6008 changed = updateRotationUncheckedLocked(false); 6009 if (!changed || forceRelayout) { 6010 getDefaultDisplayContentLocked().layoutNeeded = true; 6011 performLayoutAndPlaceSurfacesLocked(); 6012 } 6013 } 6014 6015 if (changed || alwaysSendConfiguration) { 6016 sendNewConfiguration(); 6017 } 6018 6019 Binder.restoreCallingIdentity(origId); 6020 } 6021 6022 // TODO(multidisplay): Rotate any display? 6023 /** 6024 * Updates the current rotation. 6025 * 6026 * Returns true if the rotation has been changed. In this case YOU 6027 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. 6028 */ 6029 public boolean updateRotationUncheckedLocked(boolean inTransaction) { 6030 if (mDeferredRotationPauseCount > 0) { 6031 // Rotation updates have been paused temporarily. Defer the update until 6032 // updates have been resumed. 6033 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused."); 6034 return false; 6035 } 6036 6037 ScreenRotationAnimation screenRotationAnimation = 6038 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6039 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 6040 // Rotation updates cannot be performed while the previous rotation change 6041 // animation is still in progress. Skip this update. We will try updating 6042 // again after the animation is finished and the display is unfrozen. 6043 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress."); 6044 return false; 6045 } 6046 6047 if (!mDisplayEnabled) { 6048 // No point choosing a rotation if the display is not enabled. 6049 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled."); 6050 return false; 6051 } 6052 6053 // TODO: Implement forced rotation changes. 6054 // Set mAltOrientation to indicate that the application is receiving 6055 // an orientation that has different metrics than it expected. 6056 // eg. Portrait instead of Landscape. 6057 6058 int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation); 6059 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 6060 mForcedAppOrientation, rotation); 6061 6062 if (DEBUG_ORIENTATION) { 6063 Slog.v(TAG, "Application requested orientation " 6064 + mForcedAppOrientation + ", got rotation " + rotation 6065 + " which has " + (altOrientation ? "incompatible" : "compatible") 6066 + " metrics"); 6067 } 6068 6069 if (mRotation == rotation && mAltOrientation == altOrientation) { 6070 // No change. 6071 return false; 6072 } 6073 6074 if (DEBUG_ORIENTATION) { 6075 Slog.v(TAG, 6076 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") 6077 + " from " + mRotation + (mAltOrientation ? " (alt)" : "") 6078 + ", forceApp=" + mForcedAppOrientation); 6079 } 6080 6081 mRotation = rotation; 6082 mAltOrientation = altOrientation; 6083 mPolicy.setRotationLw(mRotation); 6084 6085 mWindowsFreezingScreen = true; 6086 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 6087 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION); 6088 mWaitingForConfig = true; 6089 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6090 displayContent.layoutNeeded = true; 6091 final int[] anim = new int[2]; 6092 if (displayContent.isDimming()) { 6093 anim[0] = anim[1] = 0; 6094 } else { 6095 mPolicy.selectRotationAnimationLw(anim); 6096 } 6097 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]); 6098 // startFreezingDisplayLocked can reset the ScreenRotationAnimation. 6099 screenRotationAnimation = 6100 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6101 6102 // We need to update our screen size information to match the new 6103 // rotation. Note that this is redundant with the later call to 6104 // sendNewConfiguration() that must be called after this function 6105 // returns... however we need to do the screen size part of that 6106 // before then so we have the correct size to use when initializing 6107 // the rotation animation for the new rotation. 6108 computeScreenConfigurationLocked(null); 6109 6110 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6111 if (!inTransaction) { 6112 if (SHOW_TRANSACTIONS) { 6113 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked"); 6114 } 6115 SurfaceControl.openTransaction(); 6116 } 6117 try { 6118 // NOTE: We disable the rotation in the emulator because 6119 // it doesn't support hardware OpenGL emulation yet. 6120 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 6121 && screenRotationAnimation.hasScreenshot()) { 6122 if (screenRotationAnimation.setRotationInTransaction( 6123 rotation, mFxSession, 6124 MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(), 6125 displayInfo.logicalWidth, displayInfo.logicalHeight)) { 6126 scheduleAnimationLocked(); 6127 } 6128 } 6129 6130 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 6131 } finally { 6132 if (!inTransaction) { 6133 SurfaceControl.closeTransaction(); 6134 if (SHOW_LIGHT_TRANSACTIONS) { 6135 Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked"); 6136 } 6137 } 6138 } 6139 6140 final WindowList windows = displayContent.getWindowList(); 6141 for (int i = windows.size() - 1; i >= 0; i--) { 6142 WindowState w = windows.get(i); 6143 if (w.mHasSurface) { 6144 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w); 6145 w.mOrientationChanging = true; 6146 mInnerFields.mOrientationChangeComplete = false; 6147 } 6148 w.mLastFreezeDuration = 0; 6149 } 6150 6151 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 6152 try { 6153 mRotationWatchers.get(i).watcher.onRotationChanged(rotation); 6154 } catch (RemoteException e) { 6155 } 6156 } 6157 6158 //TODO (multidisplay): Magnification is supported only for the default display. 6159 if (mAccessibilityController != null 6160 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 6161 mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation); 6162 } 6163 6164 return true; 6165 } 6166 6167 @Override 6168 public int getRotation() { 6169 return mRotation; 6170 } 6171 6172 @Override 6173 public boolean isRotationFrozen() { 6174 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED; 6175 } 6176 6177 @Override 6178 public int watchRotation(IRotationWatcher watcher) { 6179 final IBinder watcherBinder = watcher.asBinder(); 6180 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 6181 @Override 6182 public void binderDied() { 6183 synchronized (mWindowMap) { 6184 for (int i=0; i<mRotationWatchers.size(); i++) { 6185 if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) { 6186 RotationWatcher removed = mRotationWatchers.remove(i); 6187 IBinder binder = removed.watcher.asBinder(); 6188 if (binder != null) { 6189 binder.unlinkToDeath(this, 0); 6190 } 6191 i--; 6192 } 6193 } 6194 } 6195 } 6196 }; 6197 6198 synchronized (mWindowMap) { 6199 try { 6200 watcher.asBinder().linkToDeath(dr, 0); 6201 mRotationWatchers.add(new RotationWatcher(watcher, dr)); 6202 } catch (RemoteException e) { 6203 // Client died, no cleanup needed. 6204 } 6205 6206 return mRotation; 6207 } 6208 } 6209 6210 @Override 6211 public void removeRotationWatcher(IRotationWatcher watcher) { 6212 final IBinder watcherBinder = watcher.asBinder(); 6213 synchronized (mWindowMap) { 6214 for (int i=0; i<mRotationWatchers.size(); i++) { 6215 RotationWatcher rotationWatcher = mRotationWatchers.get(i); 6216 if (watcherBinder == rotationWatcher.watcher.asBinder()) { 6217 RotationWatcher removed = mRotationWatchers.remove(i); 6218 IBinder binder = removed.watcher.asBinder(); 6219 if (binder != null) { 6220 binder.unlinkToDeath(removed.deathRecipient, 0); 6221 } 6222 i--; 6223 } 6224 } 6225 } 6226 } 6227 6228 /** 6229 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 6230 * theme attribute) on devices that feature a physical options menu key attempt to position 6231 * their menu panel window along the edge of the screen nearest the physical menu key. 6232 * This lowers the travel distance between invoking the menu panel and selecting 6233 * a menu option. 6234 * 6235 * This method helps control where that menu is placed. Its current implementation makes 6236 * assumptions about the menu key and its relationship to the screen based on whether 6237 * the device's natural orientation is portrait (width < height) or landscape. 6238 * 6239 * The menu key is assumed to be located along the bottom edge of natural-portrait 6240 * devices and along the right edge of natural-landscape devices. If these assumptions 6241 * do not hold for the target device, this method should be changed to reflect that. 6242 * 6243 * @return A {@link Gravity} value for placing the options menu window 6244 */ 6245 @Override 6246 public int getPreferredOptionsPanelGravity() { 6247 synchronized (mWindowMap) { 6248 final int rotation = getRotation(); 6249 6250 // TODO(multidisplay): Assume that such devices physical keys are on the main screen. 6251 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6252 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) { 6253 // On devices with a natural orientation of portrait 6254 switch (rotation) { 6255 default: 6256 case Surface.ROTATION_0: 6257 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6258 case Surface.ROTATION_90: 6259 return Gravity.RIGHT | Gravity.BOTTOM; 6260 case Surface.ROTATION_180: 6261 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6262 case Surface.ROTATION_270: 6263 return Gravity.START | Gravity.BOTTOM; 6264 } 6265 } 6266 6267 // On devices with a natural orientation of landscape 6268 switch (rotation) { 6269 default: 6270 case Surface.ROTATION_0: 6271 return Gravity.RIGHT | Gravity.BOTTOM; 6272 case Surface.ROTATION_90: 6273 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6274 case Surface.ROTATION_180: 6275 return Gravity.START | Gravity.BOTTOM; 6276 case Surface.ROTATION_270: 6277 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6278 } 6279 } 6280 } 6281 6282 /** 6283 * Starts the view server on the specified port. 6284 * 6285 * @param port The port to listener to. 6286 * 6287 * @return True if the server was successfully started, false otherwise. 6288 * 6289 * @see com.android.server.wm.ViewServer 6290 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 6291 */ 6292 @Override 6293 public boolean startViewServer(int port) { 6294 if (isSystemSecure()) { 6295 return false; 6296 } 6297 6298 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 6299 return false; 6300 } 6301 6302 if (port < 1024) { 6303 return false; 6304 } 6305 6306 if (mViewServer != null) { 6307 if (!mViewServer.isRunning()) { 6308 try { 6309 return mViewServer.start(); 6310 } catch (IOException e) { 6311 Slog.w(TAG, "View server did not start"); 6312 } 6313 } 6314 return false; 6315 } 6316 6317 try { 6318 mViewServer = new ViewServer(this, port); 6319 return mViewServer.start(); 6320 } catch (IOException e) { 6321 Slog.w(TAG, "View server did not start"); 6322 } 6323 return false; 6324 } 6325 6326 private boolean isSystemSecure() { 6327 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 6328 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 6329 } 6330 6331 /** 6332 * Stops the view server if it exists. 6333 * 6334 * @return True if the server stopped, false if it wasn't started or 6335 * couldn't be stopped. 6336 * 6337 * @see com.android.server.wm.ViewServer 6338 */ 6339 @Override 6340 public boolean stopViewServer() { 6341 if (isSystemSecure()) { 6342 return false; 6343 } 6344 6345 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 6346 return false; 6347 } 6348 6349 if (mViewServer != null) { 6350 return mViewServer.stop(); 6351 } 6352 return false; 6353 } 6354 6355 /** 6356 * Indicates whether the view server is running. 6357 * 6358 * @return True if the server is running, false otherwise. 6359 * 6360 * @see com.android.server.wm.ViewServer 6361 */ 6362 @Override 6363 public boolean isViewServerRunning() { 6364 if (isSystemSecure()) { 6365 return false; 6366 } 6367 6368 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 6369 return false; 6370 } 6371 6372 return mViewServer != null && mViewServer.isRunning(); 6373 } 6374 6375 /** 6376 * Lists all availble windows in the system. The listing is written in the 6377 * specified Socket's output stream with the following syntax: 6378 * windowHashCodeInHexadecimal windowName 6379 * Each line of the ouput represents a different window. 6380 * 6381 * @param client The remote client to send the listing to. 6382 * @return False if an error occured, true otherwise. 6383 */ 6384 boolean viewServerListWindows(Socket client) { 6385 if (isSystemSecure()) { 6386 return false; 6387 } 6388 6389 boolean result = true; 6390 6391 WindowList windows = new WindowList(); 6392 synchronized (mWindowMap) { 6393 //noinspection unchecked 6394 final int numDisplays = mDisplayContents.size(); 6395 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6396 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 6397 windows.addAll(displayContent.getWindowList()); 6398 } 6399 } 6400 6401 BufferedWriter out = null; 6402 6403 // Any uncaught exception will crash the system process 6404 try { 6405 OutputStream clientStream = client.getOutputStream(); 6406 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6407 6408 final int count = windows.size(); 6409 for (int i = 0; i < count; i++) { 6410 final WindowState w = windows.get(i); 6411 out.write(Integer.toHexString(System.identityHashCode(w))); 6412 out.write(' '); 6413 out.append(w.mAttrs.getTitle()); 6414 out.write('\n'); 6415 } 6416 6417 out.write("DONE.\n"); 6418 out.flush(); 6419 } catch (Exception e) { 6420 result = false; 6421 } finally { 6422 if (out != null) { 6423 try { 6424 out.close(); 6425 } catch (IOException e) { 6426 result = false; 6427 } 6428 } 6429 } 6430 6431 return result; 6432 } 6433 6434 // TODO(multidisplay): Extend to multiple displays. 6435 /** 6436 * Returns the focused window in the following format: 6437 * windowHashCodeInHexadecimal windowName 6438 * 6439 * @param client The remote client to send the listing to. 6440 * @return False if an error occurred, true otherwise. 6441 */ 6442 boolean viewServerGetFocusedWindow(Socket client) { 6443 if (isSystemSecure()) { 6444 return false; 6445 } 6446 6447 boolean result = true; 6448 6449 WindowState focusedWindow = getFocusedWindow(); 6450 6451 BufferedWriter out = null; 6452 6453 // Any uncaught exception will crash the system process 6454 try { 6455 OutputStream clientStream = client.getOutputStream(); 6456 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6457 6458 if(focusedWindow != null) { 6459 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 6460 out.write(' '); 6461 out.append(focusedWindow.mAttrs.getTitle()); 6462 } 6463 out.write('\n'); 6464 out.flush(); 6465 } catch (Exception e) { 6466 result = false; 6467 } finally { 6468 if (out != null) { 6469 try { 6470 out.close(); 6471 } catch (IOException e) { 6472 result = false; 6473 } 6474 } 6475 } 6476 6477 return result; 6478 } 6479 6480 /** 6481 * Sends a command to a target window. The result of the command, if any, will be 6482 * written in the output stream of the specified socket. 6483 * 6484 * The parameters must follow this syntax: 6485 * windowHashcode extra 6486 * 6487 * Where XX is the length in characeters of the windowTitle. 6488 * 6489 * The first parameter is the target window. The window with the specified hashcode 6490 * will be the target. If no target can be found, nothing happens. The extra parameters 6491 * will be delivered to the target window and as parameters to the command itself. 6492 * 6493 * @param client The remote client to sent the result, if any, to. 6494 * @param command The command to execute. 6495 * @param parameters The command parameters. 6496 * 6497 * @return True if the command was successfully delivered, false otherwise. This does 6498 * not indicate whether the command itself was successful. 6499 */ 6500 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 6501 if (isSystemSecure()) { 6502 return false; 6503 } 6504 6505 boolean success = true; 6506 Parcel data = null; 6507 Parcel reply = null; 6508 6509 BufferedWriter out = null; 6510 6511 // Any uncaught exception will crash the system process 6512 try { 6513 // Find the hashcode of the window 6514 int index = parameters.indexOf(' '); 6515 if (index == -1) { 6516 index = parameters.length(); 6517 } 6518 final String code = parameters.substring(0, index); 6519 int hashCode = (int) Long.parseLong(code, 16); 6520 6521 // Extract the command's parameter after the window description 6522 if (index < parameters.length()) { 6523 parameters = parameters.substring(index + 1); 6524 } else { 6525 parameters = ""; 6526 } 6527 6528 final WindowState window = findWindow(hashCode); 6529 if (window == null) { 6530 return false; 6531 } 6532 6533 data = Parcel.obtain(); 6534 data.writeInterfaceToken("android.view.IWindow"); 6535 data.writeString(command); 6536 data.writeString(parameters); 6537 data.writeInt(1); 6538 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 6539 6540 reply = Parcel.obtain(); 6541 6542 final IBinder binder = window.mClient.asBinder(); 6543 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 6544 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 6545 6546 reply.readException(); 6547 6548 if (!client.isOutputShutdown()) { 6549 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 6550 out.write("DONE\n"); 6551 out.flush(); 6552 } 6553 6554 } catch (Exception e) { 6555 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); 6556 success = false; 6557 } finally { 6558 if (data != null) { 6559 data.recycle(); 6560 } 6561 if (reply != null) { 6562 reply.recycle(); 6563 } 6564 if (out != null) { 6565 try { 6566 out.close(); 6567 } catch (IOException e) { 6568 6569 } 6570 } 6571 } 6572 6573 return success; 6574 } 6575 6576 public void addWindowChangeListener(WindowChangeListener listener) { 6577 synchronized(mWindowMap) { 6578 mWindowChangeListeners.add(listener); 6579 } 6580 } 6581 6582 public void removeWindowChangeListener(WindowChangeListener listener) { 6583 synchronized(mWindowMap) { 6584 mWindowChangeListeners.remove(listener); 6585 } 6586 } 6587 6588 private void notifyWindowsChanged() { 6589 WindowChangeListener[] windowChangeListeners; 6590 synchronized(mWindowMap) { 6591 if(mWindowChangeListeners.isEmpty()) { 6592 return; 6593 } 6594 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6595 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6596 } 6597 int N = windowChangeListeners.length; 6598 for(int i = 0; i < N; i++) { 6599 windowChangeListeners[i].windowsChanged(); 6600 } 6601 } 6602 6603 private void notifyFocusChanged() { 6604 WindowChangeListener[] windowChangeListeners; 6605 synchronized(mWindowMap) { 6606 if(mWindowChangeListeners.isEmpty()) { 6607 return; 6608 } 6609 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6610 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6611 } 6612 int N = windowChangeListeners.length; 6613 for(int i = 0; i < N; i++) { 6614 windowChangeListeners[i].focusChanged(); 6615 } 6616 } 6617 6618 private WindowState findWindow(int hashCode) { 6619 if (hashCode == -1) { 6620 // TODO(multidisplay): Extend to multiple displays. 6621 return getFocusedWindow(); 6622 } 6623 6624 synchronized (mWindowMap) { 6625 final int numDisplays = mDisplayContents.size(); 6626 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6627 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 6628 final int numWindows = windows.size(); 6629 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 6630 final WindowState w = windows.get(winNdx); 6631 if (System.identityHashCode(w) == hashCode) { 6632 return w; 6633 } 6634 } 6635 } 6636 } 6637 6638 return null; 6639 } 6640 6641 /* 6642 * Instruct the Activity Manager to fetch the current configuration and broadcast 6643 * that to config-changed listeners if appropriate. 6644 */ 6645 void sendNewConfiguration() { 6646 try { 6647 mActivityManager.updateConfiguration(null); 6648 } catch (RemoteException e) { 6649 } 6650 } 6651 6652 public Configuration computeNewConfiguration() { 6653 synchronized (mWindowMap) { 6654 Configuration config = computeNewConfigurationLocked(); 6655 if (config == null && mWaitingForConfig) { 6656 // Nothing changed but we are waiting for something... stop that! 6657 mWaitingForConfig = false; 6658 mLastFinishedFreezeSource = "new-config"; 6659 performLayoutAndPlaceSurfacesLocked(); 6660 } 6661 return config; 6662 } 6663 } 6664 6665 Configuration computeNewConfigurationLocked() { 6666 Configuration config = new Configuration(); 6667 config.fontScale = 0; 6668 if (!computeScreenConfigurationLocked(config)) { 6669 return null; 6670 } 6671 return config; 6672 } 6673 6674 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) { 6675 // TODO: Multidisplay: for now only use with default display. 6676 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation); 6677 if (width < displayInfo.smallestNominalAppWidth) { 6678 displayInfo.smallestNominalAppWidth = width; 6679 } 6680 if (width > displayInfo.largestNominalAppWidth) { 6681 displayInfo.largestNominalAppWidth = width; 6682 } 6683 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation); 6684 if (height < displayInfo.smallestNominalAppHeight) { 6685 displayInfo.smallestNominalAppHeight = height; 6686 } 6687 if (height > displayInfo.largestNominalAppHeight) { 6688 displayInfo.largestNominalAppHeight = height; 6689 } 6690 } 6691 6692 private int reduceConfigLayout(int curLayout, int rotation, float density, 6693 int dw, int dh) { 6694 // TODO: Multidisplay: for now only use with default display. 6695 // Get the app screen size at this rotation. 6696 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6697 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6698 6699 // Compute the screen layout size class for this rotation. 6700 int longSize = w; 6701 int shortSize = h; 6702 if (longSize < shortSize) { 6703 int tmp = longSize; 6704 longSize = shortSize; 6705 shortSize = tmp; 6706 } 6707 longSize = (int)(longSize/density); 6708 shortSize = (int)(shortSize/density); 6709 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 6710 } 6711 6712 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 6713 int dw, int dh, float density, Configuration outConfig) { 6714 // TODO: Multidisplay: for now only use with default display. 6715 6716 // We need to determine the smallest width that will occur under normal 6717 // operation. To this, start with the base screen size and compute the 6718 // width under the different possible rotations. We need to un-rotate 6719 // the current screen dimensions before doing this. 6720 int unrotDw, unrotDh; 6721 if (rotated) { 6722 unrotDw = dh; 6723 unrotDh = dw; 6724 } else { 6725 unrotDw = dw; 6726 unrotDh = dh; 6727 } 6728 displayInfo.smallestNominalAppWidth = 1<<30; 6729 displayInfo.smallestNominalAppHeight = 1<<30; 6730 displayInfo.largestNominalAppWidth = 0; 6731 displayInfo.largestNominalAppHeight = 0; 6732 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh); 6733 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw); 6734 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh); 6735 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw); 6736 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 6737 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh); 6738 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw); 6739 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); 6740 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); 6741 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 6742 outConfig.screenLayout = sl; 6743 } 6744 6745 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, 6746 int dw, int dh) { 6747 // TODO: Multidisplay: for now only use with default display. 6748 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6749 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6750 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 6751 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 6752 if (curSize == 0 || size < curSize) { 6753 curSize = size; 6754 } 6755 return curSize; 6756 } 6757 6758 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) { 6759 // TODO: Multidisplay: for now only use with default display. 6760 mTmpDisplayMetrics.setTo(dm); 6761 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 6762 final int unrotDw, unrotDh; 6763 if (rotated) { 6764 unrotDw = dh; 6765 unrotDh = dw; 6766 } else { 6767 unrotDw = dw; 6768 unrotDh = dh; 6769 } 6770 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh); 6771 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw); 6772 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh); 6773 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw); 6774 return sw; 6775 } 6776 6777 boolean computeScreenConfigurationLocked(Configuration config) { 6778 if (!mDisplayReady) { 6779 return false; 6780 } 6781 6782 // TODO(multidisplay): For now, apply Configuration to main screen only. 6783 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6784 6785 // Use the effective "visual" dimensions based on current rotation 6786 final boolean rotated = (mRotation == Surface.ROTATION_90 6787 || mRotation == Surface.ROTATION_270); 6788 final int realdw = rotated ? 6789 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; 6790 final int realdh = rotated ? 6791 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; 6792 int dw = realdw; 6793 int dh = realdh; 6794 6795 if (mAltOrientation) { 6796 if (realdw > realdh) { 6797 // Turn landscape into portrait. 6798 int maxw = (int)(realdh/1.3f); 6799 if (maxw < realdw) { 6800 dw = maxw; 6801 } 6802 } else { 6803 // Turn portrait into landscape. 6804 int maxh = (int)(realdw/1.3f); 6805 if (maxh < realdh) { 6806 dh = maxh; 6807 } 6808 } 6809 } 6810 6811 if (config != null) { 6812 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : 6813 Configuration.ORIENTATION_LANDSCAPE; 6814 } 6815 6816 // Update application display metrics. 6817 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); 6818 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); 6819 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6820 synchronized(displayContent.mDisplaySizeLock) { 6821 displayInfo.rotation = mRotation; 6822 displayInfo.logicalWidth = dw; 6823 displayInfo.logicalHeight = dh; 6824 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; 6825 displayInfo.appWidth = appWidth; 6826 displayInfo.appHeight = appHeight; 6827 displayInfo.getLogicalMetrics(mRealDisplayMetrics, 6828 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 6829 displayInfo.getAppMetrics(mDisplayMetrics); 6830 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 6831 displayContent.getDisplayId(), displayInfo); 6832 } 6833 if (false) { 6834 Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); 6835 } 6836 6837 final DisplayMetrics dm = mDisplayMetrics; 6838 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, 6839 mCompatDisplayMetrics); 6840 6841 if (config != null) { 6842 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) 6843 / dm.density); 6844 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) 6845 / dm.density); 6846 computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config); 6847 6848 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 6849 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 6850 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); 6851 config.densityDpi = displayContent.mBaseDisplayDensity; 6852 6853 // Update the configuration based on available input devices, lid switch, 6854 // and platform configuration. 6855 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6856 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6857 config.navigation = Configuration.NAVIGATION_NONAV; 6858 6859 int keyboardPresence = 0; 6860 int navigationPresence = 0; 6861 final InputDevice[] devices = mInputManager.getInputDevices(); 6862 final int len = devices.length; 6863 for (int i = 0; i < len; i++) { 6864 InputDevice device = devices[i]; 6865 if (!device.isVirtual()) { 6866 final int sources = device.getSources(); 6867 final int presenceFlag = device.isExternal() ? 6868 WindowManagerPolicy.PRESENCE_EXTERNAL : 6869 WindowManagerPolicy.PRESENCE_INTERNAL; 6870 6871 if (mIsTouchDevice) { 6872 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 6873 InputDevice.SOURCE_TOUCHSCREEN) { 6874 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 6875 } 6876 } else { 6877 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6878 } 6879 6880 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 6881 config.navigation = Configuration.NAVIGATION_TRACKBALL; 6882 navigationPresence |= presenceFlag; 6883 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 6884 && config.navigation == Configuration.NAVIGATION_NONAV) { 6885 config.navigation = Configuration.NAVIGATION_DPAD; 6886 navigationPresence |= presenceFlag; 6887 } 6888 6889 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 6890 config.keyboard = Configuration.KEYBOARD_QWERTY; 6891 keyboardPresence |= presenceFlag; 6892 } 6893 } 6894 } 6895 6896 // Determine whether a hard keyboard is available and enabled. 6897 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 6898 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 6899 mHardKeyboardAvailable = hardKeyboardAvailable; 6900 mHardKeyboardEnabled = hardKeyboardAvailable; 6901 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6902 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6903 } 6904 if (!mHardKeyboardEnabled) { 6905 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6906 } 6907 6908 // Let the policy update hidden states. 6909 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 6910 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 6911 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 6912 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 6913 } 6914 6915 return true; 6916 } 6917 6918 public boolean isHardKeyboardAvailable() { 6919 synchronized (mWindowMap) { 6920 return mHardKeyboardAvailable; 6921 } 6922 } 6923 6924 public boolean isHardKeyboardEnabled() { 6925 synchronized (mWindowMap) { 6926 return mHardKeyboardEnabled; 6927 } 6928 } 6929 6930 public void setHardKeyboardEnabled(boolean enabled) { 6931 synchronized (mWindowMap) { 6932 if (mHardKeyboardEnabled != enabled) { 6933 mHardKeyboardEnabled = enabled; 6934 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6935 } 6936 } 6937 } 6938 6939 public void setOnHardKeyboardStatusChangeListener( 6940 OnHardKeyboardStatusChangeListener listener) { 6941 synchronized (mWindowMap) { 6942 mHardKeyboardStatusChangeListener = listener; 6943 } 6944 } 6945 6946 void notifyHardKeyboardStatusChange() { 6947 final boolean available, enabled; 6948 final OnHardKeyboardStatusChangeListener listener; 6949 synchronized (mWindowMap) { 6950 listener = mHardKeyboardStatusChangeListener; 6951 available = mHardKeyboardAvailable; 6952 enabled = mHardKeyboardEnabled; 6953 } 6954 if (listener != null) { 6955 listener.onHardKeyboardStatusChange(available, enabled); 6956 } 6957 } 6958 6959 // ------------------------------------------------------------- 6960 // Drag and drop 6961 // ------------------------------------------------------------- 6962 6963 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 6964 int flags, int width, int height, Surface outSurface) { 6965 if (DEBUG_DRAG) { 6966 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 6967 + " flags=" + Integer.toHexString(flags) + " win=" + window 6968 + " asbinder=" + window.asBinder()); 6969 } 6970 6971 final int callerPid = Binder.getCallingPid(); 6972 final long origId = Binder.clearCallingIdentity(); 6973 IBinder token = null; 6974 6975 try { 6976 synchronized (mWindowMap) { 6977 try { 6978 if (mDragState == null) { 6979 // TODO(multi-display): support other displays 6980 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6981 final Display display = displayContent.getDisplay(); 6982 SurfaceControl surface = new SurfaceControl(session, "drag surface", 6983 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 6984 surface.setLayerStack(display.getLayerStack()); 6985 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 6986 + surface + ": CREATE"); 6987 outSurface.copyFrom(surface); 6988 final IBinder winBinder = window.asBinder(); 6989 token = new Binder(); 6990 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 6991 token = mDragState.mToken = new Binder(); 6992 6993 // 5 second timeout for this window to actually begin the drag 6994 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 6995 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 6996 mH.sendMessageDelayed(msg, 5000); 6997 } else { 6998 Slog.w(TAG, "Drag already in progress"); 6999 } 7000 } catch (OutOfResourcesException e) { 7001 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 7002 if (mDragState != null) { 7003 mDragState.reset(); 7004 mDragState = null; 7005 } 7006 } 7007 } 7008 } finally { 7009 Binder.restoreCallingIdentity(origId); 7010 } 7011 7012 return token; 7013 } 7014 7015 // ------------------------------------------------------------- 7016 // Input Events and Focus Management 7017 // ------------------------------------------------------------- 7018 7019 final InputMonitor mInputMonitor = new InputMonitor(this); 7020 private boolean mEventDispatchingEnabled; 7021 7022 @Override 7023 public void pauseKeyDispatching(IBinder _token) { 7024 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7025 "pauseKeyDispatching()")) { 7026 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7027 } 7028 7029 synchronized (mWindowMap) { 7030 WindowToken token = mTokenMap.get(_token); 7031 if (token != null) { 7032 mInputMonitor.pauseDispatchingLw(token); 7033 } 7034 } 7035 } 7036 7037 @Override 7038 public void resumeKeyDispatching(IBinder _token) { 7039 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7040 "resumeKeyDispatching()")) { 7041 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7042 } 7043 7044 synchronized (mWindowMap) { 7045 WindowToken token = mTokenMap.get(_token); 7046 if (token != null) { 7047 mInputMonitor.resumeDispatchingLw(token); 7048 } 7049 } 7050 } 7051 7052 @Override 7053 public void setEventDispatching(boolean enabled) { 7054 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7055 "setEventDispatching()")) { 7056 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7057 } 7058 7059 synchronized (mWindowMap) { 7060 mEventDispatchingEnabled = enabled; 7061 if (mDisplayEnabled) { 7062 mInputMonitor.setEventDispatchingLw(enabled); 7063 } 7064 } 7065 } 7066 7067 private WindowState getFocusedWindow() { 7068 synchronized (mWindowMap) { 7069 return getFocusedWindowLocked(); 7070 } 7071 } 7072 7073 private WindowState getFocusedWindowLocked() { 7074 return mCurrentFocus; 7075 } 7076 7077 public boolean detectSafeMode() { 7078 if (!mInputMonitor.waitForInputDevicesReady( 7079 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 7080 Slog.w(TAG, "Devices still not ready after waiting " 7081 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 7082 + " milliseconds before attempting to detect safe mode."); 7083 } 7084 7085 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7086 KeyEvent.KEYCODE_MENU); 7087 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 7088 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 7089 KeyEvent.KEYCODE_DPAD_CENTER); 7090 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 7091 InputManagerService.BTN_MOUSE); 7092 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7093 KeyEvent.KEYCODE_VOLUME_DOWN); 7094 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 7095 || volumeDownState > 0; 7096 try { 7097 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 7098 mSafeMode = true; 7099 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 7100 } 7101 } catch (IllegalArgumentException e) { 7102 } 7103 if (mSafeMode) { 7104 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 7105 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 7106 } else { 7107 Log.i(TAG, "SAFE MODE not enabled"); 7108 } 7109 mPolicy.setSafeMode(mSafeMode); 7110 return mSafeMode; 7111 } 7112 7113 public void displayReady() { 7114 displayReady(Display.DEFAULT_DISPLAY); 7115 7116 synchronized(mWindowMap) { 7117 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7118 readForcedDisplaySizeAndDensityLocked(displayContent); 7119 mDisplayReady = true; 7120 } 7121 7122 try { 7123 mActivityManager.updateConfiguration(null); 7124 } catch (RemoteException e) { 7125 } 7126 7127 synchronized(mWindowMap) { 7128 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 7129 PackageManager.FEATURE_TOUCHSCREEN); 7130 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 7131 } 7132 7133 try { 7134 mActivityManager.updateConfiguration(null); 7135 } catch (RemoteException e) { 7136 } 7137 } 7138 7139 private void displayReady(int displayId) { 7140 synchronized(mWindowMap) { 7141 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7142 if (displayContent != null) { 7143 mAnimator.addDisplayLocked(displayId); 7144 synchronized(displayContent.mDisplaySizeLock) { 7145 // Bootstrap the default logical display from the display manager. 7146 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7147 DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId); 7148 if (newDisplayInfo != null) { 7149 displayInfo.copyFrom(newDisplayInfo); 7150 } 7151 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; 7152 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; 7153 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; 7154 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; 7155 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; 7156 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; 7157 displayContent.mBaseDisplayRect.set(0, 0, 7158 displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight); 7159 } 7160 } 7161 } 7162 } 7163 7164 public void systemReady() { 7165 mPolicy.systemReady(); 7166 } 7167 7168 // ------------------------------------------------------------- 7169 // Async Handler 7170 // ------------------------------------------------------------- 7171 7172 final class H extends Handler { 7173 public static final int REPORT_FOCUS_CHANGE = 2; 7174 public static final int REPORT_LOSING_FOCUS = 3; 7175 public static final int DO_TRAVERSAL = 4; 7176 public static final int ADD_STARTING = 5; 7177 public static final int REMOVE_STARTING = 6; 7178 public static final int FINISHED_STARTING = 7; 7179 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 7180 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 7181 public static final int WINDOW_FREEZE_TIMEOUT = 11; 7182 7183 public static final int APP_TRANSITION_TIMEOUT = 13; 7184 public static final int PERSIST_ANIMATION_SCALE = 14; 7185 public static final int FORCE_GC = 15; 7186 public static final int ENABLE_SCREEN = 16; 7187 public static final int APP_FREEZE_TIMEOUT = 17; 7188 public static final int SEND_NEW_CONFIGURATION = 18; 7189 public static final int REPORT_WINDOWS_CHANGE = 19; 7190 public static final int DRAG_START_TIMEOUT = 20; 7191 public static final int DRAG_END_TIMEOUT = 21; 7192 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 7193 public static final int BOOT_TIMEOUT = 23; 7194 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 7195 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 7196 public static final int DO_ANIMATION_CALLBACK = 26; 7197 7198 public static final int DO_DISPLAY_ADDED = 27; 7199 public static final int DO_DISPLAY_REMOVED = 28; 7200 public static final int DO_DISPLAY_CHANGED = 29; 7201 7202 public static final int CLIENT_FREEZE_TIMEOUT = 30; 7203 public static final int TAP_OUTSIDE_STACK = 31; 7204 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 7205 7206 public static final int ALL_WINDOWS_DRAWN = 33; 7207 7208 public static final int NEW_ANIMATOR_SCALE = 34; 7209 7210 @Override 7211 public void handleMessage(Message msg) { 7212 if (DEBUG_WINDOW_TRACE) { 7213 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 7214 } 7215 switch (msg.what) { 7216 case REPORT_FOCUS_CHANGE: { 7217 WindowState lastFocus; 7218 WindowState newFocus; 7219 7220 synchronized(mWindowMap) { 7221 lastFocus = mLastFocus; 7222 newFocus = mCurrentFocus; 7223 if (lastFocus == newFocus) { 7224 // Focus is not changing, so nothing to do. 7225 return; 7226 } 7227 mLastFocus = newFocus; 7228 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus + 7229 " to " + newFocus); 7230 if (newFocus != null && lastFocus != null 7231 && !newFocus.isDisplayedLw()) { 7232 //Slog.i(TAG, "Delaying loss of focus..."); 7233 mLosingFocus.add(lastFocus); 7234 lastFocus = null; 7235 } 7236 } 7237 7238 //System.out.println("Changing focus from " + lastFocus 7239 // + " to " + newFocus); 7240 if (newFocus != null) { 7241 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus); 7242 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 7243 notifyFocusChanged(); 7244 } 7245 7246 if (lastFocus != null) { 7247 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus); 7248 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 7249 } 7250 } break; 7251 7252 case REPORT_LOSING_FOCUS: { 7253 ArrayList<WindowState> losers; 7254 7255 synchronized(mWindowMap) { 7256 losers = mLosingFocus; 7257 mLosingFocus = new ArrayList<WindowState>(); 7258 } 7259 7260 final int N = losers.size(); 7261 for (int i=0; i<N; i++) { 7262 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " + 7263 losers.get(i)); 7264 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 7265 } 7266 } break; 7267 7268 case DO_TRAVERSAL: { 7269 synchronized(mWindowMap) { 7270 mTraversalScheduled = false; 7271 performLayoutAndPlaceSurfacesLocked(); 7272 } 7273 } break; 7274 7275 case ADD_STARTING: { 7276 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7277 final StartingData sd = wtoken.startingData; 7278 7279 if (sd == null) { 7280 // Animation has been canceled... do nothing. 7281 return; 7282 } 7283 7284 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 7285 + wtoken + ": pkg=" + sd.pkg); 7286 7287 View view = null; 7288 try { 7289 view = mPolicy.addStartingWindow( 7290 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 7291 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags); 7292 } catch (Exception e) { 7293 Slog.w(TAG, "Exception when adding starting window", e); 7294 } 7295 7296 if (view != null) { 7297 boolean abort = false; 7298 7299 synchronized(mWindowMap) { 7300 if (wtoken.removed || wtoken.startingData == null) { 7301 // If the window was successfully added, then 7302 // we need to remove it. 7303 if (wtoken.startingWindow != null) { 7304 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7305 "Aborted starting " + wtoken 7306 + ": removed=" + wtoken.removed 7307 + " startingData=" + wtoken.startingData); 7308 wtoken.startingWindow = null; 7309 wtoken.startingData = null; 7310 abort = true; 7311 } 7312 } else { 7313 wtoken.startingView = view; 7314 } 7315 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7316 "Added starting " + wtoken 7317 + ": startingWindow=" 7318 + wtoken.startingWindow + " startingView=" 7319 + wtoken.startingView); 7320 } 7321 7322 if (abort) { 7323 try { 7324 mPolicy.removeStartingWindow(wtoken.token, view); 7325 } catch (Exception e) { 7326 Slog.w(TAG, "Exception when removing starting window", e); 7327 } 7328 } 7329 } 7330 } break; 7331 7332 case REMOVE_STARTING: { 7333 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7334 IBinder token = null; 7335 View view = null; 7336 synchronized (mWindowMap) { 7337 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7338 + wtoken + ": startingWindow=" 7339 + wtoken.startingWindow + " startingView=" 7340 + wtoken.startingView); 7341 if (wtoken.startingWindow != null) { 7342 view = wtoken.startingView; 7343 token = wtoken.token; 7344 wtoken.startingData = null; 7345 wtoken.startingView = null; 7346 wtoken.startingWindow = null; 7347 wtoken.startingDisplayed = false; 7348 } 7349 } 7350 if (view != null) { 7351 try { 7352 mPolicy.removeStartingWindow(token, view); 7353 } catch (Exception e) { 7354 Slog.w(TAG, "Exception when removing starting window", e); 7355 } 7356 } 7357 } break; 7358 7359 case FINISHED_STARTING: { 7360 IBinder token = null; 7361 View view = null; 7362 while (true) { 7363 synchronized (mWindowMap) { 7364 final int N = mFinishedStarting.size(); 7365 if (N <= 0) { 7366 break; 7367 } 7368 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7369 7370 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7371 "Finished starting " + wtoken 7372 + ": startingWindow=" + wtoken.startingWindow 7373 + " startingView=" + wtoken.startingView); 7374 7375 if (wtoken.startingWindow == null) { 7376 continue; 7377 } 7378 7379 view = wtoken.startingView; 7380 token = wtoken.token; 7381 wtoken.startingData = null; 7382 wtoken.startingView = null; 7383 wtoken.startingWindow = null; 7384 wtoken.startingDisplayed = false; 7385 } 7386 7387 try { 7388 mPolicy.removeStartingWindow(token, view); 7389 } catch (Exception e) { 7390 Slog.w(TAG, "Exception when removing starting window", e); 7391 } 7392 } 7393 } break; 7394 7395 case REPORT_APPLICATION_TOKEN_DRAWN: { 7396 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7397 7398 try { 7399 if (DEBUG_VISIBILITY) Slog.v( 7400 TAG, "Reporting drawn in " + wtoken); 7401 wtoken.appToken.windowsDrawn(); 7402 } catch (RemoteException ex) { 7403 } 7404 } break; 7405 7406 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7407 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7408 7409 boolean nowVisible = msg.arg1 != 0; 7410 boolean nowGone = msg.arg2 != 0; 7411 7412 try { 7413 if (DEBUG_VISIBILITY) Slog.v( 7414 TAG, "Reporting visible in " + wtoken 7415 + " visible=" + nowVisible 7416 + " gone=" + nowGone); 7417 if (nowVisible) { 7418 wtoken.appToken.windowsVisible(); 7419 } else { 7420 wtoken.appToken.windowsGone(); 7421 } 7422 } catch (RemoteException ex) { 7423 } 7424 } break; 7425 7426 case WINDOW_FREEZE_TIMEOUT: { 7427 // TODO(multidisplay): Can non-default displays rotate? 7428 synchronized (mWindowMap) { 7429 Slog.w(TAG, "Window freeze timeout expired."); 7430 final WindowList windows = getDefaultWindowListLocked(); 7431 int i = windows.size(); 7432 while (i > 0) { 7433 i--; 7434 WindowState w = windows.get(i); 7435 if (w.mOrientationChanging) { 7436 w.mOrientationChanging = false; 7437 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 7438 - mDisplayFreezeTime); 7439 Slog.w(TAG, "Force clearing orientation change: " + w); 7440 } 7441 } 7442 performLayoutAndPlaceSurfacesLocked(); 7443 } 7444 break; 7445 } 7446 7447 case APP_TRANSITION_TIMEOUT: { 7448 synchronized (mWindowMap) { 7449 if (mAppTransition.isTransitionSet()) { 7450 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT"); 7451 mAppTransition.setTimeout(); 7452 performLayoutAndPlaceSurfacesLocked(); 7453 } 7454 } 7455 break; 7456 } 7457 7458 case PERSIST_ANIMATION_SCALE: { 7459 Settings.Global.putFloat(mContext.getContentResolver(), 7460 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 7461 Settings.Global.putFloat(mContext.getContentResolver(), 7462 Settings.Global.TRANSITION_ANIMATION_SCALE, 7463 mTransitionAnimationScaleSetting); 7464 Settings.Global.putFloat(mContext.getContentResolver(), 7465 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting); 7466 break; 7467 } 7468 7469 case FORCE_GC: { 7470 synchronized (mWindowMap) { 7471 // Since we're holding both mWindowMap and mAnimator we don't need to 7472 // hold mAnimator.mLayoutToAnim. 7473 if (mAnimator.mAnimating || mAnimationScheduled) { 7474 // If we are animating, don't do the gc now but 7475 // delay a bit so we don't interrupt the animation. 7476 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 7477 return; 7478 } 7479 // If we are currently rotating the display, it will 7480 // schedule a new message when done. 7481 if (mDisplayFrozen) { 7482 return; 7483 } 7484 } 7485 Runtime.getRuntime().gc(); 7486 break; 7487 } 7488 7489 case ENABLE_SCREEN: { 7490 performEnableScreen(); 7491 break; 7492 } 7493 7494 case APP_FREEZE_TIMEOUT: { 7495 synchronized (mWindowMap) { 7496 Slog.w(TAG, "App freeze timeout expired."); 7497 final int numStacks = mStackIdToStack.size(); 7498 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 7499 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 7500 final ArrayList<Task> tasks = stack.getTasks(); 7501 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 7502 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 7503 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 7504 AppWindowToken tok = tokens.get(tokenNdx); 7505 if (tok.mAppAnimator.freezingScreen) { 7506 Slog.w(TAG, "Force clearing freeze: " + tok); 7507 unsetAppFreezingScreenLocked(tok, true, true); 7508 } 7509 } 7510 } 7511 } 7512 } 7513 break; 7514 } 7515 7516 case CLIENT_FREEZE_TIMEOUT: { 7517 synchronized (mWindowMap) { 7518 if (mClientFreezingScreen) { 7519 mClientFreezingScreen = false; 7520 mLastFinishedFreezeSource = "client-timeout"; 7521 stopFreezingDisplayLocked(); 7522 } 7523 } 7524 break; 7525 } 7526 7527 case SEND_NEW_CONFIGURATION: { 7528 removeMessages(SEND_NEW_CONFIGURATION); 7529 sendNewConfiguration(); 7530 break; 7531 } 7532 7533 case REPORT_WINDOWS_CHANGE: { 7534 if (mWindowsChanged) { 7535 synchronized (mWindowMap) { 7536 mWindowsChanged = false; 7537 } 7538 notifyWindowsChanged(); 7539 } 7540 break; 7541 } 7542 7543 case DRAG_START_TIMEOUT: { 7544 IBinder win = (IBinder)msg.obj; 7545 if (DEBUG_DRAG) { 7546 Slog.w(TAG, "Timeout starting drag by win " + win); 7547 } 7548 synchronized (mWindowMap) { 7549 // !!! TODO: ANR the app that has failed to start the drag in time 7550 if (mDragState != null) { 7551 mDragState.unregister(); 7552 mInputMonitor.updateInputWindowsLw(true /*force*/); 7553 mDragState.reset(); 7554 mDragState = null; 7555 } 7556 } 7557 break; 7558 } 7559 7560 case DRAG_END_TIMEOUT: { 7561 IBinder win = (IBinder)msg.obj; 7562 if (DEBUG_DRAG) { 7563 Slog.w(TAG, "Timeout ending drag to win " + win); 7564 } 7565 synchronized (mWindowMap) { 7566 // !!! TODO: ANR the drag-receiving app 7567 if (mDragState != null) { 7568 mDragState.mDragResult = false; 7569 mDragState.endDragLw(); 7570 } 7571 } 7572 break; 7573 } 7574 7575 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7576 notifyHardKeyboardStatusChange(); 7577 break; 7578 } 7579 7580 case BOOT_TIMEOUT: { 7581 performBootTimeout(); 7582 break; 7583 } 7584 7585 case WAITING_FOR_DRAWN_TIMEOUT: { 7586 Runnable callback = null; 7587 synchronized (mWindowMap) { 7588 Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn); 7589 mWaitingForDrawn.clear(); 7590 callback = mWaitingForDrawnCallback; 7591 mWaitingForDrawnCallback = null; 7592 } 7593 if (callback != null) { 7594 callback.run(); 7595 } 7596 break; 7597 } 7598 7599 case SHOW_STRICT_MODE_VIOLATION: { 7600 showStrictModeViolation(msg.arg1, msg.arg2); 7601 break; 7602 } 7603 7604 case DO_ANIMATION_CALLBACK: { 7605 try { 7606 ((IRemoteCallback)msg.obj).sendResult(null); 7607 } catch (RemoteException e) { 7608 } 7609 break; 7610 } 7611 7612 case DO_DISPLAY_ADDED: 7613 handleDisplayAdded(msg.arg1); 7614 break; 7615 7616 case DO_DISPLAY_REMOVED: 7617 synchronized (mWindowMap) { 7618 handleDisplayRemovedLocked(msg.arg1); 7619 } 7620 break; 7621 7622 case DO_DISPLAY_CHANGED: 7623 synchronized (mWindowMap) { 7624 handleDisplayChangedLocked(msg.arg1); 7625 } 7626 break; 7627 7628 case TAP_OUTSIDE_STACK: { 7629 int stackId; 7630 synchronized (mWindowMap) { 7631 stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2); 7632 } 7633 if (stackId >= 0) { 7634 try { 7635 mActivityManager.setFocusedStack(stackId); 7636 } catch (RemoteException e) { 7637 } 7638 } 7639 } 7640 break; 7641 case NOTIFY_ACTIVITY_DRAWN: 7642 try { 7643 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 7644 } catch (RemoteException e) { 7645 } 7646 break; 7647 case ALL_WINDOWS_DRAWN: { 7648 Runnable callback; 7649 synchronized (mWindowMap) { 7650 callback = mWaitingForDrawnCallback; 7651 mWaitingForDrawnCallback = null; 7652 } 7653 if (callback != null) { 7654 callback.run(); 7655 } 7656 } 7657 case NEW_ANIMATOR_SCALE: { 7658 float scale = getCurrentAnimatorScale(); 7659 ValueAnimator.setDurationScale(scale); 7660 Session session = (Session)msg.obj; 7661 if (session != null) { 7662 try { 7663 session.mCallback.onAnimatorScaleChanged(scale); 7664 } catch (RemoteException e) { 7665 } 7666 } else { 7667 ArrayList<IWindowSessionCallback> callbacks 7668 = new ArrayList<IWindowSessionCallback>(); 7669 synchronized (mWindowMap) { 7670 for (int i=0; i<mSessions.size(); i++) { 7671 callbacks.add(mSessions.valueAt(i).mCallback); 7672 } 7673 7674 } 7675 for (int i=0; i<callbacks.size(); i++) { 7676 try { 7677 callbacks.get(i).onAnimatorScaleChanged(scale); 7678 } catch (RemoteException e) { 7679 } 7680 } 7681 } 7682 } 7683 break; 7684 } 7685 if (DEBUG_WINDOW_TRACE) { 7686 Slog.v(TAG, "handleMessage: exit"); 7687 } 7688 } 7689 } 7690 7691 // ------------------------------------------------------------- 7692 // IWindowManager API 7693 // ------------------------------------------------------------- 7694 7695 @Override 7696 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, 7697 IInputContext inputContext) { 7698 if (client == null) throw new IllegalArgumentException("null client"); 7699 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7700 Session session = new Session(this, callback, client, inputContext); 7701 return session; 7702 } 7703 7704 @Override 7705 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7706 synchronized (mWindowMap) { 7707 // The focus for the client is the window immediately below 7708 // where we would place the input method window. 7709 int idx = findDesiredInputMethodWindowIndexLocked(false); 7710 if (idx > 0) { 7711 // TODO(multidisplay): IMEs are only supported on the default display. 7712 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 7713 if (DEBUG_INPUT_METHOD) { 7714 Slog.i(TAG, "Desired input method target: " + imFocus); 7715 Slog.i(TAG, "Current focus: " + mCurrentFocus); 7716 Slog.i(TAG, "Last focus: " + mLastFocus); 7717 } 7718 if (imFocus != null) { 7719 // This may be a starting window, in which case we still want 7720 // to count it as okay. 7721 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7722 && imFocus.mAppToken != null) { 7723 // The client has definitely started, so it really should 7724 // have a window in this app token. Let's look for it. 7725 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7726 WindowState w = imFocus.mAppToken.windows.get(i); 7727 if (w != imFocus) { 7728 Log.i(TAG, "Switching to real app window: " + w); 7729 imFocus = w; 7730 break; 7731 } 7732 } 7733 } 7734 if (DEBUG_INPUT_METHOD) { 7735 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7736 if (imFocus.mSession.mClient != null) { 7737 Slog.i(TAG, "IM target client binder: " 7738 + imFocus.mSession.mClient.asBinder()); 7739 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 7740 } 7741 } 7742 if (imFocus.mSession.mClient != null && 7743 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7744 return true; 7745 } 7746 } 7747 } 7748 7749 // Okay, how about this... what is the current focus? 7750 // It seems in some cases we may not have moved the IM 7751 // target window, such as when it was in a pop-up window, 7752 // so let's also look at the current focus. (An example: 7753 // go to Gmail, start searching so the keyboard goes up, 7754 // press home. Sometimes the IME won't go down.) 7755 // Would be nice to fix this more correctly, but it's 7756 // way at the end of a release, and this should be good enough. 7757 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 7758 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7759 return true; 7760 } 7761 } 7762 return false; 7763 } 7764 7765 @Override 7766 public void getInitialDisplaySize(int displayId, Point size) { 7767 synchronized (mWindowMap) { 7768 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7769 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7770 synchronized(displayContent.mDisplaySizeLock) { 7771 size.x = displayContent.mInitialDisplayWidth; 7772 size.y = displayContent.mInitialDisplayHeight; 7773 } 7774 } 7775 } 7776 } 7777 7778 @Override 7779 public void getBaseDisplaySize(int displayId, Point size) { 7780 synchronized (mWindowMap) { 7781 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7782 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7783 synchronized(displayContent.mDisplaySizeLock) { 7784 size.x = displayContent.mBaseDisplayWidth; 7785 size.y = displayContent.mBaseDisplayHeight; 7786 } 7787 } 7788 } 7789 } 7790 7791 @Override 7792 public void setForcedDisplaySize(int displayId, int width, int height) { 7793 if (mContext.checkCallingOrSelfPermission( 7794 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7795 PackageManager.PERMISSION_GRANTED) { 7796 throw new SecurityException("Must hold permission " + 7797 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7798 } 7799 if (displayId != Display.DEFAULT_DISPLAY) { 7800 throw new IllegalArgumentException("Can only set the default display"); 7801 } 7802 final long ident = Binder.clearCallingIdentity(); 7803 try { 7804 synchronized(mWindowMap) { 7805 // Set some sort of reasonable bounds on the size of the display that we 7806 // will try to emulate. 7807 final int MIN_WIDTH = 200; 7808 final int MIN_HEIGHT = 200; 7809 final int MAX_SCALE = 2; 7810 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7811 if (displayContent != null) { 7812 width = Math.min(Math.max(width, MIN_WIDTH), 7813 displayContent.mInitialDisplayWidth * MAX_SCALE); 7814 height = Math.min(Math.max(height, MIN_HEIGHT), 7815 displayContent.mInitialDisplayHeight * MAX_SCALE); 7816 setForcedDisplaySizeLocked(displayContent, width, height); 7817 Settings.Global.putString(mContext.getContentResolver(), 7818 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 7819 } 7820 } 7821 } finally { 7822 Binder.restoreCallingIdentity(ident); 7823 } 7824 } 7825 7826 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 7827 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 7828 Settings.Global.DISPLAY_SIZE_FORCED); 7829 if (sizeStr == null || sizeStr.length() == 0) { 7830 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 7831 } 7832 if (sizeStr != null && sizeStr.length() > 0) { 7833 final int pos = sizeStr.indexOf(','); 7834 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 7835 int width, height; 7836 try { 7837 width = Integer.parseInt(sizeStr.substring(0, pos)); 7838 height = Integer.parseInt(sizeStr.substring(pos+1)); 7839 synchronized(displayContent.mDisplaySizeLock) { 7840 if (displayContent.mBaseDisplayWidth != width 7841 || displayContent.mBaseDisplayHeight != height) { 7842 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 7843 displayContent.mBaseDisplayWidth = width; 7844 displayContent.mBaseDisplayHeight = height; 7845 } 7846 } 7847 } catch (NumberFormatException ex) { 7848 } 7849 } 7850 } 7851 String densityStr = Settings.Global.getString(mContext.getContentResolver(), 7852 Settings.Global.DISPLAY_DENSITY_FORCED); 7853 if (densityStr == null || densityStr.length() == 0) { 7854 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 7855 } 7856 if (densityStr != null && densityStr.length() > 0) { 7857 int density; 7858 try { 7859 density = Integer.parseInt(densityStr); 7860 synchronized(displayContent.mDisplaySizeLock) { 7861 if (displayContent.mBaseDisplayDensity != density) { 7862 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 7863 displayContent.mBaseDisplayDensity = density; 7864 } 7865 } 7866 } catch (NumberFormatException ex) { 7867 } 7868 } 7869 } 7870 7871 // displayContent must not be null 7872 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 7873 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7874 7875 synchronized(displayContent.mDisplaySizeLock) { 7876 displayContent.mBaseDisplayWidth = width; 7877 displayContent.mBaseDisplayHeight = height; 7878 } 7879 reconfigureDisplayLocked(displayContent); 7880 } 7881 7882 @Override 7883 public void clearForcedDisplaySize(int displayId) { 7884 if (mContext.checkCallingOrSelfPermission( 7885 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7886 PackageManager.PERMISSION_GRANTED) { 7887 throw new SecurityException("Must hold permission " + 7888 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7889 } 7890 if (displayId != Display.DEFAULT_DISPLAY) { 7891 throw new IllegalArgumentException("Can only set the default display"); 7892 } 7893 final long ident = Binder.clearCallingIdentity(); 7894 try { 7895 synchronized(mWindowMap) { 7896 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7897 if (displayContent != null) { 7898 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 7899 displayContent.mInitialDisplayHeight); 7900 Settings.Global.putString(mContext.getContentResolver(), 7901 Settings.Global.DISPLAY_SIZE_FORCED, ""); 7902 } 7903 } 7904 } finally { 7905 Binder.restoreCallingIdentity(ident); 7906 } 7907 } 7908 7909 @Override 7910 public int getInitialDisplayDensity(int displayId) { 7911 synchronized (mWindowMap) { 7912 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7913 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7914 synchronized(displayContent.mDisplaySizeLock) { 7915 return displayContent.mInitialDisplayDensity; 7916 } 7917 } 7918 } 7919 return -1; 7920 } 7921 7922 @Override 7923 public int getBaseDisplayDensity(int displayId) { 7924 synchronized (mWindowMap) { 7925 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7926 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7927 synchronized(displayContent.mDisplaySizeLock) { 7928 return displayContent.mBaseDisplayDensity; 7929 } 7930 } 7931 } 7932 return -1; 7933 } 7934 7935 @Override 7936 public void setForcedDisplayDensity(int displayId, int density) { 7937 if (mContext.checkCallingOrSelfPermission( 7938 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7939 PackageManager.PERMISSION_GRANTED) { 7940 throw new SecurityException("Must hold permission " + 7941 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7942 } 7943 if (displayId != Display.DEFAULT_DISPLAY) { 7944 throw new IllegalArgumentException("Can only set the default display"); 7945 } 7946 final long ident = Binder.clearCallingIdentity(); 7947 try { 7948 synchronized(mWindowMap) { 7949 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7950 if (displayContent != null) { 7951 setForcedDisplayDensityLocked(displayContent, density); 7952 Settings.Global.putString(mContext.getContentResolver(), 7953 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 7954 } 7955 } 7956 } finally { 7957 Binder.restoreCallingIdentity(ident); 7958 } 7959 } 7960 7961 // displayContent must not be null 7962 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 7963 Slog.i(TAG, "Using new display density: " + density); 7964 7965 synchronized(displayContent.mDisplaySizeLock) { 7966 displayContent.mBaseDisplayDensity = density; 7967 } 7968 reconfigureDisplayLocked(displayContent); 7969 } 7970 7971 @Override 7972 public void clearForcedDisplayDensity(int displayId) { 7973 if (mContext.checkCallingOrSelfPermission( 7974 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7975 PackageManager.PERMISSION_GRANTED) { 7976 throw new SecurityException("Must hold permission " + 7977 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7978 } 7979 if (displayId != Display.DEFAULT_DISPLAY) { 7980 throw new IllegalArgumentException("Can only set the default display"); 7981 } 7982 final long ident = Binder.clearCallingIdentity(); 7983 try { 7984 synchronized(mWindowMap) { 7985 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7986 if (displayContent != null) { 7987 setForcedDisplayDensityLocked(displayContent, 7988 displayContent.mInitialDisplayDensity); 7989 Settings.Global.putString(mContext.getContentResolver(), 7990 Settings.Global.DISPLAY_DENSITY_FORCED, ""); 7991 } 7992 } 7993 } finally { 7994 Binder.restoreCallingIdentity(ident); 7995 } 7996 } 7997 7998 // displayContent must not be null 7999 private void reconfigureDisplayLocked(DisplayContent displayContent) { 8000 // TODO: Multidisplay: for now only use with default display. 8001 configureDisplayPolicyLocked(displayContent); 8002 displayContent.layoutNeeded = true; 8003 8004 boolean configChanged = updateOrientationFromAppTokensLocked(false); 8005 mTempConfiguration.setToDefaults(); 8006 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 8007 if (computeScreenConfigurationLocked(mTempConfiguration)) { 8008 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 8009 configChanged = true; 8010 } 8011 } 8012 8013 if (configChanged) { 8014 mWaitingForConfig = true; 8015 startFreezingDisplayLocked(false, 0, 0); 8016 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8017 } 8018 8019 performLayoutAndPlaceSurfacesLocked(); 8020 } 8021 8022 private void configureDisplayPolicyLocked(DisplayContent displayContent) { 8023 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 8024 displayContent.mBaseDisplayWidth, 8025 displayContent.mBaseDisplayHeight, 8026 displayContent.mBaseDisplayDensity); 8027 8028 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8029 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 8030 displayInfo.overscanLeft, displayInfo.overscanTop, 8031 displayInfo.overscanRight, displayInfo.overscanBottom); 8032 } 8033 8034 @Override 8035 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 8036 if (mContext.checkCallingOrSelfPermission( 8037 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8038 PackageManager.PERMISSION_GRANTED) { 8039 throw new SecurityException("Must hold permission " + 8040 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8041 } 8042 final long ident = Binder.clearCallingIdentity(); 8043 try { 8044 synchronized(mWindowMap) { 8045 DisplayContent displayContent = getDisplayContentLocked(displayId); 8046 if (displayContent != null) { 8047 setOverscanLocked(displayContent, left, top, right, bottom); 8048 } 8049 } 8050 } finally { 8051 Binder.restoreCallingIdentity(ident); 8052 } 8053 } 8054 8055 private void setOverscanLocked(DisplayContent displayContent, 8056 int left, int top, int right, int bottom) { 8057 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8058 synchronized (displayContent.mDisplaySizeLock) { 8059 displayInfo.overscanLeft = left; 8060 displayInfo.overscanTop = top; 8061 displayInfo.overscanRight = right; 8062 displayInfo.overscanBottom = bottom; 8063 } 8064 8065 mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom); 8066 mDisplaySettings.writeSettingsLocked(); 8067 8068 reconfigureDisplayLocked(displayContent); 8069 } 8070 8071 // ------------------------------------------------------------- 8072 // Internals 8073 // ------------------------------------------------------------- 8074 8075 final WindowState windowForClientLocked(Session session, IWindow client, 8076 boolean throwOnError) { 8077 return windowForClientLocked(session, client.asBinder(), throwOnError); 8078 } 8079 8080 final WindowState windowForClientLocked(Session session, IBinder client, 8081 boolean throwOnError) { 8082 WindowState win = mWindowMap.get(client); 8083 if (localLOGV) Slog.v( 8084 TAG, "Looking up client " + client + ": " + win); 8085 if (win == null) { 8086 RuntimeException ex = new IllegalArgumentException( 8087 "Requested window " + client + " does not exist"); 8088 if (throwOnError) { 8089 throw ex; 8090 } 8091 Slog.w(TAG, "Failed looking up window", ex); 8092 return null; 8093 } 8094 if (session != null && win.mSession != session) { 8095 RuntimeException ex = new IllegalArgumentException( 8096 "Requested window " + client + " is in session " + 8097 win.mSession + ", not " + session); 8098 if (throwOnError) { 8099 throw ex; 8100 } 8101 Slog.w(TAG, "Failed looking up window", ex); 8102 return null; 8103 } 8104 8105 return win; 8106 } 8107 8108 final void rebuildAppWindowListLocked() { 8109 rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); 8110 } 8111 8112 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 8113 final WindowList windows = displayContent.getWindowList(); 8114 int NW = windows.size(); 8115 int i; 8116 int lastBelow = -1; 8117 int numRemoved = 0; 8118 8119 if (mRebuildTmp.length < NW) { 8120 mRebuildTmp = new WindowState[NW+10]; 8121 } 8122 8123 // First remove all existing app windows. 8124 i=0; 8125 while (i < NW) { 8126 WindowState w = windows.get(i); 8127 if (w.mAppToken != null) { 8128 WindowState win = windows.remove(i); 8129 win.mRebuilding = true; 8130 mRebuildTmp[numRemoved] = win; 8131 mWindowsChanged = true; 8132 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win); 8133 NW--; 8134 numRemoved++; 8135 continue; 8136 } else if (lastBelow == i-1) { 8137 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8138 lastBelow = i; 8139 } 8140 } 8141 i++; 8142 } 8143 8144 // Keep whatever windows were below the app windows still below, 8145 // by skipping them. 8146 lastBelow++; 8147 i = lastBelow; 8148 8149 // First add all of the exiting app tokens... these are no longer 8150 // in the main app list, but still have windows shown. We put them 8151 // in the back because now that the animation is over we no longer 8152 // will care about them. 8153 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 8154 final int numStacks = stacks.size(); 8155 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8156 AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens; 8157 int NT = exitingAppTokens.size(); 8158 for (int j = 0; j < NT; j++) { 8159 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 8160 } 8161 } 8162 8163 // And add in the still active app tokens in Z order. 8164 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8165 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8166 final int numTasks = tasks.size(); 8167 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 8168 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8169 final int numTokens = tokens.size(); 8170 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 8171 final AppWindowToken wtoken = tokens.get(tokenNdx); 8172 if (wtoken.mDeferRemoval) { 8173 continue; 8174 } 8175 i = reAddAppWindowsLocked(displayContent, i, wtoken); 8176 } 8177 } 8178 } 8179 8180 i -= lastBelow; 8181 if (i != numRemoved) { 8182 Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " + 8183 numRemoved + " windows but added " + i, 8184 new RuntimeException("here").fillInStackTrace()); 8185 for (i=0; i<numRemoved; i++) { 8186 WindowState ws = mRebuildTmp[i]; 8187 if (ws.mRebuilding) { 8188 StringWriter sw = new StringWriter(); 8189 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 8190 ws.dump(pw, "", true); 8191 pw.flush(); 8192 Slog.w(TAG, "This window was lost: " + ws); 8193 Slog.w(TAG, sw.toString()); 8194 ws.mWinAnimator.destroySurfaceLocked(); 8195 } 8196 } 8197 Slog.w(TAG, "Current app token list:"); 8198 dumpAppTokensLocked(); 8199 Slog.w(TAG, "Final window list:"); 8200 dumpWindowsLocked(); 8201 } 8202 } 8203 8204 private final void assignLayersLocked(WindowList windows) { 8205 int N = windows.size(); 8206 int curBaseLayer = 0; 8207 int curLayer = 0; 8208 int i; 8209 8210 if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows, 8211 new RuntimeException("here").fillInStackTrace()); 8212 8213 boolean anyLayerChanged = false; 8214 8215 for (i=0; i<N; i++) { 8216 final WindowState w = windows.get(i); 8217 final WindowStateAnimator winAnimator = w.mWinAnimator; 8218 boolean layerChanged = false; 8219 int oldLayer = w.mLayer; 8220 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 8221 || (i > 0 && w.mIsWallpaper)) { 8222 curLayer += WINDOW_LAYER_MULTIPLIER; 8223 w.mLayer = curLayer; 8224 } else { 8225 curBaseLayer = curLayer = w.mBaseLayer; 8226 w.mLayer = curLayer; 8227 } 8228 if (w.mLayer != oldLayer) { 8229 layerChanged = true; 8230 anyLayerChanged = true; 8231 } 8232 final AppWindowToken wtoken = w.mAppToken; 8233 oldLayer = winAnimator.mAnimLayer; 8234 if (w.mTargetAppToken != null) { 8235 winAnimator.mAnimLayer = 8236 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 8237 } else if (wtoken != null) { 8238 winAnimator.mAnimLayer = 8239 w.mLayer + wtoken.mAppAnimator.animLayerAdjustment; 8240 } else { 8241 winAnimator.mAnimLayer = w.mLayer; 8242 } 8243 if (w.mIsImWindow) { 8244 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 8245 } else if (w.mIsWallpaper) { 8246 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 8247 } 8248 if (winAnimator.mAnimLayer != oldLayer) { 8249 layerChanged = true; 8250 anyLayerChanged = true; 8251 } 8252 if (layerChanged && w.getStack().isDimming(winAnimator)) { 8253 // Force an animation pass just to update the mDimLayer layer. 8254 scheduleAnimationLocked(); 8255 } 8256 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 8257 + "mBase=" + w.mBaseLayer 8258 + " mLayer=" + w.mLayer 8259 + (wtoken == null ? 8260 "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment) 8261 + " =mAnimLayer=" + winAnimator.mAnimLayer); 8262 //System.out.println( 8263 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 8264 } 8265 8266 //TODO (multidisplay): Magnification is supported only for the default display. 8267 if (mAccessibilityController != null && anyLayerChanged 8268 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) { 8269 mAccessibilityController.onWindowLayersChangedLocked(); 8270 } 8271 } 8272 8273 private final void performLayoutAndPlaceSurfacesLocked() { 8274 int loopCount = 6; 8275 do { 8276 mTraversalScheduled = false; 8277 performLayoutAndPlaceSurfacesLockedLoop(); 8278 mH.removeMessages(H.DO_TRAVERSAL); 8279 loopCount--; 8280 } while (mTraversalScheduled && loopCount > 0); 8281 mInnerFields.mWallpaperActionPending = false; 8282 } 8283 8284 private boolean mInLayout = false; 8285 private final void performLayoutAndPlaceSurfacesLockedLoop() { 8286 if (mInLayout) { 8287 if (DEBUG) { 8288 throw new RuntimeException("Recursive call!"); 8289 } 8290 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 8291 + Debug.getCallers(3)); 8292 return; 8293 } 8294 8295 if (mWaitingForConfig) { 8296 // Our configuration has changed (most likely rotation), but we 8297 // don't yet have the complete configuration to report to 8298 // applications. Don't do any window layout until we have it. 8299 return; 8300 } 8301 8302 if (!mDisplayReady) { 8303 // Not yet initialized, nothing to do. 8304 return; 8305 } 8306 8307 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 8308 mInLayout = true; 8309 boolean recoveringMemory = false; 8310 8311 try { 8312 if (mForceRemoves != null) { 8313 recoveringMemory = true; 8314 // Wait a little bit for things to settle down, and off we go. 8315 for (int i=0; i<mForceRemoves.size(); i++) { 8316 WindowState ws = mForceRemoves.get(i); 8317 Slog.i(TAG, "Force removing: " + ws); 8318 removeWindowInnerLocked(ws.mSession, ws); 8319 } 8320 mForceRemoves = null; 8321 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 8322 Object tmp = new Object(); 8323 synchronized (tmp) { 8324 try { 8325 tmp.wait(250); 8326 } catch (InterruptedException e) { 8327 } 8328 } 8329 } 8330 } catch (RuntimeException e) { 8331 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 8332 } 8333 8334 try { 8335 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 8336 8337 mInLayout = false; 8338 8339 if (needsLayout()) { 8340 if (++mLayoutRepeatCount < 6) { 8341 requestTraversalLocked(); 8342 } else { 8343 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 8344 mLayoutRepeatCount = 0; 8345 } 8346 } else { 8347 mLayoutRepeatCount = 0; 8348 } 8349 8350 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 8351 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 8352 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE); 8353 } 8354 } catch (RuntimeException e) { 8355 mInLayout = false; 8356 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 8357 } 8358 8359 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 8360 } 8361 8362 private final void performLayoutLockedInner(final DisplayContent displayContent, 8363 boolean initial, boolean updateInputWindows) { 8364 if (!displayContent.layoutNeeded) { 8365 return; 8366 } 8367 displayContent.layoutNeeded = false; 8368 WindowList windows = displayContent.getWindowList(); 8369 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 8370 8371 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8372 final int dw = displayInfo.logicalWidth; 8373 final int dh = displayInfo.logicalHeight; 8374 8375 final int NFW = mFakeWindows.size(); 8376 for (int i=0; i<NFW; i++) { 8377 mFakeWindows.get(i).layout(dw, dh); 8378 } 8379 8380 final int N = windows.size(); 8381 int i; 8382 8383 if (DEBUG_LAYOUT) { 8384 Slog.v(TAG, "-------------------------------------"); 8385 Slog.v(TAG, "performLayout: needed=" 8386 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 8387 } 8388 8389 WindowStateAnimator universeBackground = null; 8390 8391 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); 8392 if (isDefaultDisplay) { 8393 // Not needed on non-default displays. 8394 mSystemDecorLayer = mPolicy.getSystemDecorLayerLw(); 8395 mScreenRect.set(0, 0, dw, dh); 8396 } 8397 8398 mPolicy.getContentRectLw(mTmpContentRect); 8399 displayContent.resize(mTmpContentRect); 8400 8401 int seq = mLayoutSeq+1; 8402 if (seq < 0) seq = 0; 8403 mLayoutSeq = seq; 8404 8405 boolean behindDream = false; 8406 8407 // First perform layout of any root windows (not attached 8408 // to another window). 8409 int topAttached = -1; 8410 for (i = N-1; i >= 0; i--) { 8411 final WindowState win = windows.get(i); 8412 8413 // Don't do layout of a window if it is not visible, or 8414 // soon won't be visible, to avoid wasting time and funky 8415 // changes while a window is animating away. 8416 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) 8417 || win.isGoneForLayoutLw(); 8418 8419 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 8420 Slog.v(TAG, "1ST PASS " + win 8421 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 8422 + " mLayoutAttached=" + win.mLayoutAttached 8423 + " screen changed=" + win.isConfigChanged()); 8424 final AppWindowToken atoken = win.mAppToken; 8425 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 8426 + win.mViewVisibility + " mRelayoutCalled=" 8427 + win.mRelayoutCalled + " hidden=" 8428 + win.mRootToken.hidden + " hiddenRequested=" 8429 + (atoken != null && atoken.hiddenRequested) 8430 + " mAttachedHidden=" + win.mAttachedHidden); 8431 else Slog.v(TAG, " VIS: mViewVisibility=" 8432 + win.mViewVisibility + " mRelayoutCalled=" 8433 + win.mRelayoutCalled + " hidden=" 8434 + win.mRootToken.hidden + " hiddenRequested=" 8435 + (atoken != null && atoken.hiddenRequested) 8436 + " mAttachedHidden=" + win.mAttachedHidden); 8437 } 8438 8439 // If this view is GONE, then skip it -- keep the current 8440 // frame, and let the caller know so they can ignore it 8441 // if they want. (We do the normal layout for INVISIBLE 8442 // windows, since that means "perform layout as normal, 8443 // just don't display"). 8444 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 8445 || ((win.isConfigChanged() || win.setInsetsChanged()) && 8446 ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || 8447 win.mAppToken != null && win.mAppToken.layoutConfigChanges)) 8448 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8449 if (!win.mLayoutAttached) { 8450 if (initial) { 8451 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8452 win.mContentChanged = false; 8453 } 8454 if (win.mAttrs.type == TYPE_DREAM) { 8455 // Don't layout windows behind a dream, so that if it 8456 // does stuff like hide the status bar we won't get a 8457 // bad transition when it goes away. 8458 behindDream = true; 8459 } 8460 win.mLayoutNeeded = false; 8461 win.prelayout(); 8462 mPolicy.layoutWindowLw(win, null); 8463 win.mLayoutSeq = seq; 8464 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8465 + win.mFrame + " mContainingFrame=" 8466 + win.mContainingFrame + " mDisplayFrame=" 8467 + win.mDisplayFrame); 8468 } else { 8469 if (topAttached < 0) topAttached = i; 8470 } 8471 } 8472 if (win.mViewVisibility == View.VISIBLE 8473 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 8474 && universeBackground == null) { 8475 universeBackground = win.mWinAnimator; 8476 } 8477 } 8478 8479 if (mAnimator.mUniverseBackground != universeBackground) { 8480 mFocusMayChange = true; 8481 mAnimator.mUniverseBackground = universeBackground; 8482 } 8483 8484 boolean attachedBehindDream = false; 8485 8486 // Now perform layout of attached windows, which usually 8487 // depend on the position of the window they are attached to. 8488 // XXX does not deal with windows that are attached to windows 8489 // that are themselves attached. 8490 for (i = topAttached; i >= 0; i--) { 8491 final WindowState win = windows.get(i); 8492 8493 if (win.mLayoutAttached) { 8494 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 8495 + " mHaveFrame=" + win.mHaveFrame 8496 + " mViewVisibility=" + win.mViewVisibility 8497 + " mRelayoutCalled=" + win.mRelayoutCalled); 8498 // If this view is GONE, then skip it -- keep the current 8499 // frame, and let the caller know so they can ignore it 8500 // if they want. (We do the normal layout for INVISIBLE 8501 // windows, since that means "perform layout as normal, 8502 // just don't display"). 8503 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) { 8504 continue; 8505 } 8506 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8507 || !win.mHaveFrame || win.mLayoutNeeded) { 8508 if (initial) { 8509 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8510 win.mContentChanged = false; 8511 } 8512 win.mLayoutNeeded = false; 8513 win.prelayout(); 8514 mPolicy.layoutWindowLw(win, win.mAttachedWindow); 8515 win.mLayoutSeq = seq; 8516 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8517 + win.mFrame + " mContainingFrame=" 8518 + win.mContainingFrame + " mDisplayFrame=" 8519 + win.mDisplayFrame); 8520 } 8521 } else if (win.mAttrs.type == TYPE_DREAM) { 8522 // Don't layout windows behind a dream, so that if it 8523 // does stuff like hide the status bar we won't get a 8524 // bad transition when it goes away. 8525 attachedBehindDream = behindDream; 8526 } 8527 } 8528 8529 // Window frames may have changed. Tell the input dispatcher about it. 8530 mInputMonitor.setUpdateInputWindowsNeededLw(); 8531 if (updateInputWindows) { 8532 mInputMonitor.updateInputWindowsLw(false /*force*/); 8533 } 8534 8535 mPolicy.finishLayoutLw(); 8536 } 8537 8538 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8539 // If the screen is currently frozen or off, then keep 8540 // it frozen/off until this window draws at its new 8541 // orientation. 8542 if (!okToDisplay()) { 8543 if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w); 8544 w.mOrientationChanging = true; 8545 w.mLastFreezeDuration = 0; 8546 mInnerFields.mOrientationChangeComplete = false; 8547 if (!mWindowsFreezingScreen) { 8548 mWindowsFreezingScreen = true; 8549 // XXX should probably keep timeout from 8550 // when we first froze the display. 8551 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8552 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 8553 WINDOW_FREEZE_TIMEOUT_DURATION); 8554 } 8555 } 8556 } 8557 8558 /** 8559 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8560 * @param windows List of windows on default display. 8561 * @return bitmap indicating if another pass through layout must be made. 8562 */ 8563 public int handleAppTransitionReadyLocked(WindowList windows) { 8564 int changes = 0; 8565 int i; 8566 int NN = mOpeningApps.size(); 8567 boolean goodToGo = true; 8568 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8569 "Checking " + NN + " opening apps (frozen=" 8570 + mDisplayFrozen + " timeout=" 8571 + mAppTransition.isTimeout() + ")..."); 8572 if (!mDisplayFrozen && !mAppTransition.isTimeout()) { 8573 // If the display isn't frozen, wait to do anything until 8574 // all of the apps are ready. Otherwise just go because 8575 // we'll unfreeze the display when everyone is ready. 8576 for (i=0; i<NN && goodToGo; i++) { 8577 AppWindowToken wtoken = mOpeningApps.valueAt(i); 8578 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8579 "Check opening app=" + wtoken + ": allDrawn=" 8580 + wtoken.allDrawn + " startingDisplayed=" 8581 + wtoken.startingDisplayed + " startingMoved=" 8582 + wtoken.startingMoved); 8583 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8584 && !wtoken.startingMoved) { 8585 goodToGo = false; 8586 } 8587 } 8588 } 8589 if (goodToGo) { 8590 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8591 int transit = mAppTransition.getAppTransition(); 8592 if (mSkipAppTransitionAnimation) { 8593 transit = AppTransition.TRANSIT_UNSET; 8594 } 8595 mAppTransition.goodToGo(); 8596 mStartingIconInTransition = false; 8597 mSkipAppTransitionAnimation = false; 8598 8599 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8600 8601 rebuildAppWindowListLocked(); 8602 8603 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8604 WindowState oldWallpaper = 8605 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8606 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8607 ? null : mWallpaperTarget; 8608 8609 mInnerFields.mWallpaperMayChange = false; 8610 8611 // The top-most window will supply the layout params, 8612 // and we will determine it below. 8613 LayoutParams animLp = null; 8614 int bestAnimLayer = -1; 8615 boolean fullscreenAnim = false; 8616 boolean voiceInteraction = false; 8617 8618 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8619 "New wallpaper target=" + mWallpaperTarget 8620 + ", oldWallpaper=" + oldWallpaper 8621 + ", lower target=" + mLowerWallpaperTarget 8622 + ", upper target=" + mUpperWallpaperTarget); 8623 8624 boolean openingAppHasWallpaper = false; 8625 boolean closingAppHasWallpaper = false; 8626 final AppWindowToken lowerWallpaperAppToken; 8627 final AppWindowToken upperWallpaperAppToken; 8628 if (mLowerWallpaperTarget == null) { 8629 lowerWallpaperAppToken = upperWallpaperAppToken = null; 8630 } else { 8631 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken; 8632 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken; 8633 } 8634 8635 // Do a first pass through the tokens for two 8636 // things: 8637 // (1) Determine if both the closing and opening 8638 // app token sets are wallpaper targets, in which 8639 // case special animations are needed 8640 // (since the wallpaper needs to stay static 8641 // behind them). 8642 // (2) Find the layout params of the top-most 8643 // application window in the tokens, which is 8644 // what will control the animation theme. 8645 final int NC = mClosingApps.size(); 8646 NN = NC + mOpeningApps.size(); 8647 for (i=0; i<NN; i++) { 8648 final AppWindowToken wtoken; 8649 if (i < NC) { 8650 wtoken = mClosingApps.valueAt(i); 8651 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8652 closingAppHasWallpaper = true; 8653 } 8654 } else { 8655 wtoken = mOpeningApps.valueAt(i - NC); 8656 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8657 openingAppHasWallpaper = true; 8658 } 8659 } 8660 8661 voiceInteraction |= wtoken.voiceInteraction; 8662 8663 if (wtoken.appFullscreen) { 8664 WindowState ws = wtoken.findMainWindow(); 8665 if (ws != null) { 8666 animLp = ws.mAttrs; 8667 bestAnimLayer = ws.mLayer; 8668 fullscreenAnim = true; 8669 } 8670 } else if (!fullscreenAnim) { 8671 WindowState ws = wtoken.findMainWindow(); 8672 if (ws != null) { 8673 if (ws.mLayer > bestAnimLayer) { 8674 animLp = ws.mAttrs; 8675 bestAnimLayer = ws.mLayer; 8676 } 8677 } 8678 } 8679 } 8680 8681 mAnimateWallpaperWithTarget = false; 8682 if (closingAppHasWallpaper && openingAppHasWallpaper) { 8683 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!"); 8684 switch (transit) { 8685 case AppTransition.TRANSIT_ACTIVITY_OPEN: 8686 case AppTransition.TRANSIT_TASK_OPEN: 8687 case AppTransition.TRANSIT_TASK_TO_FRONT: 8688 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN; 8689 break; 8690 case AppTransition.TRANSIT_ACTIVITY_CLOSE: 8691 case AppTransition.TRANSIT_TASK_CLOSE: 8692 case AppTransition.TRANSIT_TASK_TO_BACK: 8693 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; 8694 break; 8695 } 8696 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); 8697 } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty() 8698 && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 8699 // We are transitioning from an activity with 8700 // a wallpaper to one without. 8701 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; 8702 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8703 "New transit away from wallpaper: " + transit); 8704 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) { 8705 // We are transitioning from an activity without 8706 // a wallpaper to now showing the wallpaper 8707 transit = AppTransition.TRANSIT_WALLPAPER_OPEN; 8708 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8709 "New transit into wallpaper: " + transit); 8710 } else { 8711 mAnimateWallpaperWithTarget = true; 8712 } 8713 8714 // If all closing windows are obscured, then there is 8715 // no need to do an animation. This is the case, for 8716 // example, when this transition is being done behind 8717 // the lock screen. 8718 if (!mPolicy.allowAppAnimationsLw()) { 8719 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8720 "Animations disallowed by keyguard or dream."); 8721 animLp = null; 8722 } 8723 8724 AppWindowToken topOpeningApp = null; 8725 int topOpeningLayer = 0; 8726 8727 NN = mOpeningApps.size(); 8728 for (i=0; i<NN; i++) { 8729 AppWindowToken wtoken = mOpeningApps.valueAt(i); 8730 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 8731 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 8732 appAnimator.clearThumbnail(); 8733 wtoken.inPendingTransaction = false; 8734 appAnimator.animation = null; 8735 setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction); 8736 wtoken.updateReportedVisibilityLocked(); 8737 wtoken.waitingToShow = false; 8738 8739 appAnimator.mAllAppWinAnimators.clear(); 8740 final int N = wtoken.allAppWindows.size(); 8741 for (int j = 0; j < N; j++) { 8742 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 8743 } 8744 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 8745 8746 if (animLp != null) { 8747 int layer = -1; 8748 for (int j=0; j<wtoken.windows.size(); j++) { 8749 WindowState win = wtoken.windows.get(j); 8750 if (win.mWinAnimator.mAnimLayer > layer) { 8751 layer = win.mWinAnimator.mAnimLayer; 8752 } 8753 } 8754 if (topOpeningApp == null || layer > topOpeningLayer) { 8755 topOpeningApp = wtoken; 8756 topOpeningLayer = layer; 8757 } 8758 } 8759 } 8760 NN = mClosingApps.size(); 8761 for (i=0; i<NN; i++) { 8762 AppWindowToken wtoken = mClosingApps.valueAt(i); 8763 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken); 8764 wtoken.mAppAnimator.clearThumbnail(); 8765 wtoken.inPendingTransaction = false; 8766 wtoken.mAppAnimator.animation = null; 8767 setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction); 8768 wtoken.updateReportedVisibilityLocked(); 8769 wtoken.waitingToHide = false; 8770 // Force the allDrawn flag, because we want to start 8771 // this guy's animations regardless of whether it's 8772 // gotten drawn. 8773 wtoken.allDrawn = true; 8774 wtoken.deferClearAllDrawn = false; 8775 } 8776 8777 boolean useAlternateThumbnailAnimation = true; 8778 AppWindowAnimator appAnimator = 8779 topOpeningApp == null ? null : topOpeningApp.mAppAnimator; 8780 Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail(); 8781 if (!useAlternateThumbnailAnimation && nextAppTransitionThumbnail != null 8782 && appAnimator != null && appAnimator.animation != null) { 8783 // This thumbnail animation is very special, we need to have 8784 // an extra surface with the thumbnail included with the animation. 8785 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(), 8786 nextAppTransitionThumbnail.getHeight()); 8787 try { 8788 // TODO(multi-display): support other displays 8789 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8790 final Display display = displayContent.getDisplay(); 8791 SurfaceControl surfaceControl = new SurfaceControl(mFxSession, 8792 "thumbnail anim", 8793 dirty.width(), dirty.height(), 8794 PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 8795 surfaceControl.setLayerStack(display.getLayerStack()); 8796 appAnimator.thumbnail = surfaceControl; 8797 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE"); 8798 Surface drawSurface = new Surface(); 8799 drawSurface.copyFrom(surfaceControl); 8800 Canvas c = drawSurface.lockCanvas(dirty); 8801 c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null); 8802 drawSurface.unlockCanvasAndPost(c); 8803 drawSurface.release(); 8804 appAnimator.thumbnailLayer = topOpeningLayer; 8805 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 8806 Animation anim = mAppTransition.createThumbnailScaleAnimationLocked( 8807 displayInfo.appWidth, displayInfo.appHeight, transit); 8808 appAnimator.thumbnailAnimation = anim; 8809 anim.restrictDuration(MAX_ANIMATION_DURATION); 8810 anim.scaleCurrentDuration(getTransitionAnimationScaleLocked()); 8811 Point p = new Point(); 8812 mAppTransition.getStartingPoint(p); 8813 appAnimator.thumbnailX = p.x; 8814 appAnimator.thumbnailY = p.y; 8815 } catch (OutOfResourcesException e) { 8816 Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width() 8817 + " h=" + dirty.height(), e); 8818 appAnimator.clearThumbnail(); 8819 } 8820 } 8821 8822 mAppTransition.postAnimationCallback(); 8823 mAppTransition.clear(); 8824 8825 mOpeningApps.clear(); 8826 mClosingApps.clear(); 8827 8828 // This has changed the visibility of windows, so perform 8829 // a new layout to get them all up-to-date. 8830 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT 8831 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 8832 getDefaultDisplayContentLocked().layoutNeeded = true; 8833 8834 // TODO(multidisplay): IMEs are only supported on the default display. 8835 if (windows == getDefaultWindowListLocked() 8836 && !moveInputMethodWindowsIfNeededLocked(true)) { 8837 assignLayersLocked(windows); 8838 } 8839 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/); 8840 mFocusMayChange = false; 8841 } 8842 8843 return changes; 8844 } 8845 8846 /** 8847 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8848 * @return bitmap indicating if another pass through layout must be made. 8849 */ 8850 private int handleAnimatingStoppedAndTransitionLocked() { 8851 int changes = 0; 8852 8853 mAppTransition.setIdle(); 8854 // Restore window app tokens to the ActivityManager views 8855 ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks(); 8856 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 8857 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8858 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 8859 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8860 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 8861 tokens.get(tokenNdx).sendingToBottom = false; 8862 } 8863 } 8864 } 8865 rebuildAppWindowListLocked(); 8866 8867 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8868 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 8869 "Wallpaper layer changed: assigning layers + relayout"); 8870 moveInputMethodWindowsIfNeededLocked(true); 8871 mInnerFields.mWallpaperMayChange = true; 8872 // Since the window list has been rebuilt, focus might 8873 // have to be recomputed since the actual order of windows 8874 // might have changed again. 8875 mFocusMayChange = true; 8876 8877 return changes; 8878 } 8879 8880 private void updateResizingWindows(final WindowState w) { 8881 final WindowStateAnimator winAnimator = w.mWinAnimator; 8882 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { 8883 w.setInsetsChanged(); 8884 boolean configChanged = w.isConfigChanged(); 8885 if (DEBUG_CONFIGURATION && configChanged) { 8886 Slog.v(TAG, "Win " + w + " config changed: " 8887 + mCurConfiguration); 8888 } 8889 if (localLOGV) Slog.v(TAG, "Resizing " + w 8890 + ": configChanged=" + configChanged 8891 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8892 w.mLastFrame.set(w.mFrame); 8893 if (w.mContentInsetsChanged 8894 || w.mVisibleInsetsChanged 8895 || winAnimator.mSurfaceResized 8896 || configChanged) { 8897 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8898 Slog.v(TAG, "Resize reasons for w=" + w + ": " 8899 + " contentInsetsChanged=" + w.mContentInsetsChanged 8900 + " " + w.mContentInsets.toShortString() 8901 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8902 + " " + w.mVisibleInsets.toShortString() 8903 + " stableInsetsChanged=" + w.mStableInsetsChanged 8904 + " " + w.mStableInsets.toShortString() 8905 + " surfaceResized=" + winAnimator.mSurfaceResized 8906 + " configChanged=" + configChanged); 8907 } 8908 8909 w.mLastOverscanInsets.set(w.mOverscanInsets); 8910 w.mLastContentInsets.set(w.mContentInsets); 8911 w.mLastVisibleInsets.set(w.mVisibleInsets); 8912 w.mLastStableInsets.set(w.mStableInsets); 8913 makeWindowFreezingScreenIfNeededLocked(w); 8914 // If the orientation is changing, then we need to 8915 // hold off on unfreezing the display until this 8916 // window has been redrawn; to do that, we need 8917 // to go through the process of getting informed 8918 // by the application when it has finished drawing. 8919 if (w.mOrientationChanging) { 8920 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 8921 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 8922 + w + ", surface " + winAnimator.mSurfaceControl); 8923 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 8924 if (w.mAppToken != null) { 8925 w.mAppToken.allDrawn = false; 8926 w.mAppToken.deferClearAllDrawn = false; 8927 } 8928 } 8929 if (!mResizingWindows.contains(w)) { 8930 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8931 "Resizing window " + w + " to " + winAnimator.mSurfaceW 8932 + "x" + winAnimator.mSurfaceH); 8933 mResizingWindows.add(w); 8934 } 8935 } else if (w.mOrientationChanging) { 8936 if (w.isDrawnLw()) { 8937 if (DEBUG_ORIENTATION) Slog.v(TAG, 8938 "Orientation not waiting for draw in " 8939 + w + ", surface " + winAnimator.mSurfaceControl); 8940 w.mOrientationChanging = false; 8941 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 8942 - mDisplayFreezeTime); 8943 } 8944 } 8945 } 8946 } 8947 8948 /** 8949 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8950 * 8951 * @param w WindowState this method is applied to. 8952 * @param currentTime The time which animations use for calculating transitions. 8953 * @param innerDw Width of app window. 8954 * @param innerDh Height of app window. 8955 */ 8956 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 8957 final int innerDw, final int innerDh) { 8958 final WindowManager.LayoutParams attrs = w.mAttrs; 8959 final int attrFlags = attrs.flags; 8960 final boolean canBeSeen = w.isDisplayedLw(); 8961 final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8962 8963 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8964 // This window completely covers everything behind it, 8965 // so we want to leave all of them as undimmed (for 8966 // performance reasons). 8967 mInnerFields.mObscured = true; 8968 } 8969 8970 if (w.mHasSurface) { 8971 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8972 mInnerFields.mHoldScreen = w.mSession; 8973 } 8974 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 8975 && mInnerFields.mScreenBrightness < 0) { 8976 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 8977 } 8978 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 8979 && mInnerFields.mButtonBrightness < 0) { 8980 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 8981 } 8982 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0 8983 && mInnerFields.mUserActivityTimeout < 0) { 8984 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout; 8985 } 8986 8987 final int type = attrs.type; 8988 if (canBeSeen 8989 && (type == TYPE_SYSTEM_DIALOG 8990 || type == TYPE_RECENTS_OVERLAY 8991 || type == TYPE_SYSTEM_ERROR 8992 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) { 8993 mInnerFields.mSyswin = true; 8994 } 8995 8996 if (canBeSeen) { 8997 // This function assumes that the contents of the default display are 8998 // processed first before secondary displays. 8999 final DisplayContent displayContent = w.getDisplayContent(); 9000 if (displayContent != null && displayContent.isDefaultDisplay) { 9001 // While a dream or keyguard is showing, obscure ordinary application 9002 // content on secondary displays (by forcibly enabling mirroring unless 9003 // there is other content we want to show) but still allow opaque 9004 // keyguard dialogs to be shown. 9005 if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 9006 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true; 9007 } 9008 mInnerFields.mDisplayHasContent = true; 9009 } else if (displayContent != null && 9010 (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays 9011 || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) { 9012 // Allow full screen keyguard presentation dialogs to be seen. 9013 mInnerFields.mDisplayHasContent = true; 9014 } 9015 } 9016 } 9017 } 9018 9019 private void handleFlagDimBehind(WindowState w) { 9020 final WindowManager.LayoutParams attrs = w.mAttrs; 9021 if ((attrs.flags & FLAG_DIM_BEHIND) != 0 9022 && w.isDisplayedLw() 9023 && !w.mExiting) { 9024 final WindowStateAnimator winAnimator = w.mWinAnimator; 9025 final TaskStack stack = w.getStack(); 9026 stack.setDimmingTag(); 9027 if (!stack.isDimming(winAnimator)) { 9028 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming."); 9029 stack.startDimmingIfNeeded(winAnimator); 9030 } 9031 } 9032 } 9033 9034 private void updateAllDrawnLocked(DisplayContent displayContent) { 9035 // See if any windows have been drawn, so they (and others 9036 // associated with them) can now be shown. 9037 ArrayList<TaskStack> stacks = displayContent.getStacks(); 9038 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 9039 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9040 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9041 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9042 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9043 final AppWindowToken wtoken = tokens.get(tokenNdx); 9044 if (!wtoken.allDrawn) { 9045 int numInteresting = wtoken.numInterestingWindows; 9046 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 9047 if (DEBUG_VISIBILITY) Slog.v(TAG, 9048 "allDrawn: " + wtoken 9049 + " interesting=" + numInteresting 9050 + " drawn=" + wtoken.numDrawnWindows); 9051 wtoken.allDrawn = true; 9052 mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget(); 9053 } 9054 } 9055 } 9056 } 9057 } 9058 } 9059 9060 // "Something has changed! Let's make it correct now." 9061 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 9062 if (DEBUG_WINDOW_TRACE) { 9063 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 9064 + Debug.getCallers(3)); 9065 } 9066 9067 final long currentTime = SystemClock.uptimeMillis(); 9068 9069 int i; 9070 9071 if (mFocusMayChange) { 9072 mFocusMayChange = false; 9073 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 9074 false /*updateInputWindows*/); 9075 } 9076 9077 // Initialize state of exiting tokens. 9078 final int numDisplays = mDisplayContents.size(); 9079 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9080 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9081 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) { 9082 displayContent.mExitingTokens.get(i).hasVisible = false; 9083 } 9084 } 9085 9086 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9087 // Initialize state of exiting applications. 9088 final AppTokenList exitingAppTokens = 9089 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9090 for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9091 exitingAppTokens.get(tokenNdx).hasVisible = false; 9092 } 9093 } 9094 9095 mInnerFields.mHoldScreen = null; 9096 mInnerFields.mScreenBrightness = -1; 9097 mInnerFields.mButtonBrightness = -1; 9098 mInnerFields.mUserActivityTimeout = -1; 9099 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false; 9100 9101 mTransactionSequence++; 9102 9103 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked(); 9104 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 9105 final int defaultDw = defaultInfo.logicalWidth; 9106 final int defaultDh = defaultInfo.logicalHeight; 9107 9108 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9109 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 9110 SurfaceControl.openTransaction(); 9111 try { 9112 9113 if (mWatermark != null) { 9114 mWatermark.positionSurface(defaultDw, defaultDh); 9115 } 9116 if (mStrictModeFlash != null) { 9117 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 9118 } 9119 9120 boolean focusDisplayed = false; 9121 9122 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9123 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9124 boolean updateAllDrawn = false; 9125 WindowList windows = displayContent.getWindowList(); 9126 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9127 final int displayId = displayContent.getDisplayId(); 9128 final int dw = displayInfo.logicalWidth; 9129 final int dh = displayInfo.logicalHeight; 9130 final int innerDw = displayInfo.appWidth; 9131 final int innerDh = displayInfo.appHeight; 9132 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 9133 9134 // Reset for each display. 9135 mInnerFields.mDisplayHasContent = false; 9136 9137 int repeats = 0; 9138 do { 9139 repeats++; 9140 if (repeats > 6) { 9141 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 9142 displayContent.layoutNeeded = false; 9143 break; 9144 } 9145 9146 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 9147 displayContent.pendingLayoutChanges); 9148 9149 if ((displayContent.pendingLayoutChanges & 9150 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 && 9151 (adjustWallpaperWindowsLocked() & 9152 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 9153 assignLayersLocked(windows); 9154 displayContent.layoutNeeded = true; 9155 } 9156 9157 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 9158 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 9159 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 9160 if (updateOrientationFromAppTokensLocked(true)) { 9161 displayContent.layoutNeeded = true; 9162 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9163 } 9164 } 9165 9166 if ((displayContent.pendingLayoutChanges 9167 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9168 displayContent.layoutNeeded = true; 9169 } 9170 9171 // FIRST LOOP: Perform a layout, if needed. 9172 if (repeats < 4) { 9173 performLayoutLockedInner(displayContent, repeats == 1, 9174 false /*updateInputWindows*/); 9175 } else { 9176 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 9177 } 9178 9179 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 9180 // it is animating. 9181 displayContent.pendingLayoutChanges = 0; 9182 9183 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 9184 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 9185 9186 if (isDefaultDisplay) { 9187 mPolicy.beginPostLayoutPolicyLw(dw, dh); 9188 for (i = windows.size() - 1; i >= 0; i--) { 9189 WindowState w = windows.get(i); 9190 if (w.mHasSurface) { 9191 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); 9192 } 9193 } 9194 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 9195 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 9196 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges); 9197 } 9198 } while (displayContent.pendingLayoutChanges != 0); 9199 9200 mInnerFields.mObscured = false; 9201 mInnerFields.mSyswin = false; 9202 displayContent.resetDimming(); 9203 9204 // Only used if default window 9205 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 9206 9207 final int N = windows.size(); 9208 for (i=N-1; i>=0; i--) { 9209 WindowState w = windows.get(i); 9210 final TaskStack stack = w.getStack(); 9211 if (stack == null) { 9212 continue; 9213 } 9214 9215 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 9216 9217 // Update effect. 9218 w.mObscured = mInnerFields.mObscured; 9219 if (!mInnerFields.mObscured) { 9220 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 9221 } 9222 9223 if (!stack.testDimmingTag()) { 9224 handleFlagDimBehind(w); 9225 } 9226 9227 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 9228 && w.isVisibleLw()) { 9229 // This is the wallpaper target and its obscured state 9230 // changed... make sure the current wallaper's visibility 9231 // has been updated accordingly. 9232 updateWallpaperVisibilityLocked(); 9233 } 9234 9235 final WindowStateAnimator winAnimator = w.mWinAnimator; 9236 9237 // If the window has moved due to its containing 9238 // content frame changing, then we'd like to animate 9239 // it. 9240 if (w.mHasSurface && w.shouldAnimateMove()) { 9241 // Frame has moved, containing content frame 9242 // has also moved, and we're not currently animating... 9243 // let's do something. 9244 Animation a = AnimationUtils.loadAnimation(mContext, 9245 com.android.internal.R.anim.window_move_from_decor); 9246 winAnimator.setAnimation(a); 9247 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 9248 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 9249 9250 //TODO (multidisplay): Accessibility supported only for the default display. 9251 if (mAccessibilityController != null 9252 && displayId == Display.DEFAULT_DISPLAY) { 9253 mAccessibilityController.onSomeWindowResizedOrMovedLocked(); 9254 } 9255 9256 try { 9257 w.mClient.moved(w.mFrame.left, w.mFrame.top); 9258 } catch (RemoteException e) { 9259 } 9260 } 9261 9262 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 9263 w.mContentChanged = false; 9264 9265 // Moved from updateWindowsAndWallpaperLocked(). 9266 if (w.mHasSurface) { 9267 // Take care of the window being ready to display. 9268 final boolean committed = 9269 winAnimator.commitFinishDrawingLocked(currentTime); 9270 if (isDefaultDisplay && committed) { 9271 if (w.mAttrs.type == TYPE_DREAM) { 9272 // HACK: When a dream is shown, it may at that 9273 // point hide the lock screen. So we need to 9274 // redo the layout to let the phone window manager 9275 // make this happen. 9276 displayContent.pendingLayoutChanges |= 9277 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9278 if (DEBUG_LAYOUT_REPEATS) { 9279 debugLayoutRepeats( 9280 "dream and commitFinishDrawingLocked true", 9281 displayContent.pendingLayoutChanges); 9282 } 9283 } 9284 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 9285 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 9286 "First draw done in potential wallpaper target " + w); 9287 mInnerFields.mWallpaperMayChange = true; 9288 displayContent.pendingLayoutChanges |= 9289 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9290 if (DEBUG_LAYOUT_REPEATS) { 9291 debugLayoutRepeats( 9292 "wallpaper and commitFinishDrawingLocked true", 9293 displayContent.pendingLayoutChanges); 9294 } 9295 } 9296 } 9297 9298 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 9299 9300 final AppWindowToken atoken = w.mAppToken; 9301 if (DEBUG_STARTING_WINDOW && atoken != null 9302 && w == atoken.startingWindow) { 9303 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 9304 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 9305 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 9306 } 9307 if (atoken != null 9308 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 9309 if (atoken.lastTransactionSequence != mTransactionSequence) { 9310 atoken.lastTransactionSequence = mTransactionSequence; 9311 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 9312 atoken.startingDisplayed = false; 9313 } 9314 if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 9315 && !w.mExiting && !w.mDestroying) { 9316 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 9317 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 9318 + ", isAnimating=" + winAnimator.isAnimating()); 9319 if (!w.isDrawnLw()) { 9320 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl 9321 + " pv=" + w.mPolicyVisibility 9322 + " mDrawState=" + winAnimator.mDrawState 9323 + " ah=" + w.mAttachedHidden 9324 + " th=" + atoken.hiddenRequested 9325 + " a=" + winAnimator.mAnimating); 9326 } 9327 } 9328 if (w != atoken.startingWindow) { 9329 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 9330 atoken.numInterestingWindows++; 9331 if (w.isDrawnLw()) { 9332 atoken.numDrawnWindows++; 9333 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 9334 "tokenMayBeDrawn: " + atoken 9335 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 9336 + " mAppFreezing=" + w.mAppFreezing); 9337 updateAllDrawn = true; 9338 } 9339 } 9340 } else if (w.isDrawnLw()) { 9341 atoken.startingDisplayed = true; 9342 } 9343 } 9344 } 9345 } 9346 9347 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 9348 && w.isDisplayedLw()) { 9349 focusDisplayed = true; 9350 } 9351 9352 updateResizingWindows(w); 9353 } 9354 9355 mDisplayManagerInternal.setDisplayHasContent(displayId, 9356 mInnerFields.mDisplayHasContent, 9357 true /* inTraversal, must call performTraversalInTrans... below */); 9358 9359 getDisplayContentLocked(displayId).stopDimmingIfNeeded(); 9360 9361 if (updateAllDrawn) { 9362 updateAllDrawnLocked(displayContent); 9363 } 9364 } 9365 9366 if (focusDisplayed) { 9367 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 9368 } 9369 9370 // Give the display manager a chance to adjust properties 9371 // like display rotation if it needs to. 9372 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 9373 9374 } catch (RuntimeException e) { 9375 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 9376 } finally { 9377 SurfaceControl.closeTransaction(); 9378 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9379 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 9380 } 9381 9382 final WindowList defaultWindows = defaultDisplay.getWindowList(); 9383 9384 // If we are ready to perform an app transition, check through 9385 // all of the app tokens to be shown and see if they are ready 9386 // to go. 9387 if (mAppTransition.isReady()) { 9388 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 9389 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 9390 defaultDisplay.pendingLayoutChanges); 9391 } 9392 9393 if (!mAnimator.mAnimating && mAppTransition.isRunning()) { 9394 // We have finished the animation of an app transition. To do 9395 // this, we have delayed a lot of operations like showing and 9396 // hiding apps, moving apps in Z-order, etc. The app token list 9397 // reflects the correct Z-order, but the window list may now 9398 // be out of sync with it. So here we will just rebuild the 9399 // entire app window list. Fun! 9400 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 9401 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 9402 defaultDisplay.pendingLayoutChanges); 9403 } 9404 9405 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 9406 && !mAppTransition.isReady()) { 9407 // At this point, there was a window with a wallpaper that 9408 // was force hiding other windows behind it, but now it 9409 // is going away. This may be simple -- just animate 9410 // away the wallpaper and its window -- or it may be 9411 // hard -- the wallpaper now needs to be shown behind 9412 // something that was hidden. 9413 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9414 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 9415 defaultDisplay.pendingLayoutChanges); 9416 } 9417 mInnerFields.mWallpaperForceHidingChanged = false; 9418 9419 if (mInnerFields.mWallpaperMayChange) { 9420 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting"); 9421 defaultDisplay.pendingLayoutChanges |= 9422 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9423 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange", 9424 defaultDisplay.pendingLayoutChanges); 9425 } 9426 9427 if (mFocusMayChange) { 9428 mFocusMayChange = false; 9429 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 9430 false /*updateInputWindows*/)) { 9431 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 9432 } 9433 } 9434 9435 if (needsLayout()) { 9436 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9437 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 9438 defaultDisplay.pendingLayoutChanges); 9439 } 9440 9441 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 9442 WindowState win = mResizingWindows.get(i); 9443 if (win.mAppFreezing) { 9444 // Don't remove this window until rotation has completed. 9445 continue; 9446 } 9447 win.reportResized(); 9448 mResizingWindows.remove(i); 9449 } 9450 9451 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 9452 "With display frozen, orientationChangeComplete=" 9453 + mInnerFields.mOrientationChangeComplete); 9454 if (mInnerFields.mOrientationChangeComplete) { 9455 if (mWindowsFreezingScreen) { 9456 mWindowsFreezingScreen = false; 9457 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource; 9458 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9459 } 9460 stopFreezingDisplayLocked(); 9461 } 9462 9463 // Destroy the surface of any windows that are no longer visible. 9464 boolean wallpaperDestroyed = false; 9465 i = mDestroySurface.size(); 9466 if (i > 0) { 9467 do { 9468 i--; 9469 WindowState win = mDestroySurface.get(i); 9470 win.mDestroying = false; 9471 if (mInputMethodWindow == win) { 9472 mInputMethodWindow = null; 9473 } 9474 if (win == mWallpaperTarget) { 9475 wallpaperDestroyed = true; 9476 } 9477 win.mWinAnimator.destroySurfaceLocked(); 9478 } while (i > 0); 9479 mDestroySurface.clear(); 9480 } 9481 9482 // Time to remove any exiting tokens? 9483 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9484 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9485 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens; 9486 for (i = exitingTokens.size() - 1; i >= 0; i--) { 9487 WindowToken token = exitingTokens.get(i); 9488 if (!token.hasVisible) { 9489 exitingTokens.remove(i); 9490 if (token.windowType == TYPE_WALLPAPER) { 9491 mWallpaperTokens.remove(token); 9492 } 9493 } 9494 } 9495 } 9496 9497 // Time to remove any exiting applications? 9498 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9499 // Initialize state of exiting applications. 9500 final AppTokenList exitingAppTokens = 9501 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9502 for (i = exitingAppTokens.size() - 1; i >= 0; i--) { 9503 AppWindowToken token = exitingAppTokens.get(i); 9504 if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) { 9505 // Make sure there is no animation running on this token, 9506 // so any windows associated with it will be removed as 9507 // soon as their animations are complete 9508 token.mAppAnimator.clearAnimation(); 9509 token.mAppAnimator.animating = false; 9510 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 9511 "performLayout: App token exiting now removed" + token); 9512 removeAppFromTaskLocked(token); 9513 exitingAppTokens.remove(i); 9514 } 9515 } 9516 } 9517 9518 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 9519 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 9520 try { 9521 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 9522 } catch (RemoteException e) { 9523 } 9524 } 9525 mRelayoutWhileAnimating.clear(); 9526 } 9527 9528 if (wallpaperDestroyed) { 9529 defaultDisplay.pendingLayoutChanges |= 9530 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9531 defaultDisplay.layoutNeeded = true; 9532 } 9533 9534 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9535 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9536 if (displayContent.pendingLayoutChanges != 0) { 9537 displayContent.layoutNeeded = true; 9538 } 9539 } 9540 9541 // Finally update all input windows now that the window changes have stabilized. 9542 mInputMonitor.updateInputWindowsLw(true /*force*/); 9543 9544 setHoldScreenLocked(mInnerFields.mHoldScreen); 9545 if (!mDisplayFrozen) { 9546 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 9547 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1); 9548 } else { 9549 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager( 9550 toBrightnessOverride(mInnerFields.mScreenBrightness)); 9551 } 9552 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 9553 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1); 9554 } else { 9555 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager( 9556 toBrightnessOverride(mInnerFields.mButtonBrightness)); 9557 } 9558 mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager( 9559 mInnerFields.mUserActivityTimeout); 9560 } 9561 9562 if (mTurnOnScreen) { 9563 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 9564 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 9565 mTurnOnScreen = false; 9566 } 9567 9568 if (mInnerFields.mUpdateRotation) { 9569 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9570 if (updateRotationUncheckedLocked(false)) { 9571 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9572 } else { 9573 mInnerFields.mUpdateRotation = false; 9574 } 9575 } 9576 9577 if (mWaitingForDrawnCallback != null || 9578 (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded && 9579 !mInnerFields.mUpdateRotation)) { 9580 checkDrawnWindowsLocked(); 9581 } 9582 9583 final int N = mPendingRemove.size(); 9584 if (N > 0) { 9585 if (mPendingRemoveTmp.length < N) { 9586 mPendingRemoveTmp = new WindowState[N+10]; 9587 } 9588 mPendingRemove.toArray(mPendingRemoveTmp); 9589 mPendingRemove.clear(); 9590 DisplayContentList displayList = new DisplayContentList(); 9591 for (i = 0; i < N; i++) { 9592 WindowState w = mPendingRemoveTmp[i]; 9593 removeWindowInnerLocked(w.mSession, w); 9594 final DisplayContent displayContent = w.getDisplayContent(); 9595 if (displayContent != null && !displayList.contains(displayContent)) { 9596 displayList.add(displayContent); 9597 } 9598 } 9599 9600 for (DisplayContent displayContent : displayList) { 9601 assignLayersLocked(displayContent.getWindowList()); 9602 displayContent.layoutNeeded = true; 9603 } 9604 } 9605 9606 // Remove all deferred displays stacks, tasks, and activities. 9607 for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) { 9608 mDisplayContents.valueAt(displayNdx).checkForDeferredActions(); 9609 } 9610 9611 setFocusedStackFrame(); 9612 9613 // Check to see if we are now in a state where the screen should 9614 // be enabled, because the window obscured flags have changed. 9615 enableScreenIfNeededLocked(); 9616 9617 scheduleAnimationLocked(); 9618 9619 if (DEBUG_WINDOW_TRACE) { 9620 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" 9621 + mAnimator.mAnimating); 9622 } 9623 } 9624 9625 private int toBrightnessOverride(float value) { 9626 return (int)(value * PowerManager.BRIGHTNESS_ON); 9627 } 9628 9629 void checkDrawnWindowsLocked() { 9630 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { 9631 return; 9632 } 9633 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { 9634 WindowState win = mWaitingForDrawn.get(j); 9635 if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win + 9636 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() + 9637 " mHasSurface=" + win.mHasSurface + 9638 " drawState=" + win.mWinAnimator.mDrawState); 9639 if (win.mRemoved || !win.mHasSurface) { 9640 // Window has been removed; no draw will now happen, so stop waiting. 9641 if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win); 9642 mWaitingForDrawn.remove(win); 9643 } else if (win.hasDrawnLw()) { 9644 // Window is now drawn (and shown). 9645 if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win); 9646 mWaitingForDrawn.remove(win); 9647 } 9648 } 9649 if (mWaitingForDrawn.isEmpty()) { 9650 if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!"); 9651 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 9652 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); 9653 } 9654 } 9655 9656 void setHoldScreenLocked(final Session newHoldScreen) { 9657 final boolean hold = newHoldScreen != null; 9658 9659 if (hold && mHoldingScreenOn != newHoldScreen) { 9660 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 9661 } 9662 mHoldingScreenOn = newHoldScreen; 9663 9664 final boolean state = mHoldingScreenWakeLock.isHeld(); 9665 if (hold != state) { 9666 if (hold) { 9667 mHoldingScreenWakeLock.acquire(); 9668 mPolicy.keepScreenOnStartedLw(); 9669 } else { 9670 mPolicy.keepScreenOnStoppedLw(); 9671 mHoldingScreenWakeLock.release(); 9672 } 9673 } 9674 } 9675 9676 void requestTraversal() { 9677 synchronized (mWindowMap) { 9678 requestTraversalLocked(); 9679 } 9680 } 9681 9682 void requestTraversalLocked() { 9683 if (!mTraversalScheduled) { 9684 mTraversalScheduled = true; 9685 mH.sendEmptyMessage(H.DO_TRAVERSAL); 9686 } 9687 } 9688 9689 /** Note that Locked in this case is on mLayoutToAnim */ 9690 void scheduleAnimationLocked() { 9691 if (!mAnimationScheduled) { 9692 mAnimationScheduled = true; 9693 mChoreographer.postCallback( 9694 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 9695 } 9696 } 9697 9698 private boolean needsLayout() { 9699 final int numDisplays = mDisplayContents.size(); 9700 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9701 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9702 if (displayContent.layoutNeeded) { 9703 return true; 9704 } 9705 } 9706 return false; 9707 } 9708 9709 boolean copyAnimToLayoutParamsLocked() { 9710 boolean doRequest = false; 9711 9712 final int bulkUpdateParams = mAnimator.mBulkUpdateParams; 9713 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 9714 mInnerFields.mUpdateRotation = true; 9715 doRequest = true; 9716 } 9717 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 9718 mInnerFields.mWallpaperMayChange = true; 9719 doRequest = true; 9720 } 9721 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 9722 mInnerFields.mWallpaperForceHidingChanged = true; 9723 doRequest = true; 9724 } 9725 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 9726 mInnerFields.mOrientationChangeComplete = false; 9727 } else { 9728 mInnerFields.mOrientationChangeComplete = true; 9729 mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource; 9730 if (mWindowsFreezingScreen) { 9731 doRequest = true; 9732 } 9733 } 9734 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 9735 mTurnOnScreen = true; 9736 } 9737 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) { 9738 mInnerFields.mWallpaperActionPending = true; 9739 } 9740 9741 return doRequest; 9742 } 9743 9744 /** If a window that has an animation specifying a colored background and the current wallpaper 9745 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 9746 * suddenly disappear. */ 9747 int adjustAnimationBackground(WindowStateAnimator winAnimator) { 9748 WindowList windows = winAnimator.mWin.getWindowList(); 9749 for (int i = windows.size() - 1; i >= 0; --i) { 9750 WindowState testWin = windows.get(i); 9751 if (testWin.mIsWallpaper && testWin.isVisibleNow()) { 9752 return testWin.mWinAnimator.mAnimLayer; 9753 } 9754 } 9755 return winAnimator.mAnimLayer; 9756 } 9757 9758 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9759 boolean secure) { 9760 final SurfaceControl surface = winAnimator.mSurfaceControl; 9761 boolean leakedSurface = false; 9762 boolean killedApps = false; 9763 9764 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9765 winAnimator.mSession.mPid, operation); 9766 9767 if (mForceRemoves == null) { 9768 mForceRemoves = new ArrayList<WindowState>(); 9769 } 9770 9771 long callingIdentity = Binder.clearCallingIdentity(); 9772 try { 9773 // There was some problem... first, do a sanity check of the 9774 // window list to make sure we haven't left any dangling surfaces 9775 // around. 9776 9777 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 9778 final int numDisplays = mDisplayContents.size(); 9779 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9780 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9781 final int numWindows = windows.size(); 9782 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9783 final WindowState ws = windows.get(winNdx); 9784 WindowStateAnimator wsa = ws.mWinAnimator; 9785 if (wsa.mSurfaceControl != null) { 9786 if (!mSessions.contains(wsa.mSession)) { 9787 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 9788 + ws + " surface=" + wsa.mSurfaceControl 9789 + " token=" + ws.mToken 9790 + " pid=" + ws.mSession.mPid 9791 + " uid=" + ws.mSession.mUid); 9792 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9793 wsa.mSurfaceControl.destroy(); 9794 wsa.mSurfaceShown = false; 9795 wsa.mSurfaceControl = null; 9796 ws.mHasSurface = false; 9797 mForceRemoves.add(ws); 9798 leakedSurface = true; 9799 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9800 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 9801 + ws + " surface=" + wsa.mSurfaceControl 9802 + " token=" + ws.mAppToken); 9803 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9804 wsa.mSurfaceControl.destroy(); 9805 wsa.mSurfaceShown = false; 9806 wsa.mSurfaceControl = null; 9807 ws.mHasSurface = false; 9808 leakedSurface = true; 9809 } 9810 } 9811 } 9812 } 9813 9814 if (!leakedSurface) { 9815 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 9816 SparseIntArray pidCandidates = new SparseIntArray(); 9817 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9818 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9819 final int numWindows = windows.size(); 9820 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9821 final WindowState ws = windows.get(winNdx); 9822 if (mForceRemoves.contains(ws)) { 9823 continue; 9824 } 9825 WindowStateAnimator wsa = ws.mWinAnimator; 9826 if (wsa.mSurfaceControl != null) { 9827 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9828 } 9829 } 9830 if (pidCandidates.size() > 0) { 9831 int[] pids = new int[pidCandidates.size()]; 9832 for (int i=0; i<pids.length; i++) { 9833 pids[i] = pidCandidates.keyAt(i); 9834 } 9835 try { 9836 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9837 killedApps = true; 9838 } 9839 } catch (RemoteException e) { 9840 } 9841 } 9842 } 9843 } 9844 9845 if (leakedSurface || killedApps) { 9846 // We managed to reclaim some memory, so get rid of the trouble 9847 // surface and ask the app to request another one. 9848 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 9849 if (surface != null) { 9850 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9851 "RECOVER DESTROY", null); 9852 surface.destroy(); 9853 winAnimator.mSurfaceShown = false; 9854 winAnimator.mSurfaceControl = null; 9855 winAnimator.mWin.mHasSurface = false; 9856 scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken); 9857 } 9858 9859 try { 9860 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9861 } catch (RemoteException e) { 9862 } 9863 } 9864 } finally { 9865 Binder.restoreCallingIdentity(callingIdentity); 9866 } 9867 9868 return leakedSurface || killedApps; 9869 } 9870 9871 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9872 WindowState newFocus = computeFocusedWindowLocked(); 9873 if (mCurrentFocus != newFocus) { 9874 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9875 // This check makes sure that we don't already have the focus 9876 // change message pending. 9877 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9878 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9879 // TODO(multidisplay): Focused windows on default display only. 9880 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9881 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked( 9882 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 9883 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES); 9884 if (imWindowChanged) { 9885 displayContent.layoutNeeded = true; 9886 newFocus = computeFocusedWindowLocked(); 9887 } 9888 9889 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " + 9890 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 9891 final WindowState oldFocus = mCurrentFocus; 9892 mCurrentFocus = newFocus; 9893 mLosingFocus.remove(newFocus); 9894 9895 // TODO(multidisplay): Accessibilty supported only of default desiplay. 9896 if (mAccessibilityController != null 9897 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 9898 mAccessibilityController.onWindowFocusChangedLocked(); 9899 } 9900 9901 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9902 9903 if (imWindowChanged && oldFocus != mInputMethodWindow) { 9904 // Focus of the input method window changed. Perform layout if needed. 9905 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9906 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9907 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9908 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9909 // Client will do the layout, but we need to assign layers 9910 // for handleNewWindowLocked() below. 9911 assignLayersLocked(displayContent.getWindowList()); 9912 } 9913 } 9914 9915 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9916 // The change in focus caused us to need to do a layout. Okay. 9917 displayContent.layoutNeeded = true; 9918 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9919 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9920 } 9921 } 9922 9923 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9924 // If we defer assigning layers, then the caller is responsible for 9925 // doing this part. 9926 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 9927 } 9928 9929 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9930 return true; 9931 } 9932 return false; 9933 } 9934 9935 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 9936 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9937 } 9938 9939 private WindowState computeFocusedWindowLocked() { 9940 if (mAnimator.mUniverseBackground != null 9941 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 9942 return mAnimator.mUniverseBackground.mWin; 9943 } 9944 9945 final int displayCount = mDisplayContents.size(); 9946 for (int i = 0; i < displayCount; i++) { 9947 final DisplayContent displayContent = mDisplayContents.valueAt(i); 9948 WindowState win = findFocusedWindowLocked(displayContent); 9949 if (win != null) { 9950 return win; 9951 } 9952 } 9953 return null; 9954 } 9955 9956 private WindowState findFocusedWindowLocked(DisplayContent displayContent) { 9957 final WindowList windows = displayContent.getWindowList(); 9958 for (int i = windows.size() - 1; i >= 0; i--) { 9959 final WindowState win = windows.get(i); 9960 9961 if (localLOGV || DEBUG_FOCUS) Slog.v( 9962 TAG, "Looking for focus: " + i 9963 + " = " + win 9964 + ", flags=" + win.mAttrs.flags 9965 + ", canReceive=" + win.canReceiveKeys()); 9966 9967 AppWindowToken wtoken = win.mAppToken; 9968 9969 // If this window's application has been removed, just skip it. 9970 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 9971 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because " 9972 + (wtoken.removed ? "removed" : "sendingToBottom")); 9973 continue; 9974 } 9975 9976 if (!win.canReceiveKeys()) { 9977 continue; 9978 } 9979 9980 // Descend through all of the app tokens and find the first that either matches 9981 // win.mAppToken (return win) or mFocusedApp (return null). 9982 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && 9983 mFocusedApp != null) { 9984 ArrayList<Task> tasks = displayContent.getTasks(); 9985 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9986 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9987 int tokenNdx = tokens.size() - 1; 9988 for ( ; tokenNdx >= 0; --tokenNdx) { 9989 final AppWindowToken token = tokens.get(tokenNdx); 9990 if (wtoken == token) { 9991 break; 9992 } 9993 if (mFocusedApp == token) { 9994 // Whoops, we are below the focused app... no focus for you! 9995 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG, 9996 "findFocusedWindow: Reached focused app=" + mFocusedApp); 9997 return null; 9998 } 9999 } 10000 if (tokenNdx >= 0) { 10001 // Early exit from loop, must have found the matching token. 10002 break; 10003 } 10004 } 10005 } 10006 10007 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i + 10008 " = " + win); 10009 return win; 10010 } 10011 10012 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows."); 10013 return null; 10014 } 10015 10016 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 10017 if (mDisplayFrozen) { 10018 return; 10019 } 10020 10021 if (!mDisplayReady || !mPolicy.isScreenOnFully()) { 10022 // No need to freeze the screen before the system is ready or if 10023 // the screen is off. 10024 return; 10025 } 10026 10027 mScreenFrozenLock.acquire(); 10028 10029 mDisplayFrozen = true; 10030 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 10031 mLastFinishedFreezeSource = null; 10032 10033 mInputMonitor.freezeInputDispatchingLw(); 10034 10035 // Clear the last input window -- that is just used for 10036 // clean transitions between IMEs, and if we are freezing 10037 // the screen then the whole world is changing behind the scenes. 10038 mPolicy.setLastInputMethodWindowLw(null, null); 10039 10040 if (mAppTransition.isTransitionSet()) { 10041 mAppTransition.freeze(); 10042 } 10043 10044 if (PROFILE_ORIENTATION) { 10045 File file = new File("/data/system/frozen"); 10046 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 10047 } 10048 10049 if (CUSTOM_SCREEN_ROTATION) { 10050 mExitAnimId = exitAnim; 10051 mEnterAnimId = enterAnim; 10052 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10053 final int displayId = displayContent.getDisplayId(); 10054 ScreenRotationAnimation screenRotationAnimation = 10055 mAnimator.getScreenRotationAnimationLocked(displayId); 10056 if (screenRotationAnimation != null) { 10057 screenRotationAnimation.kill(); 10058 } 10059 10060 // Check whether the current screen contains any secure content. 10061 boolean isSecure = false; 10062 final WindowList windows = getDefaultWindowListLocked(); 10063 final int N = windows.size(); 10064 for (int i = 0; i < N; i++) { 10065 WindowState ws = windows.get(i); 10066 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) { 10067 isSecure = true; 10068 break; 10069 } 10070 } 10071 10072 // TODO(multidisplay): rotation on main screen only. 10073 displayContent.updateDisplayInfo(); 10074 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 10075 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure); 10076 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10077 } 10078 } 10079 10080 private void stopFreezingDisplayLocked() { 10081 if (!mDisplayFrozen) { 10082 return; 10083 } 10084 10085 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen 10086 || mClientFreezingScreen) { 10087 if (DEBUG_ORIENTATION) Slog.d(TAG, 10088 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 10089 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 10090 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 10091 + ", mClientFreezingScreen=" + mClientFreezingScreen); 10092 return; 10093 } 10094 10095 mDisplayFrozen = false; 10096 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 10097 StringBuilder sb = new StringBuilder(128); 10098 sb.append("Screen frozen for "); 10099 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 10100 if (mLastFinishedFreezeSource != null) { 10101 sb.append(" due to "); 10102 sb.append(mLastFinishedFreezeSource); 10103 } 10104 Slog.i(TAG, sb.toString()); 10105 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 10106 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 10107 if (PROFILE_ORIENTATION) { 10108 Debug.stopMethodTracing(); 10109 } 10110 10111 boolean updateRotation = false; 10112 10113 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10114 final int displayId = displayContent.getDisplayId(); 10115 ScreenRotationAnimation screenRotationAnimation = 10116 mAnimator.getScreenRotationAnimationLocked(displayId); 10117 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 10118 && screenRotationAnimation.hasScreenshot()) { 10119 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 10120 // TODO(multidisplay): rotation on main screen only. 10121 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10122 // Get rotation animation again, with new top window 10123 boolean isDimming = displayContent.isDimming(); 10124 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 10125 mExitAnimId = mEnterAnimId = 0; 10126 } 10127 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 10128 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, 10129 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 10130 scheduleAnimationLocked(); 10131 } else { 10132 screenRotationAnimation.kill(); 10133 screenRotationAnimation = null; 10134 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10135 updateRotation = true; 10136 } 10137 } else { 10138 if (screenRotationAnimation != null) { 10139 screenRotationAnimation.kill(); 10140 screenRotationAnimation = null; 10141 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10142 } 10143 updateRotation = true; 10144 } 10145 10146 mInputMonitor.thawInputDispatchingLw(); 10147 10148 boolean configChanged; 10149 10150 // While the display is frozen we don't re-compute the orientation 10151 // to avoid inconsistent states. However, something interesting 10152 // could have actually changed during that time so re-evaluate it 10153 // now to catch that. 10154 configChanged = updateOrientationFromAppTokensLocked(false); 10155 10156 // A little kludge: a lot could have happened while the 10157 // display was frozen, so now that we are coming back we 10158 // do a gc so that any remote references the system 10159 // processes holds on others can be released if they are 10160 // no longer needed. 10161 mH.removeMessages(H.FORCE_GC); 10162 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 10163 10164 mScreenFrozenLock.release(); 10165 10166 if (updateRotation) { 10167 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 10168 configChanged |= updateRotationUncheckedLocked(false); 10169 } 10170 10171 if (configChanged) { 10172 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10173 } 10174 } 10175 10176 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 10177 DisplayMetrics dm) { 10178 if (index < tokens.length) { 10179 String str = tokens[index]; 10180 if (str != null && str.length() > 0) { 10181 try { 10182 int val = Integer.parseInt(str); 10183 return val; 10184 } catch (Exception e) { 10185 } 10186 } 10187 } 10188 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 10189 return defDps; 10190 } 10191 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 10192 return val; 10193 } 10194 10195 void createWatermarkInTransaction() { 10196 if (mWatermark != null) { 10197 return; 10198 } 10199 10200 File file = new File("/system/etc/setup.conf"); 10201 FileInputStream in = null; 10202 DataInputStream ind = null; 10203 try { 10204 in = new FileInputStream(file); 10205 ind = new DataInputStream(in); 10206 String line = ind.readLine(); 10207 if (line != null) { 10208 String[] toks = line.split("%"); 10209 if (toks != null && toks.length > 0) { 10210 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 10211 mRealDisplayMetrics, mFxSession, toks); 10212 } 10213 } 10214 } catch (FileNotFoundException e) { 10215 } catch (IOException e) { 10216 } finally { 10217 if (ind != null) { 10218 try { 10219 ind.close(); 10220 } catch (IOException e) { 10221 } 10222 } else if (in != null) { 10223 try { 10224 in.close(); 10225 } catch (IOException e) { 10226 } 10227 } 10228 } 10229 } 10230 10231 @Override 10232 public void statusBarVisibilityChanged(int visibility) { 10233 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10234 != PackageManager.PERMISSION_GRANTED) { 10235 throw new SecurityException("Caller does not hold permission " 10236 + android.Manifest.permission.STATUS_BAR); 10237 } 10238 10239 synchronized (mWindowMap) { 10240 mLastStatusBarVisibility = visibility; 10241 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 10242 updateStatusBarVisibilityLocked(visibility); 10243 } 10244 } 10245 10246 // TOOD(multidisplay): StatusBar on multiple screens? 10247 void updateStatusBarVisibilityLocked(int visibility) { 10248 mInputManager.setSystemUiVisibility(visibility); 10249 final WindowList windows = getDefaultWindowListLocked(); 10250 final int N = windows.size(); 10251 for (int i = 0; i < N; i++) { 10252 WindowState ws = windows.get(i); 10253 try { 10254 int curValue = ws.mSystemUiVisibility; 10255 int diff = curValue ^ visibility; 10256 // We are only interested in differences of one of the 10257 // clearable flags... 10258 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 10259 // ...if it has actually been cleared. 10260 diff &= ~visibility; 10261 int newValue = (curValue&~diff) | (visibility&diff); 10262 if (newValue != curValue) { 10263 ws.mSeq++; 10264 ws.mSystemUiVisibility = newValue; 10265 } 10266 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 10267 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 10268 visibility, newValue, diff); 10269 } 10270 } catch (RemoteException e) { 10271 // so sorry 10272 } 10273 } 10274 } 10275 10276 @Override 10277 public void reevaluateStatusBarVisibility() { 10278 synchronized (mWindowMap) { 10279 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 10280 updateStatusBarVisibilityLocked(visibility); 10281 performLayoutAndPlaceSurfacesLocked(); 10282 } 10283 } 10284 10285 @Override 10286 public FakeWindow addFakeWindow(Looper looper, 10287 InputEventReceiver.Factory inputEventReceiverFactory, 10288 String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags, 10289 boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) { 10290 synchronized (mWindowMap) { 10291 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 10292 name, windowType, 10293 layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys, 10294 hasFocus, touchFullscreen); 10295 int i=0; 10296 while (i<mFakeWindows.size()) { 10297 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 10298 break; 10299 } 10300 } 10301 mFakeWindows.add(i, fw); 10302 mInputMonitor.updateInputWindowsLw(true); 10303 return fw; 10304 } 10305 } 10306 10307 boolean removeFakeWindowLocked(FakeWindow window) { 10308 synchronized (mWindowMap) { 10309 if (mFakeWindows.remove(window)) { 10310 mInputMonitor.updateInputWindowsLw(true); 10311 return true; 10312 } 10313 return false; 10314 } 10315 } 10316 10317 // It is assumed that this method is called only by InputMethodManagerService. 10318 public void saveLastInputMethodWindowForTransition() { 10319 synchronized (mWindowMap) { 10320 // TODO(multidisplay): Pass in the displayID. 10321 DisplayContent displayContent = getDefaultDisplayContentLocked(); 10322 if (mInputMethodWindow != null) { 10323 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 10324 } 10325 } 10326 } 10327 10328 public int getInputMethodWindowVisibleHeight() { 10329 synchronized (mWindowMap) { 10330 return mPolicy.getInputMethodWindowVisibleHeightLw(); 10331 } 10332 } 10333 10334 @Override 10335 public boolean hasNavigationBar() { 10336 return mPolicy.hasNavigationBar(); 10337 } 10338 10339 @Override 10340 public void lockNow(Bundle options) { 10341 mPolicy.lockNow(options); 10342 } 10343 10344 public void showRecentApps() { 10345 mPolicy.showRecentApps(); 10346 } 10347 10348 @Override 10349 public boolean isSafeModeEnabled() { 10350 return mSafeMode; 10351 } 10352 10353 @Override 10354 public boolean clearWindowContentFrameStats(IBinder token) { 10355 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10356 "clearWindowContentFrameStats()")) { 10357 throw new SecurityException("Requires FRAME_STATS permission"); 10358 } 10359 synchronized (mWindowMap) { 10360 WindowState windowState = mWindowMap.get(token); 10361 if (windowState == null) { 10362 return false; 10363 } 10364 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10365 if (surfaceControl == null) { 10366 return false; 10367 } 10368 return surfaceControl.clearContentFrameStats(); 10369 } 10370 } 10371 10372 @Override 10373 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) { 10374 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10375 "getWindowContentFrameStats()")) { 10376 throw new SecurityException("Requires FRAME_STATS permission"); 10377 } 10378 synchronized (mWindowMap) { 10379 WindowState windowState = mWindowMap.get(token); 10380 if (windowState == null) { 10381 return null; 10382 } 10383 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10384 if (surfaceControl == null) { 10385 return null; 10386 } 10387 if (mTempWindowRenderStats == null) { 10388 mTempWindowRenderStats = new WindowContentFrameStats(); 10389 } 10390 WindowContentFrameStats stats = mTempWindowRenderStats; 10391 if (!surfaceControl.getContentFrameStats(stats)) { 10392 return null; 10393 } 10394 return stats; 10395 } 10396 } 10397 10398 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10399 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 10400 mPolicy.dump(" ", pw, args); 10401 } 10402 10403 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10404 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 10405 mAnimator.dumpLocked(pw, " ", dumpAll); 10406 } 10407 10408 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 10409 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 10410 if (mTokenMap.size() > 0) { 10411 pw.println(" All tokens:"); 10412 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10413 while (it.hasNext()) { 10414 WindowToken token = it.next(); 10415 pw.print(" "); pw.print(token); 10416 if (dumpAll) { 10417 pw.println(':'); 10418 token.dump(pw, " "); 10419 } else { 10420 pw.println(); 10421 } 10422 } 10423 } 10424 if (mWallpaperTokens.size() > 0) { 10425 pw.println(); 10426 pw.println(" Wallpaper tokens:"); 10427 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 10428 WindowToken token = mWallpaperTokens.get(i); 10429 pw.print(" Wallpaper #"); pw.print(i); 10430 pw.print(' '); pw.print(token); 10431 if (dumpAll) { 10432 pw.println(':'); 10433 token.dump(pw, " "); 10434 } else { 10435 pw.println(); 10436 } 10437 } 10438 } 10439 if (mFinishedStarting.size() > 0) { 10440 pw.println(); 10441 pw.println(" Finishing start of application tokens:"); 10442 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10443 WindowToken token = mFinishedStarting.get(i); 10444 pw.print(" Finished Starting #"); pw.print(i); 10445 pw.print(' '); pw.print(token); 10446 if (dumpAll) { 10447 pw.println(':'); 10448 token.dump(pw, " "); 10449 } else { 10450 pw.println(); 10451 } 10452 } 10453 } 10454 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 10455 pw.println(); 10456 if (mOpeningApps.size() > 0) { 10457 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10458 } 10459 if (mClosingApps.size() > 0) { 10460 pw.print(" mClosingApps="); pw.println(mClosingApps); 10461 } 10462 } 10463 } 10464 10465 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 10466 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 10467 for (int i=0; i<mSessions.size(); i++) { 10468 Session s = mSessions.valueAt(i); 10469 pw.print(" Session "); pw.print(s); pw.println(':'); 10470 s.dump(pw, " "); 10471 } 10472 } 10473 10474 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 10475 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 10476 if (mDisplayReady) { 10477 final int numDisplays = mDisplayContents.size(); 10478 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10479 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10480 displayContent.dump(" ", pw); 10481 } 10482 } else { 10483 pw.println(" NO DISPLAY"); 10484 } 10485 } 10486 10487 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 10488 ArrayList<WindowState> windows) { 10489 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 10490 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 10491 } 10492 10493 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 10494 ArrayList<WindowState> windows) { 10495 final int numDisplays = mDisplayContents.size(); 10496 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10497 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); 10498 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10499 final WindowState w = windowList.get(winNdx); 10500 if (windows == null || windows.contains(w)) { 10501 pw.print(" Window #"); pw.print(winNdx); pw.print(' '); 10502 pw.print(w); pw.println(":"); 10503 w.dump(pw, " ", dumpAll || windows != null); 10504 } 10505 } 10506 } 10507 if (mInputMethodDialogs.size() > 0) { 10508 pw.println(); 10509 pw.println(" Input method dialogs:"); 10510 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 10511 WindowState w = mInputMethodDialogs.get(i); 10512 if (windows == null || windows.contains(w)) { 10513 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 10514 } 10515 } 10516 } 10517 if (mPendingRemove.size() > 0) { 10518 pw.println(); 10519 pw.println(" Remove pending for:"); 10520 for (int i=mPendingRemove.size()-1; i>=0; i--) { 10521 WindowState w = mPendingRemove.get(i); 10522 if (windows == null || windows.contains(w)) { 10523 pw.print(" Remove #"); pw.print(i); pw.print(' '); 10524 pw.print(w); 10525 if (dumpAll) { 10526 pw.println(":"); 10527 w.dump(pw, " ", true); 10528 } else { 10529 pw.println(); 10530 } 10531 } 10532 } 10533 } 10534 if (mForceRemoves != null && mForceRemoves.size() > 0) { 10535 pw.println(); 10536 pw.println(" Windows force removing:"); 10537 for (int i=mForceRemoves.size()-1; i>=0; i--) { 10538 WindowState w = mForceRemoves.get(i); 10539 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10540 pw.print(w); 10541 if (dumpAll) { 10542 pw.println(":"); 10543 w.dump(pw, " ", true); 10544 } else { 10545 pw.println(); 10546 } 10547 } 10548 } 10549 if (mDestroySurface.size() > 0) { 10550 pw.println(); 10551 pw.println(" Windows waiting to destroy their surface:"); 10552 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10553 WindowState w = mDestroySurface.get(i); 10554 if (windows == null || windows.contains(w)) { 10555 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10556 pw.print(w); 10557 if (dumpAll) { 10558 pw.println(":"); 10559 w.dump(pw, " ", true); 10560 } else { 10561 pw.println(); 10562 } 10563 } 10564 } 10565 } 10566 if (mLosingFocus.size() > 0) { 10567 pw.println(); 10568 pw.println(" Windows losing focus:"); 10569 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10570 WindowState w = mLosingFocus.get(i); 10571 if (windows == null || windows.contains(w)) { 10572 pw.print(" Losing #"); pw.print(i); pw.print(' '); 10573 pw.print(w); 10574 if (dumpAll) { 10575 pw.println(":"); 10576 w.dump(pw, " ", true); 10577 } else { 10578 pw.println(); 10579 } 10580 } 10581 } 10582 } 10583 if (mResizingWindows.size() > 0) { 10584 pw.println(); 10585 pw.println(" Windows waiting to resize:"); 10586 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10587 WindowState w = mResizingWindows.get(i); 10588 if (windows == null || windows.contains(w)) { 10589 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 10590 pw.print(w); 10591 if (dumpAll) { 10592 pw.println(":"); 10593 w.dump(pw, " ", true); 10594 } else { 10595 pw.println(); 10596 } 10597 } 10598 } 10599 } 10600 if (mWaitingForDrawn.size() > 0) { 10601 pw.println(); 10602 pw.println(" Clients waiting for these windows to be drawn:"); 10603 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10604 WindowState win = mWaitingForDrawn.get(i); 10605 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); 10606 } 10607 } 10608 pw.println(); 10609 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10610 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10611 if (mLastFocus != mCurrentFocus) { 10612 pw.print(" mLastFocus="); pw.println(mLastFocus); 10613 } 10614 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10615 if (mInputMethodTarget != null) { 10616 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10617 } 10618 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10619 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10620 pw.print(" mLastDisplayFreezeDuration="); 10621 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 10622 if ( mLastFinishedFreezeSource != null) { 10623 pw.print(" due to "); 10624 pw.print(mLastFinishedFreezeSource); 10625 } 10626 pw.println(); 10627 if (dumpAll) { 10628 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 10629 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 10630 if (mLastStatusBarVisibility != 0) { 10631 pw.print(" mLastStatusBarVisibility=0x"); 10632 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 10633 } 10634 if (mInputMethodWindow != null) { 10635 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10636 } 10637 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 10638 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) { 10639 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 10640 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 10641 } 10642 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 10643 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 10644 if (mInputMethodAnimLayerAdjustment != 0 || 10645 mWallpaperAnimLayerAdjustment != 0) { 10646 pw.print(" mInputMethodAnimLayerAdjustment="); 10647 pw.print(mInputMethodAnimLayerAdjustment); 10648 pw.print(" mWallpaperAnimLayerAdjustment="); 10649 pw.println(mWallpaperAnimLayerAdjustment); 10650 } 10651 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10652 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10653 if (needsLayout()) { 10654 pw.print(" layoutNeeded on displays="); 10655 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10656 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10657 if (displayContent.layoutNeeded) { 10658 pw.print(displayContent.getDisplayId()); 10659 } 10660 } 10661 pw.println(); 10662 } 10663 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 10664 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10665 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 10666 pw.print(" client="); pw.print(mClientFreezingScreen); 10667 pw.print(" apps="); pw.print(mAppsFreezingScreen); 10668 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 10669 pw.print(" mRotation="); pw.print(mRotation); 10670 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 10671 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 10672 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 10673 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 10674 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled); 10675 pw.print(" window="); pw.print(mWindowAnimationScaleSetting); 10676 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); 10677 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); 10678 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); 10679 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 10680 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 10681 pw.println(" mLayoutToAnim:"); 10682 mAppTransition.dump(pw); 10683 } 10684 } 10685 10686 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10687 int opti, boolean dumpAll) { 10688 WindowList windows = new WindowList(); 10689 if ("visible".equals(name)) { 10690 synchronized(mWindowMap) { 10691 final int numDisplays = mDisplayContents.size(); 10692 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10693 final WindowList windowList = 10694 mDisplayContents.valueAt(displayNdx).getWindowList(); 10695 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10696 final WindowState w = windowList.get(winNdx); 10697 if (w.mWinAnimator.mSurfaceShown) { 10698 windows.add(w); 10699 } 10700 } 10701 } 10702 } 10703 } else { 10704 int objectId = 0; 10705 // See if this is an object ID. 10706 try { 10707 objectId = Integer.parseInt(name, 16); 10708 name = null; 10709 } catch (RuntimeException e) { 10710 } 10711 synchronized(mWindowMap) { 10712 final int numDisplays = mDisplayContents.size(); 10713 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10714 final WindowList windowList = 10715 mDisplayContents.valueAt(displayNdx).getWindowList(); 10716 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10717 final WindowState w = windowList.get(winNdx); 10718 if (name != null) { 10719 if (w.mAttrs.getTitle().toString().contains(name)) { 10720 windows.add(w); 10721 } 10722 } else if (System.identityHashCode(w) == objectId) { 10723 windows.add(w); 10724 } 10725 } 10726 } 10727 } 10728 } 10729 10730 if (windows.size() <= 0) { 10731 return false; 10732 } 10733 10734 synchronized(mWindowMap) { 10735 dumpWindowsLocked(pw, dumpAll, windows); 10736 } 10737 return true; 10738 } 10739 10740 void dumpLastANRLocked(PrintWriter pw) { 10741 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10742 if (mLastANRState == null) { 10743 pw.println(" <no ANR has occurred since boot>"); 10744 } else { 10745 pw.println(mLastANRState); 10746 } 10747 } 10748 10749 /** 10750 * Saves information about the state of the window manager at 10751 * the time an ANR occurred before anything else in the system changes 10752 * in response. 10753 * 10754 * @param appWindowToken The application that ANR'd, may be null. 10755 * @param windowState The window that ANR'd, may be null. 10756 * @param reason The reason for the ANR, may be null. 10757 */ 10758 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, 10759 String reason) { 10760 StringWriter sw = new StringWriter(); 10761 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 10762 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10763 if (appWindowToken != null) { 10764 pw.println(" Application at fault: " + appWindowToken.stringName); 10765 } 10766 if (windowState != null) { 10767 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10768 } 10769 if (reason != null) { 10770 pw.println(" Reason: " + reason); 10771 } 10772 pw.println(); 10773 dumpWindowsNoHeaderLocked(pw, true, null); 10774 pw.close(); 10775 mLastANRState = sw.toString(); 10776 } 10777 10778 @Override 10779 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10780 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10781 != PackageManager.PERMISSION_GRANTED) { 10782 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10783 + Binder.getCallingPid() 10784 + ", uid=" + Binder.getCallingUid()); 10785 return; 10786 } 10787 10788 boolean dumpAll = false; 10789 10790 int opti = 0; 10791 while (opti < args.length) { 10792 String opt = args[opti]; 10793 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10794 break; 10795 } 10796 opti++; 10797 if ("-a".equals(opt)) { 10798 dumpAll = true; 10799 } else if ("-h".equals(opt)) { 10800 pw.println("Window manager dump options:"); 10801 pw.println(" [-a] [-h] [cmd] ..."); 10802 pw.println(" cmd may be one of:"); 10803 pw.println(" l[astanr]: last ANR information"); 10804 pw.println(" p[policy]: policy state"); 10805 pw.println(" a[animator]: animator state"); 10806 pw.println(" s[essions]: active sessions"); 10807 pw.println(" d[isplays]: active display contents"); 10808 pw.println(" t[okens]: token list"); 10809 pw.println(" w[indows]: window list"); 10810 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10811 pw.println(" be a partial substring in a window name, a"); 10812 pw.println(" Window hex object identifier, or"); 10813 pw.println(" \"all\" for all windows, or"); 10814 pw.println(" \"visible\" for the visible windows."); 10815 pw.println(" -a: include all available server state."); 10816 return; 10817 } else { 10818 pw.println("Unknown argument: " + opt + "; use -h for help"); 10819 } 10820 } 10821 10822 // Is the caller requesting to dump a particular piece of data? 10823 if (opti < args.length) { 10824 String cmd = args[opti]; 10825 opti++; 10826 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10827 synchronized(mWindowMap) { 10828 dumpLastANRLocked(pw); 10829 } 10830 return; 10831 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10832 synchronized(mWindowMap) { 10833 dumpPolicyLocked(pw, args, true); 10834 } 10835 return; 10836 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 10837 synchronized(mWindowMap) { 10838 dumpAnimatorLocked(pw, args, true); 10839 } 10840 return; 10841 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10842 synchronized(mWindowMap) { 10843 dumpSessionsLocked(pw, true); 10844 } 10845 return; 10846 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 10847 synchronized(mWindowMap) { 10848 dumpDisplayContentsLocked(pw, true); 10849 } 10850 return; 10851 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10852 synchronized(mWindowMap) { 10853 dumpTokensLocked(pw, true); 10854 } 10855 return; 10856 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10857 synchronized(mWindowMap) { 10858 dumpWindowsLocked(pw, true, null); 10859 } 10860 return; 10861 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10862 synchronized(mWindowMap) { 10863 dumpWindowsLocked(pw, true, null); 10864 } 10865 return; 10866 } else { 10867 // Dumping a single name? 10868 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10869 pw.println("Bad window command, or no windows match: " + cmd); 10870 pw.println("Use -h for help."); 10871 } 10872 return; 10873 } 10874 } 10875 10876 synchronized(mWindowMap) { 10877 pw.println(); 10878 if (dumpAll) { 10879 pw.println("-------------------------------------------------------------------------------"); 10880 } 10881 dumpLastANRLocked(pw); 10882 pw.println(); 10883 if (dumpAll) { 10884 pw.println("-------------------------------------------------------------------------------"); 10885 } 10886 dumpPolicyLocked(pw, args, dumpAll); 10887 pw.println(); 10888 if (dumpAll) { 10889 pw.println("-------------------------------------------------------------------------------"); 10890 } 10891 dumpAnimatorLocked(pw, args, dumpAll); 10892 pw.println(); 10893 if (dumpAll) { 10894 pw.println("-------------------------------------------------------------------------------"); 10895 } 10896 dumpSessionsLocked(pw, dumpAll); 10897 pw.println(); 10898 if (dumpAll) { 10899 pw.println("-------------------------------------------------------------------------------"); 10900 } 10901 dumpDisplayContentsLocked(pw, dumpAll); 10902 pw.println(); 10903 if (dumpAll) { 10904 pw.println("-------------------------------------------------------------------------------"); 10905 } 10906 dumpTokensLocked(pw, dumpAll); 10907 pw.println(); 10908 if (dumpAll) { 10909 pw.println("-------------------------------------------------------------------------------"); 10910 } 10911 dumpWindowsLocked(pw, dumpAll, null); 10912 } 10913 } 10914 10915 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10916 @Override 10917 public void monitor() { 10918 synchronized (mWindowMap) { } 10919 } 10920 10921 public interface OnHardKeyboardStatusChangeListener { 10922 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 10923 } 10924 10925 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 10926 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 10927 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 10928 Integer.toHexString(pendingLayoutChanges)); 10929 } 10930 } 10931 10932 private DisplayContent newDisplayContentLocked(final Display display) { 10933 DisplayContent displayContent = new DisplayContent(display, this); 10934 final int displayId = display.getDisplayId(); 10935 if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display); 10936 mDisplayContents.put(displayId, displayContent); 10937 10938 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10939 final Rect rect = new Rect(); 10940 mDisplaySettings.getOverscanLocked(displayInfo.name, rect); 10941 synchronized (displayContent.mDisplaySizeLock) { 10942 displayInfo.overscanLeft = rect.left; 10943 displayInfo.overscanTop = rect.top; 10944 displayInfo.overscanRight = rect.right; 10945 displayInfo.overscanBottom = rect.bottom; 10946 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 10947 displayId, displayInfo); 10948 } 10949 configureDisplayPolicyLocked(displayContent); 10950 10951 // TODO: Create an input channel for each display with touch capability. 10952 if (displayId == Display.DEFAULT_DISPLAY) { 10953 displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent); 10954 registerPointerEventListener(displayContent.mTapDetector); 10955 } 10956 10957 return displayContent; 10958 } 10959 10960 public void createDisplayContentLocked(final Display display) { 10961 if (display == null) { 10962 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 10963 } 10964 getDisplayContentLocked(display.getDisplayId()); 10965 } 10966 10967 /** 10968 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 10969 * there is a Display for the displayId. 10970 * @param displayId The display the caller is interested in. 10971 * @return The DisplayContent associated with displayId or null if there is no Display for it. 10972 */ 10973 public DisplayContent getDisplayContentLocked(final int displayId) { 10974 DisplayContent displayContent = mDisplayContents.get(displayId); 10975 if (displayContent == null) { 10976 final Display display = mDisplayManager.getDisplay(displayId); 10977 if (display != null) { 10978 displayContent = newDisplayContentLocked(display); 10979 } 10980 } 10981 return displayContent; 10982 } 10983 10984 // There is an inherent assumption that this will never return null. 10985 public DisplayContent getDefaultDisplayContentLocked() { 10986 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 10987 } 10988 10989 public WindowList getDefaultWindowListLocked() { 10990 return getDefaultDisplayContentLocked().getWindowList(); 10991 } 10992 10993 public DisplayInfo getDefaultDisplayInfoLocked() { 10994 return getDefaultDisplayContentLocked().getDisplayInfo(); 10995 } 10996 10997 /** 10998 * Return the list of WindowStates associated on the passed display. 10999 * @param display The screen to return windows from. 11000 * @return The list of WindowStates on the screen, or null if the there is no screen. 11001 */ 11002 public WindowList getWindowListLocked(final Display display) { 11003 return getWindowListLocked(display.getDisplayId()); 11004 } 11005 11006 /** 11007 * Return the list of WindowStates associated on the passed display. 11008 * @param displayId The screen to return windows from. 11009 * @return The list of WindowStates on the screen, or null if the there is no screen. 11010 */ 11011 public WindowList getWindowListLocked(final int displayId) { 11012 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11013 return displayContent != null ? displayContent.getWindowList() : null; 11014 } 11015 11016 public void onDisplayAdded(int displayId) { 11017 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 11018 } 11019 11020 public void handleDisplayAdded(int displayId) { 11021 synchronized (mWindowMap) { 11022 final Display display = mDisplayManager.getDisplay(displayId); 11023 if (display != null) { 11024 createDisplayContentLocked(display); 11025 displayReady(displayId); 11026 } 11027 } 11028 } 11029 11030 public void onDisplayRemoved(int displayId) { 11031 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 11032 } 11033 11034 private void handleDisplayRemovedLocked(int displayId) { 11035 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11036 if (displayContent != null) { 11037 if (displayContent.isAnimating()) { 11038 displayContent.mDeferredRemoval = true; 11039 return; 11040 } 11041 if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent); 11042 mDisplayContents.delete(displayId); 11043 displayContent.close(); 11044 if (displayId == Display.DEFAULT_DISPLAY) { 11045 unregisterPointerEventListener(displayContent.mTapDetector); 11046 } 11047 } 11048 mAnimator.removeDisplayLocked(displayId); 11049 } 11050 11051 public void onDisplayChanged(int displayId) { 11052 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 11053 } 11054 11055 private void handleDisplayChangedLocked(int displayId) { 11056 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11057 if (displayContent != null) { 11058 displayContent.updateDisplayInfo(); 11059 } 11060 } 11061 11062 @Override 11063 public Object getWindowManagerLock() { 11064 return mWindowMap; 11065 } 11066 11067 private final class LocalService extends WindowManagerInternal { 11068 @Override 11069 public void requestTraversalFromDisplayManager() { 11070 requestTraversal(); 11071 } 11072 11073 @Override 11074 public void setMagnificationSpec(MagnificationSpec spec) { 11075 synchronized (mWindowMap) { 11076 if (mAccessibilityController != null) { 11077 mAccessibilityController.setMagnificationSpecLocked(spec); 11078 } else { 11079 throw new IllegalStateException("Magnification callbacks not set!"); 11080 } 11081 } 11082 if (Binder.getCallingPid() != android.os.Process.myPid()) { 11083 spec.recycle(); 11084 } 11085 } 11086 11087 @Override 11088 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { 11089 synchronized (mWindowMap) { 11090 WindowState windowState = mWindowMap.get(windowToken); 11091 if (windowState == null) { 11092 return null; 11093 } 11094 MagnificationSpec spec = null; 11095 if (mAccessibilityController != null) { 11096 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState); 11097 } 11098 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) { 11099 return null; 11100 } 11101 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec); 11102 spec.scale *= windowState.mGlobalScale; 11103 return spec; 11104 } 11105 } 11106 11107 @Override 11108 public void setMagnificationCallbacks(MagnificationCallbacks callbacks) { 11109 synchronized (mWindowMap) { 11110 if (mAccessibilityController == null) { 11111 mAccessibilityController = new AccessibilityController( 11112 WindowManagerService.this); 11113 } 11114 mAccessibilityController.setMagnificationCallbacksLocked(callbacks); 11115 if (!mAccessibilityController.hasCallbacksLocked()) { 11116 mAccessibilityController = null; 11117 } 11118 } 11119 } 11120 11121 @Override 11122 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) { 11123 synchronized (mWindowMap) { 11124 if (mAccessibilityController == null) { 11125 mAccessibilityController = new AccessibilityController( 11126 WindowManagerService.this); 11127 } 11128 mAccessibilityController.setWindowsForAccessibilityCallback(callback); 11129 if (!mAccessibilityController.hasCallbacksLocked()) { 11130 mAccessibilityController = null; 11131 } 11132 } 11133 } 11134 11135 @Override 11136 public void setInputFilter(IInputFilter filter) { 11137 mInputManager.setInputFilter(filter); 11138 } 11139 11140 @Override 11141 public IBinder getFocusedWindowToken() { 11142 synchronized (mWindowMap) { 11143 WindowState windowState = getFocusedWindowLocked(); 11144 if (windowState != null) { 11145 return windowState.mClient.asBinder(); 11146 } 11147 return null; 11148 } 11149 } 11150 11151 @Override 11152 public boolean isKeyguardLocked() { 11153 return WindowManagerService.this.isKeyguardLocked(); 11154 } 11155 11156 @Override 11157 public void showGlobalActions() { 11158 WindowManagerService.this.showGlobalActions(); 11159 } 11160 11161 @Override 11162 public void getWindowFrame(IBinder token, Rect outBounds) { 11163 synchronized (mWindowMap) { 11164 WindowState windowState = mWindowMap.get(token); 11165 if (windowState != null) { 11166 outBounds.set(windowState.mFrame); 11167 } else { 11168 outBounds.setEmpty(); 11169 } 11170 } 11171 } 11172 11173 public void waitForAllWindowsDrawn(Runnable callback, long timeout) { 11174 synchronized (mWindowMap) { 11175 mWaitingForDrawnCallback = callback; 11176 final WindowList windows = getDefaultWindowListLocked(); 11177 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 11178 final WindowState win = windows.get(winNdx); 11179 if (win.mHasSurface && win.isWinVisibleLw()) { 11180 if (!win.mIsWallpaper) { 11181 // Don't force wallpaper to redraw. 11182 win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 11183 } 11184 // Force add to mResizingWindows. 11185 win.mLastContentInsets.set(-1, -1, -1, -1); 11186 mWaitingForDrawn.add(win); 11187 } 11188 } 11189 requestTraversalLocked(); 11190 } 11191 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 11192 if (mWaitingForDrawn.isEmpty()) { 11193 callback.run(); 11194 } else { 11195 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); 11196 checkDrawnWindowsLocked(); 11197 } 11198 } 11199 } 11200} 11201