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