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