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