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