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