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