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