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