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