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