WindowManagerService.java revision 164683221948c13fd9b652416c5cc1621df6401b
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 requestTraversal(); 4204 } 4205 } 4206 4207 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp, 4208 boolean visible, int transit, boolean performLayout) { 4209 boolean delayed = false; 4210 4211 if (wtoken.clientHidden == visible) { 4212 wtoken.clientHidden = !visible; 4213 wtoken.sendAppVisibilityToClients(); 4214 } 4215 4216 wtoken.willBeHidden = false; 4217 if (wtoken.hidden == visible) { 4218 boolean changed = false; 4219 if (DEBUG_APP_TRANSITIONS) Slog.v( 4220 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden 4221 + " performLayout=" + performLayout); 4222 4223 boolean runningAppAnimation = false; 4224 4225 if (transit != AppTransition.TRANSIT_UNSET) { 4226 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { 4227 wtoken.mAppAnimator.animation = null; 4228 } 4229 if (applyAnimationLocked(wtoken, lp, transit, visible)) { 4230 delayed = runningAppAnimation = true; 4231 } 4232 WindowState window = wtoken.findMainWindow(); 4233 //TODO (multidisplay): Magnification is supported only for the default display. 4234 if (window != null && mDisplayMagnifier != null 4235 && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 4236 mDisplayMagnifier.onAppWindowTransitionLocked(window, transit); 4237 } 4238 changed = true; 4239 } 4240 4241 final int N = wtoken.allAppWindows.size(); 4242 for (int i=0; i<N; i++) { 4243 WindowState win = wtoken.allAppWindows.get(i); 4244 if (win == wtoken.startingWindow) { 4245 continue; 4246 } 4247 4248 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible()); 4249 //win.dump(" "); 4250 if (visible) { 4251 if (!win.isVisibleNow()) { 4252 if (!runningAppAnimation) { 4253 win.mWinAnimator.applyAnimationLocked( 4254 WindowManagerPolicy.TRANSIT_ENTER, true); 4255 //TODO (multidisplay): Magnification is supported only for the default 4256 if (mDisplayMagnifier != null 4257 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4258 mDisplayMagnifier.onWindowTransitionLocked(win, 4259 WindowManagerPolicy.TRANSIT_ENTER); 4260 } 4261 } 4262 changed = true; 4263 final DisplayContent displayContent = win.getDisplayContent(); 4264 if (displayContent != null) { 4265 displayContent.layoutNeeded = true; 4266 } 4267 } 4268 } else if (win.isVisibleNow()) { 4269 if (!runningAppAnimation) { 4270 win.mWinAnimator.applyAnimationLocked( 4271 WindowManagerPolicy.TRANSIT_EXIT, false); 4272 //TODO (multidisplay): Magnification is supported only for the default 4273 if (mDisplayMagnifier != null 4274 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4275 mDisplayMagnifier.onWindowTransitionLocked(win, 4276 WindowManagerPolicy.TRANSIT_EXIT); 4277 } 4278 } 4279 changed = true; 4280 final DisplayContent displayContent = win.getDisplayContent(); 4281 if (displayContent != null) { 4282 displayContent.layoutNeeded = true; 4283 } 4284 } 4285 } 4286 4287 wtoken.hidden = wtoken.hiddenRequested = !visible; 4288 if (!visible) { 4289 unsetAppFreezingScreenLocked(wtoken, true, true); 4290 } else { 4291 // If we are being set visible, and the starting window is 4292 // not yet displayed, then make sure it doesn't get displayed. 4293 WindowState swin = wtoken.startingWindow; 4294 if (swin != null && !swin.isDrawnLw()) { 4295 swin.mPolicyVisibility = false; 4296 swin.mPolicyVisibilityAfterAnim = false; 4297 } 4298 } 4299 4300 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken 4301 + ": hidden=" + wtoken.hidden + " hiddenRequested=" 4302 + wtoken.hiddenRequested); 4303 4304 if (changed) { 4305 mInputMonitor.setUpdateInputWindowsNeededLw(); 4306 if (performLayout) { 4307 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4308 false /*updateInputWindows*/); 4309 performLayoutAndPlaceSurfacesLocked(); 4310 } 4311 mInputMonitor.updateInputWindowsLw(false /*force*/); 4312 } 4313 } 4314 4315 if (wtoken.mAppAnimator.animation != null) { 4316 delayed = true; 4317 } 4318 4319 for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) { 4320 if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) { 4321 delayed = true; 4322 } 4323 } 4324 4325 return delayed; 4326 } 4327 4328 @Override 4329 public void setAppVisibility(IBinder token, boolean visible) { 4330 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4331 "setAppVisibility()")) { 4332 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4333 } 4334 4335 AppWindowToken wtoken; 4336 4337 synchronized(mWindowMap) { 4338 wtoken = findAppWindowToken(token); 4339 if (wtoken == null) { 4340 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token); 4341 return; 4342 } 4343 4344 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) { 4345 RuntimeException e = null; 4346 if (!HIDE_STACK_CRAWLS) { 4347 e = new RuntimeException(); 4348 e.fillInStackTrace(); 4349 } 4350 Slog.v(TAG, "setAppVisibility(" + token + ", visible=" + visible 4351 + "): " + mAppTransition 4352 + " hidden=" + wtoken.hidden 4353 + " hiddenRequested=" + wtoken.hiddenRequested, e); 4354 } 4355 4356 // If we are preparing an app transition, then delay changing 4357 // the visibility of this token until we execute that transition. 4358 if (okToDisplay() && mAppTransition.isTransitionSet()) { 4359 wtoken.hiddenRequested = !visible; 4360 4361 if (!wtoken.startingDisplayed) { 4362 if (DEBUG_APP_TRANSITIONS) Slog.v( 4363 TAG, "Setting dummy animation on: " + wtoken); 4364 wtoken.mAppAnimator.setDummyAnimation(); 4365 } 4366 mOpeningApps.remove(wtoken); 4367 mClosingApps.remove(wtoken); 4368 wtoken.waitingToShow = wtoken.waitingToHide = false; 4369 wtoken.inPendingTransaction = true; 4370 if (visible) { 4371 mOpeningApps.add(wtoken); 4372 wtoken.startingMoved = false; 4373 4374 // If the token is currently hidden (should be the 4375 // common case), then we need to set up to wait for 4376 // its windows to be ready. 4377 if (wtoken.hidden) { 4378 wtoken.allDrawn = false; 4379 wtoken.deferClearAllDrawn = false; 4380 wtoken.waitingToShow = true; 4381 4382 if (wtoken.clientHidden) { 4383 // In the case where we are making an app visible 4384 // but holding off for a transition, we still need 4385 // to tell the client to make its windows visible so 4386 // they get drawn. Otherwise, we will wait on 4387 // performing the transition until all windows have 4388 // been drawn, they never will be, and we are sad. 4389 wtoken.clientHidden = false; 4390 wtoken.sendAppVisibilityToClients(); 4391 } 4392 } 4393 } else { 4394 mClosingApps.add(wtoken); 4395 4396 // If the token is currently visible (should be the 4397 // common case), then set up to wait for it to be hidden. 4398 if (!wtoken.hidden) { 4399 wtoken.waitingToHide = true; 4400 } 4401 } 4402 return; 4403 } 4404 4405 final long origId = Binder.clearCallingIdentity(); 4406 setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET, 4407 true); 4408 wtoken.updateReportedVisibilityLocked(); 4409 Binder.restoreCallingIdentity(origId); 4410 } 4411 } 4412 4413 void unsetAppFreezingScreenLocked(AppWindowToken wtoken, 4414 boolean unfreezeSurfaceNow, boolean force) { 4415 if (wtoken.mAppAnimator.freezingScreen) { 4416 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken 4417 + " force=" + force); 4418 final int N = wtoken.allAppWindows.size(); 4419 boolean unfrozeWindows = false; 4420 for (int i=0; i<N; i++) { 4421 WindowState w = wtoken.allAppWindows.get(i); 4422 if (w.mAppFreezing) { 4423 w.mAppFreezing = false; 4424 if (w.mHasSurface && !w.mOrientationChanging) { 4425 if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w); 4426 w.mOrientationChanging = true; 4427 mInnerFields.mOrientationChangeComplete = false; 4428 } 4429 w.mLastFreezeDuration = 0; 4430 unfrozeWindows = true; 4431 final DisplayContent displayContent = w.getDisplayContent(); 4432 if (displayContent != null) { 4433 displayContent.layoutNeeded = true; 4434 } 4435 } 4436 } 4437 if (force || unfrozeWindows) { 4438 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken); 4439 wtoken.mAppAnimator.freezingScreen = false; 4440 wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime() 4441 - mDisplayFreezeTime); 4442 mAppsFreezingScreen--; 4443 mLastFinishedFreezeSource = wtoken; 4444 } 4445 if (unfreezeSurfaceNow) { 4446 if (unfrozeWindows) { 4447 performLayoutAndPlaceSurfacesLocked(); 4448 } 4449 stopFreezingDisplayLocked(); 4450 } 4451 } 4452 } 4453 4454 private void startAppFreezingScreenLocked(AppWindowToken wtoken) { 4455 if (DEBUG_ORIENTATION) { 4456 RuntimeException e = null; 4457 if (!HIDE_STACK_CRAWLS) { 4458 e = new RuntimeException(); 4459 e.fillInStackTrace(); 4460 } 4461 Slog.i(TAG, "Set freezing of " + wtoken.appToken 4462 + ": hidden=" + wtoken.hidden + " freezing=" 4463 + wtoken.mAppAnimator.freezingScreen, e); 4464 } 4465 if (!wtoken.hiddenRequested) { 4466 if (!wtoken.mAppAnimator.freezingScreen) { 4467 wtoken.mAppAnimator.freezingScreen = true; 4468 wtoken.mAppAnimator.lastFreezeDuration = 0; 4469 mAppsFreezingScreen++; 4470 if (mAppsFreezingScreen == 1) { 4471 startFreezingDisplayLocked(false, 0, 0); 4472 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 4473 mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000); 4474 } 4475 } 4476 final int N = wtoken.allAppWindows.size(); 4477 for (int i=0; i<N; i++) { 4478 WindowState w = wtoken.allAppWindows.get(i); 4479 w.mAppFreezing = true; 4480 } 4481 } 4482 } 4483 4484 @Override 4485 public void startAppFreezingScreen(IBinder token, int configChanges) { 4486 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4487 "setAppFreezingScreen()")) { 4488 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4489 } 4490 4491 synchronized(mWindowMap) { 4492 if (configChanges == 0 && okToDisplay()) { 4493 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token); 4494 return; 4495 } 4496 4497 AppWindowToken wtoken = findAppWindowToken(token); 4498 if (wtoken == null || wtoken.appToken == null) { 4499 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken); 4500 return; 4501 } 4502 final long origId = Binder.clearCallingIdentity(); 4503 startAppFreezingScreenLocked(wtoken); 4504 Binder.restoreCallingIdentity(origId); 4505 } 4506 } 4507 4508 @Override 4509 public void stopAppFreezingScreen(IBinder token, boolean force) { 4510 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4511 "setAppFreezingScreen()")) { 4512 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4513 } 4514 4515 synchronized(mWindowMap) { 4516 AppWindowToken wtoken = findAppWindowToken(token); 4517 if (wtoken == null || wtoken.appToken == null) { 4518 return; 4519 } 4520 final long origId = Binder.clearCallingIdentity(); 4521 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token 4522 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen); 4523 unsetAppFreezingScreenLocked(wtoken, true, force); 4524 Binder.restoreCallingIdentity(origId); 4525 } 4526 } 4527 4528 void removeAppFromTaskLocked(AppWindowToken wtoken) { 4529 final Task task = mTaskIdToTask.get(wtoken.groupId); 4530 if (task != null) { 4531 task.removeAppToken(wtoken); 4532 // Remove after bug resolved. 4533 Slog.d(TAG, "removeAppFromTaskLocked: wtoken=" + wtoken 4534 + " numTokens left=" + task.mAppTokens.size() 4535 + " Callers=" + Debug.getCallers(5)); 4536 } 4537 } 4538 4539 @Override 4540 public void removeAppToken(IBinder token) { 4541 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4542 "removeAppToken()")) { 4543 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4544 } 4545 4546 AppWindowToken wtoken = null; 4547 AppWindowToken startingToken = null; 4548 boolean delayed = false; 4549 4550 final long origId = Binder.clearCallingIdentity(); 4551 synchronized(mWindowMap) { 4552 WindowToken basewtoken = mTokenMap.remove(token); 4553 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) { 4554 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken); 4555 delayed = setTokenVisibilityLocked(wtoken, null, false, 4556 AppTransition.TRANSIT_UNSET, true); 4557 wtoken.inPendingTransaction = false; 4558 mOpeningApps.remove(wtoken); 4559 wtoken.waitingToShow = false; 4560 if (mClosingApps.contains(wtoken)) { 4561 delayed = true; 4562 } else if (mAppTransition.isTransitionSet()) { 4563 mClosingApps.add(wtoken); 4564 wtoken.waitingToHide = true; 4565 delayed = true; 4566 } 4567 if (DEBUG_APP_TRANSITIONS) Slog.v( 4568 TAG, "Removing app " + wtoken + " delayed=" + delayed 4569 + " animation=" + wtoken.mAppAnimator.animation 4570 + " animating=" + wtoken.mAppAnimator.animating); 4571 final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack; 4572 if (delayed) { 4573 // set the token aside because it has an active animation to be finished 4574 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4575 "removeAppToken make exiting: " + wtoken); 4576 stack.mExitingAppTokens.add(wtoken); 4577 wtoken.mDeferRemoval = true; 4578 } else { 4579 // Make sure there is no animation running on this token, 4580 // so any windows associated with it will be removed as 4581 // soon as their animations are complete 4582 wtoken.mAppAnimator.clearAnimation(); 4583 wtoken.mAppAnimator.animating = false; 4584 removeAppFromTaskLocked(wtoken); 4585 } 4586 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4587 "removeAppToken: " + wtoken); 4588 4589 4590 wtoken.removed = true; 4591 if (wtoken.startingData != null) { 4592 startingToken = wtoken; 4593 } 4594 unsetAppFreezingScreenLocked(wtoken, true, true); 4595 if (mFocusedApp == wtoken) { 4596 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Removing focused app token:" + wtoken); 4597 mFocusedApp = null; 4598 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 4599 mInputMonitor.setFocusedAppLw(null); 4600 } 4601 } else { 4602 Slog.w(TAG, "Attempted to remove non-existing app token: " + token); 4603 } 4604 4605 if (!delayed && wtoken != null) { 4606 wtoken.updateReportedVisibilityLocked(); 4607 } 4608 } 4609 Binder.restoreCallingIdentity(origId); 4610 4611 // Will only remove if startingToken non null. 4612 scheduleRemoveStartingWindow(startingToken); 4613 } 4614 4615 void removeStartingWindowTimeout(AppWindowToken wtoken) { 4616 if (wtoken != null) { 4617 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) + 4618 ": Remove starting window timeout " + wtoken + (wtoken != null ? 4619 " startingWindow=" + wtoken.startingWindow : "")); 4620 mH.removeMessages(H.REMOVE_STARTING_TIMEOUT, wtoken); 4621 } 4622 } 4623 4624 void scheduleRemoveStartingWindow(AppWindowToken wtoken) { 4625 if (wtoken != null && wtoken.startingWindow != null) { 4626 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) + 4627 ": Schedule remove starting " + wtoken + (wtoken != null ? 4628 " startingWindow=" + wtoken.startingWindow : "")); 4629 removeStartingWindowTimeout(wtoken); 4630 Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken); 4631 mH.sendMessage(m); 4632 } 4633 } 4634 4635 private boolean tmpRemoveAppWindowsLocked(WindowToken token) { 4636 WindowList windows = token.windows; 4637 final int NW = windows.size(); 4638 if (NW > 0) { 4639 mWindowsChanged = true; 4640 } 4641 for (int i = 0; i < NW; i++) { 4642 WindowState win = windows.get(i); 4643 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win); 4644 win.getWindowList().remove(win); 4645 int j = win.mChildWindows.size(); 4646 while (j > 0) { 4647 j--; 4648 WindowState cwin = win.mChildWindows.get(j); 4649 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 4650 "Tmp removing child window " + cwin); 4651 cwin.getWindowList().remove(cwin); 4652 } 4653 } 4654 return NW > 0; 4655 } 4656 4657 void dumpAppTokensLocked() { 4658 final int numStacks = mStackIdToStack.size(); 4659 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 4660 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 4661 Slog.v(TAG, " Stack #" + stack.mStackId + " tasks from bottom to top:"); 4662 final ArrayList<Task> tasks = stack.getTasks(); 4663 final int numTasks = tasks.size(); 4664 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4665 final Task task = tasks.get(taskNdx); 4666 Slog.v(TAG, " Task #" + task.taskId + " activities from bottom to top:"); 4667 AppTokenList tokens = task.mAppTokens; 4668 final int numTokens = tokens.size(); 4669 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 4670 Slog.v(TAG, " activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token); 4671 } 4672 } 4673 } 4674 } 4675 4676 void dumpWindowsLocked() { 4677 final int numDisplays = mDisplayContents.size(); 4678 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 4679 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 4680 Slog.v(TAG, " Display #" + displayContent.getDisplayId()); 4681 final WindowList windows = displayContent.getWindowList(); 4682 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 4683 Slog.v(TAG, " #" + winNdx + ": " + windows.get(winNdx)); 4684 } 4685 } 4686 } 4687 4688 private int findAppWindowInsertionPointLocked(AppWindowToken target) { 4689 final int taskId = target.groupId; 4690 Task targetTask = mTaskIdToTask.get(taskId); 4691 if (targetTask == null) { 4692 Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId=" 4693 + taskId); 4694 return 0; 4695 } 4696 DisplayContent displayContent = targetTask.getDisplayContent(); 4697 if (displayContent == null) { 4698 Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target); 4699 return 0; 4700 } 4701 final WindowList windows = displayContent.getWindowList(); 4702 final int NW = windows.size(); 4703 4704 boolean found = false; 4705 final ArrayList<Task> tasks = displayContent.getTasks(); 4706 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 4707 final Task task = tasks.get(taskNdx); 4708 if (!found && task.taskId != taskId) { 4709 continue; 4710 } 4711 AppTokenList tokens = task.mAppTokens; 4712 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 4713 final AppWindowToken wtoken = tokens.get(tokenNdx); 4714 if (!found && wtoken == target) { 4715 found = true; 4716 } 4717 if (found) { 4718 // Find the first app token below the new position that has 4719 // a window displayed. 4720 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token); 4721 if (wtoken.sendingToBottom) { 4722 if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom"); 4723 continue; 4724 } 4725 for (int i = wtoken.windows.size() - 1; i >= 0; --i) { 4726 WindowState win = wtoken.windows.get(i); 4727 for (int j = win.mChildWindows.size() - 1; j >= 0; --j) { 4728 WindowState cwin = win.mChildWindows.get(j); 4729 if (cwin.mSubLayer >= 0) { 4730 for (int pos = NW - 1; pos >= 0; pos--) { 4731 if (windows.get(pos) == cwin) { 4732 if (DEBUG_REORDER) Slog.v(TAG, 4733 "Found child win @" + (pos + 1)); 4734 return pos + 1; 4735 } 4736 } 4737 } 4738 } 4739 for (int pos = NW - 1; pos >= 0; pos--) { 4740 if (windows.get(pos) == win) { 4741 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1)); 4742 return pos + 1; 4743 } 4744 } 4745 } 4746 } 4747 } 4748 } 4749 // Never put an app window underneath wallpaper. 4750 for (int pos = NW - 1; pos >= 0; pos--) { 4751 if (windows.get(pos).mIsWallpaper) { 4752 if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos); 4753 return pos + 1; 4754 } 4755 } 4756 return 0; 4757 } 4758 4759 private final int reAddWindowLocked(int index, WindowState win) { 4760 final WindowList windows = win.getWindowList(); 4761 final int NCW = win.mChildWindows.size(); 4762 boolean added = false; 4763 for (int j=0; j<NCW; j++) { 4764 WindowState cwin = win.mChildWindows.get(j); 4765 if (!added && cwin.mSubLayer >= 0) { 4766 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at " 4767 + index + ": " + cwin); 4768 win.mRebuilding = false; 4769 windows.add(index, win); 4770 index++; 4771 added = true; 4772 } 4773 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4774 + index + ": " + cwin); 4775 cwin.mRebuilding = false; 4776 windows.add(index, cwin); 4777 index++; 4778 } 4779 if (!added) { 4780 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4781 + index + ": " + win); 4782 win.mRebuilding = false; 4783 windows.add(index, win); 4784 index++; 4785 } 4786 mWindowsChanged = true; 4787 return index; 4788 } 4789 4790 private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index, 4791 WindowToken token) { 4792 final int NW = token.windows.size(); 4793 for (int i=0; i<NW; i++) { 4794 final WindowState win = token.windows.get(i); 4795 final DisplayContent winDisplayContent = win.getDisplayContent(); 4796 if (winDisplayContent == displayContent || winDisplayContent == null) { 4797 win.mDisplayContent = displayContent; 4798 index = reAddWindowLocked(index, win); 4799 } 4800 } 4801 return index; 4802 } 4803 4804 void tmpRemoveTaskWindowsLocked(Task task) { 4805 AppTokenList tokens = task.mAppTokens; 4806 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 4807 tmpRemoveAppWindowsLocked(tokens.get(tokenNdx)); 4808 } 4809 } 4810 4811 void moveStackWindowsLocked(DisplayContent displayContent) { 4812 // First remove all of the windows from the list. 4813 final ArrayList<Task> tasks = displayContent.getTasks(); 4814 final int numTasks = tasks.size(); 4815 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4816 tmpRemoveTaskWindowsLocked(tasks.get(taskNdx)); 4817 } 4818 4819 // And now add them back at the correct place. 4820 // Where to start adding? 4821 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4822 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 4823 int pos = findAppWindowInsertionPointLocked(tokens.get(0)); 4824 final int numTokens = tokens.size(); 4825 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 4826 final AppWindowToken wtoken = tokens.get(tokenNdx); 4827 if (wtoken != null) { 4828 final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken); 4829 if (newPos != pos) { 4830 displayContent.layoutNeeded = true; 4831 } 4832 pos = newPos; 4833 } 4834 } 4835 } 4836 4837 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4838 false /*updateInputWindows*/)) { 4839 assignLayersLocked(displayContent.getWindowList()); 4840 } 4841 4842 mInputMonitor.setUpdateInputWindowsNeededLw(); 4843 performLayoutAndPlaceSurfacesLocked(); 4844 mInputMonitor.updateInputWindowsLw(false /*force*/); 4845 4846 //dump(); 4847 } 4848 4849 public void moveTaskToTop(int taskId) { 4850 final long origId = Binder.clearCallingIdentity(); 4851 try { 4852 synchronized(mWindowMap) { 4853 Task task = mTaskIdToTask.get(taskId); 4854 if (task == null) { 4855 // Normal behavior, addAppToken will be called next and task will be created. 4856 return; 4857 } 4858 final TaskStack stack = task.mStack; 4859 final DisplayContent displayContent = task.getDisplayContent(); 4860 displayContent.moveStack(stack, true); 4861 if (displayContent.isDefaultDisplay) { 4862 final TaskStack homeStack = displayContent.getHomeStack(); 4863 if (homeStack != stack) { 4864 // When a non-home stack moves to the top, the home stack moves to the 4865 // bottom. 4866 displayContent.moveStack(homeStack, false); 4867 } 4868 } 4869 stack.moveTaskToTop(task); 4870 } 4871 } finally { 4872 Binder.restoreCallingIdentity(origId); 4873 } 4874 } 4875 4876 public void moveTaskToBottom(int taskId) { 4877 final long origId = Binder.clearCallingIdentity(); 4878 try { 4879 synchronized(mWindowMap) { 4880 Task task = mTaskIdToTask.get(taskId); 4881 if (task == null) { 4882 Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId 4883 + " not found in mTaskIdToTask"); 4884 return; 4885 } 4886 final TaskStack stack = task.mStack; 4887 stack.moveTaskToBottom(task); 4888 moveStackWindowsLocked(stack.getDisplayContent()); 4889 } 4890 } finally { 4891 Binder.restoreCallingIdentity(origId); 4892 } 4893 } 4894 4895 /** 4896 * Create a new TaskStack and place it on a DisplayContent. 4897 * @param stackId The unique identifier of the new stack. 4898 * @param displayId The unique identifier of the DisplayContent. 4899 */ 4900 public void attachStack(int stackId, int displayId) { 4901 final long origId = Binder.clearCallingIdentity(); 4902 try { 4903 synchronized (mWindowMap) { 4904 final DisplayContent displayContent = mDisplayContents.get(displayId); 4905 if (displayContent != null) { 4906 TaskStack stack = mStackIdToStack.get(stackId); 4907 if (stack == null) { 4908 if (DEBUG_STACK) Slog.d(TAG, "attachStack: stackId=" + stackId); 4909 stack = new TaskStack(this, stackId); 4910 mStackIdToStack.put(stackId, stack); 4911 } 4912 stack.attachDisplayContent(displayContent); 4913 displayContent.attachStack(stack); 4914 moveStackWindowsLocked(displayContent); 4915 final WindowList windows = displayContent.getWindowList(); 4916 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 4917 windows.get(winNdx).reportResized(); 4918 } 4919 } 4920 } 4921 } finally { 4922 Binder.restoreCallingIdentity(origId); 4923 } 4924 } 4925 4926 public void detachStack(int stackId) { 4927 synchronized (mWindowMap) { 4928 TaskStack stack = mStackIdToStack.get(stackId); 4929 if (stack != null) { 4930 final DisplayContent displayContent = stack.getDisplayContent(); 4931 if (displayContent != null) { 4932 if (stack.isAnimating()) { 4933 displayContent.mDeferredActions |= DisplayContent.DEFER_DETACH; 4934 return; 4935 } 4936 displayContent.detachStack(stack); 4937 stack.detachDisplay(); 4938 } 4939 } 4940 } 4941 } 4942 4943 void removeTaskLocked(Task task) { 4944 final int taskId = task.taskId; 4945 final TaskStack stack = task.mStack; 4946 if (stack.isAnimating()) { 4947 if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId); 4948 task.mDeferRemoval = true; 4949 return; 4950 } 4951 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId); 4952 EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask"); 4953 task.mDeferRemoval = false; 4954 task.mStack.removeTask(task); 4955 mTaskIdToTask.delete(task.taskId); 4956 } 4957 4958 public void removeTask(int taskId) { 4959 synchronized (mWindowMap) { 4960 Task task = mTaskIdToTask.get(taskId); 4961 if (task == null) { 4962 if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId); 4963 return; 4964 } 4965 removeTaskLocked(task); 4966 } 4967 } 4968 4969 public void addTask(int taskId, int stackId, boolean toTop) { 4970 synchronized (mWindowMap) { 4971 if (DEBUG_STACK) Slog.i(TAG, "addTask: adding taskId=" + taskId 4972 + " to " + (toTop ? "top" : "bottom")); 4973 Task task = mTaskIdToTask.get(taskId); 4974 if (task == null) { 4975 return; 4976 } 4977 TaskStack stack = mStackIdToStack.get(stackId); 4978 stack.addTask(task, toTop); 4979 final DisplayContent displayContent = stack.getDisplayContent(); 4980 displayContent.layoutNeeded = true; 4981 performLayoutAndPlaceSurfacesLocked(); 4982 } 4983 } 4984 4985 public void resizeStack(int stackId, Rect bounds) { 4986 synchronized (mWindowMap) { 4987 final TaskStack stack = mStackIdToStack.get(stackId); 4988 if (stack == null) { 4989 throw new IllegalArgumentException("resizeStack: stackId " + stackId 4990 + " not found."); 4991 } 4992 if (stack.setBounds(bounds)) { 4993 stack.getDisplayContent().layoutNeeded = true; 4994 performLayoutAndPlaceSurfacesLocked(); 4995 } 4996 } 4997 } 4998 4999 public void getStackBounds(int stackId, Rect bounds) { 5000 final TaskStack stack = mStackIdToStack.get(stackId); 5001 if (stack != null) { 5002 stack.getBounds(bounds); 5003 return; 5004 } 5005 bounds.setEmpty(); 5006 } 5007 5008 // ------------------------------------------------------------- 5009 // Misc IWindowSession methods 5010 // ------------------------------------------------------------- 5011 5012 @Override 5013 public void startFreezingScreen(int exitAnim, int enterAnim) { 5014 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5015 "startFreezingScreen()")) { 5016 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5017 } 5018 5019 synchronized(mWindowMap) { 5020 if (!mClientFreezingScreen) { 5021 mClientFreezingScreen = true; 5022 final long origId = Binder.clearCallingIdentity(); 5023 try { 5024 startFreezingDisplayLocked(false, exitAnim, enterAnim); 5025 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 5026 mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000); 5027 } finally { 5028 Binder.restoreCallingIdentity(origId); 5029 } 5030 } 5031 } 5032 } 5033 5034 @Override 5035 public void stopFreezingScreen() { 5036 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5037 "stopFreezingScreen()")) { 5038 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5039 } 5040 5041 synchronized(mWindowMap) { 5042 if (mClientFreezingScreen) { 5043 mClientFreezingScreen = false; 5044 mLastFinishedFreezeSource = "client"; 5045 final long origId = Binder.clearCallingIdentity(); 5046 try { 5047 stopFreezingDisplayLocked(); 5048 } finally { 5049 Binder.restoreCallingIdentity(origId); 5050 } 5051 } 5052 } 5053 } 5054 5055 @Override 5056 public void disableKeyguard(IBinder token, String tag) { 5057 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5058 != PackageManager.PERMISSION_GRANTED) { 5059 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5060 } 5061 5062 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5063 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag))); 5064 } 5065 5066 @Override 5067 public void reenableKeyguard(IBinder token) { 5068 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5069 != PackageManager.PERMISSION_GRANTED) { 5070 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5071 } 5072 5073 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5074 KeyguardDisableHandler.KEYGUARD_REENABLE, token)); 5075 } 5076 5077 /** 5078 * @see android.app.KeyguardManager#exitKeyguardSecurely 5079 */ 5080 @Override 5081 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) { 5082 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5083 != PackageManager.PERMISSION_GRANTED) { 5084 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5085 } 5086 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() { 5087 @Override 5088 public void onKeyguardExitResult(boolean success) { 5089 try { 5090 callback.onKeyguardExitResult(success); 5091 } catch (RemoteException e) { 5092 // Client has died, we don't care. 5093 } 5094 } 5095 }); 5096 } 5097 5098 @Override 5099 public boolean inKeyguardRestrictedInputMode() { 5100 return mPolicy.inKeyguardRestrictedKeyInputMode(); 5101 } 5102 5103 @Override 5104 public boolean isKeyguardLocked() { 5105 return mPolicy.isKeyguardLocked(); 5106 } 5107 5108 @Override 5109 public boolean isKeyguardSecure() { 5110 return mPolicy.isKeyguardSecure(); 5111 } 5112 5113 @Override 5114 public void dismissKeyguard() { 5115 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5116 != PackageManager.PERMISSION_GRANTED) { 5117 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5118 } 5119 synchronized(mWindowMap) { 5120 mPolicy.dismissKeyguardLw(); 5121 } 5122 } 5123 5124 @Override 5125 public void closeSystemDialogs(String reason) { 5126 synchronized(mWindowMap) { 5127 final int numDisplays = mDisplayContents.size(); 5128 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5129 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5130 final int numWindows = windows.size(); 5131 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5132 final WindowState w = windows.get(winNdx); 5133 if (w.mHasSurface) { 5134 try { 5135 w.mClient.closeSystemDialogs(reason); 5136 } catch (RemoteException e) { 5137 } 5138 } 5139 } 5140 } 5141 } 5142 } 5143 5144 static float fixScale(float scale) { 5145 if (scale < 0) scale = 0; 5146 else if (scale > 20) scale = 20; 5147 return Math.abs(scale); 5148 } 5149 5150 @Override 5151 public void setAnimationScale(int which, float scale) { 5152 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5153 "setAnimationScale()")) { 5154 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5155 } 5156 5157 scale = fixScale(scale); 5158 switch (which) { 5159 case 0: mWindowAnimationScale = scale; break; 5160 case 1: mTransitionAnimationScale = scale; break; 5161 case 2: mAnimatorDurationScale = scale; break; 5162 } 5163 5164 // Persist setting 5165 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5166 } 5167 5168 @Override 5169 public void setAnimationScales(float[] scales) { 5170 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5171 "setAnimationScale()")) { 5172 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5173 } 5174 5175 if (scales != null) { 5176 if (scales.length >= 1) { 5177 mWindowAnimationScale = fixScale(scales[0]); 5178 } 5179 if (scales.length >= 2) { 5180 mTransitionAnimationScale = fixScale(scales[1]); 5181 } 5182 if (scales.length >= 3) { 5183 setAnimatorDurationScale(fixScale(scales[2])); 5184 } 5185 } 5186 5187 // Persist setting 5188 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5189 } 5190 5191 private void setAnimatorDurationScale(float scale) { 5192 mAnimatorDurationScale = scale; 5193 ValueAnimator.setDurationScale(scale); 5194 } 5195 5196 @Override 5197 public float getAnimationScale(int which) { 5198 switch (which) { 5199 case 0: return mWindowAnimationScale; 5200 case 1: return mTransitionAnimationScale; 5201 case 2: return mAnimatorDurationScale; 5202 } 5203 return 0; 5204 } 5205 5206 @Override 5207 public float[] getAnimationScales() { 5208 return new float[] { mWindowAnimationScale, mTransitionAnimationScale, 5209 mAnimatorDurationScale }; 5210 } 5211 5212 @Override 5213 public void registerPointerEventListener(PointerEventListener listener) { 5214 mPointerEventDispatcher.registerInputEventListener(listener); 5215 } 5216 5217 @Override 5218 public void unregisterPointerEventListener(PointerEventListener listener) { 5219 mPointerEventDispatcher.unregisterInputEventListener(listener); 5220 } 5221 5222 // Called by window manager policy. Not exposed externally. 5223 @Override 5224 public int getLidState() { 5225 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 5226 InputManagerService.SW_LID); 5227 if (sw > 0) { 5228 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 5229 return LID_CLOSED; 5230 } else if (sw == 0) { 5231 // Switch state: AKEY_STATE_UP. 5232 return LID_OPEN; 5233 } else { 5234 // Switch state: AKEY_STATE_UNKNOWN. 5235 return LID_ABSENT; 5236 } 5237 } 5238 5239 // Called by window manager policy. Not exposed externally. 5240 @Override 5241 public void switchKeyboardLayout(int deviceId, int direction) { 5242 mInputManager.switchKeyboardLayout(deviceId, direction); 5243 } 5244 5245 // Called by window manager policy. Not exposed externally. 5246 @Override 5247 public void shutdown(boolean confirm) { 5248 ShutdownThread.shutdown(mContext, confirm); 5249 } 5250 5251 // Called by window manager policy. Not exposed externally. 5252 @Override 5253 public void rebootSafeMode(boolean confirm) { 5254 ShutdownThread.rebootSafeMode(mContext, confirm); 5255 } 5256 5257 @Override 5258 public void setInputFilter(IInputFilter filter) { 5259 if (!checkCallingPermission(android.Manifest.permission.FILTER_EVENTS, "setInputFilter()")) { 5260 throw new SecurityException("Requires FILTER_EVENTS permission"); 5261 } 5262 mInputManager.setInputFilter(filter); 5263 } 5264 5265 @Override 5266 public void setTouchExplorationEnabled(boolean enabled) { 5267 mPolicy.setTouchExplorationEnabled(enabled); 5268 } 5269 5270 public void setCurrentUser(final int newUserId) { 5271 synchronized (mWindowMap) { 5272 int oldUserId = mCurrentUserId; 5273 mCurrentUserId = newUserId; 5274 mAppTransition.setCurrentUser(newUserId); 5275 mPolicy.setCurrentUserLw(newUserId); 5276 5277 // Hide windows that should not be seen by the new user. 5278 final int numDisplays = mDisplayContents.size(); 5279 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5280 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 5281 displayContent.switchUserStacks(newUserId); 5282 rebuildAppWindowListLocked(displayContent); 5283 } 5284 performLayoutAndPlaceSurfacesLocked(); 5285 } 5286 } 5287 5288 public void enableScreenAfterBoot() { 5289 synchronized(mWindowMap) { 5290 if (DEBUG_BOOT) { 5291 RuntimeException here = new RuntimeException("here"); 5292 here.fillInStackTrace(); 5293 Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled 5294 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5295 + " mShowingBootMessages=" + mShowingBootMessages 5296 + " mSystemBooted=" + mSystemBooted, here); 5297 } 5298 if (mSystemBooted) { 5299 return; 5300 } 5301 mSystemBooted = true; 5302 hideBootMessagesLocked(); 5303 // If the screen still doesn't come up after 30 seconds, give 5304 // up and turn it on. 5305 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000); 5306 } 5307 5308 mPolicy.systemBooted(); 5309 5310 performEnableScreen(); 5311 } 5312 5313 void enableScreenIfNeededLocked() { 5314 if (DEBUG_BOOT) { 5315 RuntimeException here = new RuntimeException("here"); 5316 here.fillInStackTrace(); 5317 Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled 5318 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5319 + " mShowingBootMessages=" + mShowingBootMessages 5320 + " mSystemBooted=" + mSystemBooted, here); 5321 } 5322 if (mDisplayEnabled) { 5323 return; 5324 } 5325 if (!mSystemBooted && !mShowingBootMessages) { 5326 return; 5327 } 5328 mH.sendEmptyMessage(H.ENABLE_SCREEN); 5329 } 5330 5331 public void performBootTimeout() { 5332 synchronized(mWindowMap) { 5333 if (mDisplayEnabled) { 5334 return; 5335 } 5336 Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled"); 5337 mForceDisplayEnabled = true; 5338 } 5339 performEnableScreen(); 5340 } 5341 5342 public void performEnableScreen() { 5343 synchronized(mWindowMap) { 5344 if (DEBUG_BOOT) { 5345 RuntimeException here = new RuntimeException("here"); 5346 here.fillInStackTrace(); 5347 Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled 5348 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5349 + " mShowingBootMessages=" + mShowingBootMessages 5350 + " mSystemBooted=" + mSystemBooted 5351 + " mOnlyCore=" + mOnlyCore, here); 5352 } 5353 if (mDisplayEnabled) { 5354 return; 5355 } 5356 if (!mSystemBooted && !mShowingBootMessages) { 5357 return; 5358 } 5359 5360 if (!mForceDisplayEnabled) { 5361 // Don't enable the screen until all existing windows 5362 // have been drawn. 5363 boolean haveBootMsg = false; 5364 boolean haveApp = false; 5365 // if the wallpaper service is disabled on the device, we're never going to have 5366 // wallpaper, don't bother waiting for it 5367 boolean haveWallpaper = false; 5368 boolean wallpaperEnabled = mContext.getResources().getBoolean( 5369 com.android.internal.R.bool.config_enableWallpaperService) 5370 && !mOnlyCore; 5371 boolean haveKeyguard = true; 5372 // TODO(multidisplay): Expand to all displays? 5373 final WindowList windows = getDefaultWindowListLocked(); 5374 final int N = windows.size(); 5375 for (int i=0; i<N; i++) { 5376 WindowState w = windows.get(i); 5377 if (w.mAttrs.type == TYPE_KEYGUARD) { 5378 // Only if there is a keyguard attached to the window manager 5379 // will we consider ourselves as having a keyguard. If it 5380 // isn't attached, we don't know if it wants to be shown or 5381 // hidden. If it is attached, we will say we have a keyguard 5382 // if the window doesn't want to be visible, because in that 5383 // case it explicitly doesn't want to be shown so we should 5384 // not delay turning the screen on for it. 5385 boolean vis = w.mViewVisibility == View.VISIBLE 5386 && w.mPolicyVisibility; 5387 haveKeyguard = !vis; 5388 } 5389 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 5390 return; 5391 } 5392 if (w.isDrawnLw()) { 5393 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { 5394 haveBootMsg = true; 5395 } else if (w.mAttrs.type == TYPE_APPLICATION) { 5396 haveApp = true; 5397 } else if (w.mAttrs.type == TYPE_WALLPAPER) { 5398 haveWallpaper = true; 5399 } else if (w.mAttrs.type == TYPE_KEYGUARD) { 5400 haveKeyguard = true; 5401 } 5402 } 5403 } 5404 5405 if (DEBUG_SCREEN_ON || DEBUG_BOOT) { 5406 Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages 5407 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp 5408 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled 5409 + " haveKeyguard=" + haveKeyguard); 5410 } 5411 5412 // If we are turning on the screen to show the boot message, 5413 // don't do it until the boot message is actually displayed. 5414 if (!mSystemBooted && !haveBootMsg) { 5415 return; 5416 } 5417 5418 // If we are turning on the screen after the boot is completed 5419 // normally, don't do so until we have the application and 5420 // wallpaper. 5421 if (mSystemBooted && ((!haveApp && !haveKeyguard) || 5422 (wallpaperEnabled && !haveWallpaper))) { 5423 return; 5424 } 5425 } 5426 5427 mDisplayEnabled = true; 5428 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!"); 5429 if (false) { 5430 StringWriter sw = new StringWriter(); 5431 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 5432 this.dump(null, pw, null); 5433 pw.flush(); 5434 Slog.i(TAG, sw.toString()); 5435 } 5436 try { 5437 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); 5438 if (surfaceFlinger != null) { 5439 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); 5440 Parcel data = Parcel.obtain(); 5441 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 5442 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED 5443 data, null, 0); 5444 data.recycle(); 5445 } 5446 } catch (RemoteException ex) { 5447 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); 5448 } 5449 5450 // Enable input dispatch. 5451 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled); 5452 } 5453 5454 mPolicy.enableScreenAfterBoot(); 5455 5456 // Make sure the last requested orientation has been applied. 5457 updateRotationUnchecked(false, false); 5458 } 5459 5460 public void showBootMessage(final CharSequence msg, final boolean always) { 5461 boolean first = false; 5462 synchronized(mWindowMap) { 5463 if (DEBUG_BOOT) { 5464 RuntimeException here = new RuntimeException("here"); 5465 here.fillInStackTrace(); 5466 Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always 5467 + " mAllowBootMessages=" + mAllowBootMessages 5468 + " mShowingBootMessages=" + mShowingBootMessages 5469 + " mSystemBooted=" + mSystemBooted, here); 5470 } 5471 if (!mAllowBootMessages) { 5472 return; 5473 } 5474 if (!mShowingBootMessages) { 5475 if (!always) { 5476 return; 5477 } 5478 first = true; 5479 } 5480 if (mSystemBooted) { 5481 return; 5482 } 5483 mShowingBootMessages = true; 5484 mPolicy.showBootMessage(msg, always); 5485 } 5486 if (first) { 5487 performEnableScreen(); 5488 } 5489 } 5490 5491 public void hideBootMessagesLocked() { 5492 if (DEBUG_BOOT) { 5493 RuntimeException here = new RuntimeException("here"); 5494 here.fillInStackTrace(); 5495 Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled 5496 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5497 + " mShowingBootMessages=" + mShowingBootMessages 5498 + " mSystemBooted=" + mSystemBooted, here); 5499 } 5500 if (mShowingBootMessages) { 5501 mShowingBootMessages = false; 5502 mPolicy.hideBootMessages(); 5503 } 5504 } 5505 5506 @Override 5507 public void setInTouchMode(boolean mode) { 5508 synchronized(mWindowMap) { 5509 mInTouchMode = mode; 5510 } 5511 } 5512 5513 // TODO: more accounting of which pid(s) turned it on, keep count, 5514 // only allow disables from pids which have count on, etc. 5515 @Override 5516 public void showStrictModeViolation(boolean on) { 5517 int pid = Binder.getCallingPid(); 5518 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid)); 5519 } 5520 5521 private void showStrictModeViolation(int arg, int pid) { 5522 final boolean on = arg != 0; 5523 synchronized(mWindowMap) { 5524 // Ignoring requests to enable the red border from clients 5525 // which aren't on screen. (e.g. Broadcast Receivers in 5526 // the background..) 5527 if (on) { 5528 boolean isVisible = false; 5529 final int numDisplays = mDisplayContents.size(); 5530 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5531 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5532 final int numWindows = windows.size(); 5533 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5534 final WindowState ws = windows.get(winNdx); 5535 if (ws.mSession.mPid == pid && ws.isVisibleLw()) { 5536 isVisible = true; 5537 break; 5538 } 5539 } 5540 } 5541 if (!isVisible) { 5542 return; 5543 } 5544 } 5545 5546 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5547 ">>> OPEN TRANSACTION showStrictModeViolation"); 5548 SurfaceControl.openTransaction(); 5549 try { 5550 // TODO(multi-display): support multiple displays 5551 if (mStrictModeFlash == null) { 5552 mStrictModeFlash = new StrictModeFlash( 5553 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 5554 } 5555 mStrictModeFlash.setVisibility(on); 5556 } finally { 5557 SurfaceControl.closeTransaction(); 5558 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5559 "<<< CLOSE TRANSACTION showStrictModeViolation"); 5560 } 5561 } 5562 } 5563 5564 @Override 5565 public void setStrictModeVisualIndicatorPreference(String value) { 5566 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 5567 } 5568 5569 /** 5570 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 5571 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 5572 * of the target image. 5573 * 5574 * @param displayId the Display to take a screenshot of. 5575 * @param width the width of the target bitmap 5576 * @param height the height of the target bitmap 5577 * @param force565 if true the returned bitmap will be RGB_565, otherwise it 5578 * will be the same config as the surface 5579 */ 5580 @Override 5581 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, 5582 int height, boolean force565) { 5583 if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, 5584 "screenshotApplications()")) { 5585 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 5586 } 5587 5588 Bitmap rawss = null; 5589 5590 int maxLayer = 0; 5591 final Rect frame = new Rect(); 5592 5593 float scale = 0; 5594 int dw, dh; 5595 int rot = Surface.ROTATION_0; 5596 5597 boolean screenshotReady; 5598 int minLayer; 5599 if (appToken == null) { 5600 screenshotReady = true; 5601 minLayer = 0; 5602 } else { 5603 screenshotReady = false; 5604 minLayer = Integer.MAX_VALUE; 5605 } 5606 5607 int retryCount = 0; 5608 WindowState appWin = null; 5609 5610 do { 5611 if (retryCount++ > 0) { 5612 try { 5613 Thread.sleep(100); 5614 } catch (InterruptedException e) { 5615 } 5616 } 5617 synchronized(mWindowMap) { 5618 final DisplayContent displayContent = getDisplayContentLocked(displayId); 5619 if (displayContent == null) { 5620 return null; 5621 } 5622 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 5623 dw = displayInfo.logicalWidth; 5624 dh = displayInfo.logicalHeight; 5625 5626 int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) 5627 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 5628 aboveAppLayer += TYPE_LAYER_MULTIPLIER; 5629 5630 boolean isImeTarget = mInputMethodTarget != null 5631 && mInputMethodTarget.mAppToken != null 5632 && mInputMethodTarget.mAppToken.appToken != null 5633 && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken; 5634 5635 // Figure out the part of the screen that is actually the app. 5636 boolean including = false; 5637 appWin = null; 5638 final WindowList windows = displayContent.getWindowList(); 5639 final Rect stackBounds = new Rect(); 5640 for (int i = windows.size() - 1; i >= 0; i--) { 5641 WindowState ws = windows.get(i); 5642 if (!ws.mHasSurface) { 5643 continue; 5644 } 5645 if (ws.mLayer >= aboveAppLayer) { 5646 continue; 5647 } 5648 // When we will skip windows: when we are not including 5649 // ones behind a window we didn't skip, and we are actually 5650 // taking a screenshot of a specific app. 5651 if (!including && appToken != null) { 5652 // Also, we can possibly skip this window if it is not 5653 // an IME target or the application for the screenshot 5654 // is not the current IME target. 5655 if (!ws.mIsImWindow || !isImeTarget) { 5656 // And finally, this window is of no interest if it 5657 // is not associated with the screenshot app. 5658 if (ws.mAppToken == null || ws.mAppToken.token != appToken) { 5659 continue; 5660 } 5661 appWin = ws; 5662 ws.getStackBounds(stackBounds); 5663 } 5664 } 5665 5666 // We keep on including windows until we go past a full-screen 5667 // window. 5668 including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh); 5669 5670 final WindowStateAnimator winAnim = ws.mWinAnimator; 5671 if (maxLayer < winAnim.mSurfaceLayer) { 5672 maxLayer = winAnim.mSurfaceLayer; 5673 } 5674 if (minLayer > winAnim.mSurfaceLayer) { 5675 minLayer = winAnim.mSurfaceLayer; 5676 } 5677 5678 // Don't include wallpaper in bounds calculation 5679 if (!ws.mIsWallpaper) { 5680 final Rect wf = ws.mFrame; 5681 final Rect cr = ws.mContentInsets; 5682 int left = wf.left + cr.left; 5683 int top = wf.top + cr.top; 5684 int right = wf.right - cr.right; 5685 int bottom = wf.bottom - cr.bottom; 5686 frame.union(left, top, right, bottom); 5687 frame.intersect(stackBounds); 5688 } 5689 5690 if (ws.mAppToken != null && ws.mAppToken.token == appToken && 5691 ws.isDisplayedLw()) { 5692 screenshotReady = true; 5693 } 5694 } 5695 5696 if (appToken != null && appWin == null) { 5697 // Can't find a window to snapshot. 5698 if (DEBUG_SCREENSHOT) Slog.i(TAG, 5699 "Screenshot: Couldn't find a surface matching " + appToken); 5700 return null; 5701 } 5702 if (!screenshotReady) { 5703 // Delay and hope that window gets drawn. 5704 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken 5705 + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState); 5706 continue; 5707 } 5708 5709 // Constrain frame to the screen size. 5710 frame.intersect(0, 0, dw, dh); 5711 5712 if (frame.isEmpty() || maxLayer == 0) { 5713 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 5714 + ": returning null frame=" + frame.toShortString() + " maxLayer=" 5715 + maxLayer); 5716 return null; 5717 } 5718 5719 // The screenshot API does not apply the current screen rotation. 5720 rot = getDefaultDisplayContentLocked().getDisplay().getRotation(); 5721 int fw = frame.width(); 5722 int fh = frame.height(); 5723 5724 // Constrain thumbnail to smaller of screen width or height. Assumes aspect 5725 // of thumbnail is the same as the screen (in landscape) or square. 5726 scale = Math.max(width / (float) fw, height / (float) fh); 5727 /* 5728 float targetWidthScale = width / (float) fw; 5729 float targetHeightScale = height / (float) fh; 5730 if (fw <= fh) { 5731 scale = targetWidthScale; 5732 // If aspect of thumbnail is the same as the screen (in landscape), 5733 // select the slightly larger value so we fill the entire bitmap 5734 if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) { 5735 scale = targetHeightScale; 5736 } 5737 } else { 5738 scale = targetHeightScale; 5739 // If aspect of thumbnail is the same as the screen (in landscape), 5740 // select the slightly larger value so we fill the entire bitmap 5741 if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) { 5742 scale = targetWidthScale; 5743 } 5744 } 5745 */ 5746 5747 // The screen shot will contain the entire screen. 5748 dw = (int)(dw*scale); 5749 dh = (int)(dh*scale); 5750 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 5751 int tmp = dw; 5752 dw = dh; 5753 dh = tmp; 5754 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; 5755 } 5756 if (DEBUG_SCREENSHOT) { 5757 Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 5758 + maxLayer + " appToken=" + appToken); 5759 for (int i = 0; i < windows.size(); i++) { 5760 WindowState win = windows.get(i); 5761 Slog.i(TAG, win + ": " + win.mLayer 5762 + " animLayer=" + win.mWinAnimator.mAnimLayer 5763 + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer); 5764 } 5765 } 5766 rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer); 5767 } 5768 } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES); 5769 if (retryCount > MAX_SCREENSHOT_RETRIES) Slog.i(TAG, "Screenshot max retries " + 5770 retryCount + " of " + appToken + " appWin=" + (appWin == null ? 5771 "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState))); 5772 5773 if (rawss == null) { 5774 Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh 5775 + ") to layer " + maxLayer); 5776 return null; 5777 } 5778 5779 Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig()); 5780 frame.scale(scale); 5781 Matrix matrix = new Matrix(); 5782 ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix); 5783 // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left 5784 matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top)); 5785 Canvas canvas = new Canvas(bm); 5786 canvas.drawColor(0xFF000000); 5787 canvas.drawBitmap(rawss, matrix, null); 5788 canvas.setBitmap(null); 5789 5790 if (DEBUG_SCREENSHOT) { 5791 // TEST IF IT's ALL BLACK 5792 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 5793 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 5794 boolean allBlack = true; 5795 final int firstColor = buffer[0]; 5796 for (int i = 0; i < buffer.length; i++) { 5797 if (buffer[i] != firstColor) { 5798 allBlack = false; 5799 break; 5800 } 5801 } 5802 if (allBlack) { 5803 Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" + 5804 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 5805 (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") + 5806 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 5807 } 5808 } 5809 5810 rawss.recycle(); 5811 return bm; 5812 } 5813 5814 /** 5815 * Freeze rotation changes. (Enable "rotation lock".) 5816 * Persists across reboots. 5817 * @param rotation The desired rotation to freeze to, or -1 to use the 5818 * current rotation. 5819 */ 5820 @Override 5821 public void freezeRotation(int rotation) { 5822 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5823 "freezeRotation()")) { 5824 throw new SecurityException("Requires SET_ORIENTATION permission"); 5825 } 5826 if (rotation < -1 || rotation > Surface.ROTATION_270) { 5827 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 5828 + "rotation constant."); 5829 } 5830 5831 if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); 5832 5833 long origId = Binder.clearCallingIdentity(); 5834 try { 5835 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, 5836 rotation == -1 ? mRotation : rotation); 5837 } finally { 5838 Binder.restoreCallingIdentity(origId); 5839 } 5840 5841 updateRotationUnchecked(false, false); 5842 } 5843 5844 /** 5845 * Thaw rotation changes. (Disable "rotation lock".) 5846 * Persists across reboots. 5847 */ 5848 @Override 5849 public void thawRotation() { 5850 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5851 "thawRotation()")) { 5852 throw new SecurityException("Requires SET_ORIENTATION permission"); 5853 } 5854 5855 if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); 5856 5857 long origId = Binder.clearCallingIdentity(); 5858 try { 5859 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 5860 777); // rot not used 5861 } finally { 5862 Binder.restoreCallingIdentity(origId); 5863 } 5864 5865 updateRotationUnchecked(false, false); 5866 } 5867 5868 /** 5869 * Recalculate the current rotation. 5870 * 5871 * Called by the window manager policy whenever the state of the system changes 5872 * such that the current rotation might need to be updated, such as when the 5873 * device is docked or rotated into a new posture. 5874 */ 5875 @Override 5876 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 5877 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 5878 } 5879 5880 /** 5881 * Temporarily pauses rotation changes until resumed. 5882 * 5883 * This can be used to prevent rotation changes from occurring while the user is 5884 * performing certain operations, such as drag and drop. 5885 * 5886 * This call nests and must be matched by an equal number of calls to 5887 * {@link #resumeRotationLocked}. 5888 */ 5889 void pauseRotationLocked() { 5890 mDeferredRotationPauseCount += 1; 5891 } 5892 5893 /** 5894 * Resumes normal rotation changes after being paused. 5895 */ 5896 void resumeRotationLocked() { 5897 if (mDeferredRotationPauseCount > 0) { 5898 mDeferredRotationPauseCount -= 1; 5899 if (mDeferredRotationPauseCount == 0) { 5900 boolean changed = updateRotationUncheckedLocked(false); 5901 if (changed) { 5902 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 5903 } 5904 } 5905 } 5906 } 5907 5908 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 5909 if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" 5910 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); 5911 5912 long origId = Binder.clearCallingIdentity(); 5913 boolean changed; 5914 synchronized(mWindowMap) { 5915 changed = updateRotationUncheckedLocked(false); 5916 if (!changed || forceRelayout) { 5917 getDefaultDisplayContentLocked().layoutNeeded = true; 5918 performLayoutAndPlaceSurfacesLocked(); 5919 } 5920 } 5921 5922 if (changed || alwaysSendConfiguration) { 5923 sendNewConfiguration(); 5924 } 5925 5926 Binder.restoreCallingIdentity(origId); 5927 } 5928 5929 // TODO(multidisplay): Rotate any display? 5930 /** 5931 * Updates the current rotation. 5932 * 5933 * Returns true if the rotation has been changed. In this case YOU 5934 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. 5935 */ 5936 public boolean updateRotationUncheckedLocked(boolean inTransaction) { 5937 if (mDeferredRotationPauseCount > 0) { 5938 // Rotation updates have been paused temporarily. Defer the update until 5939 // updates have been resumed. 5940 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused."); 5941 return false; 5942 } 5943 5944 ScreenRotationAnimation screenRotationAnimation = 5945 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 5946 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 5947 // Rotation updates cannot be performed while the previous rotation change 5948 // animation is still in progress. Skip this update. We will try updating 5949 // again after the animation is finished and the display is unfrozen. 5950 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress."); 5951 return false; 5952 } 5953 5954 if (!mDisplayEnabled) { 5955 // No point choosing a rotation if the display is not enabled. 5956 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled."); 5957 return false; 5958 } 5959 5960 // TODO: Implement forced rotation changes. 5961 // Set mAltOrientation to indicate that the application is receiving 5962 // an orientation that has different metrics than it expected. 5963 // eg. Portrait instead of Landscape. 5964 5965 int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation); 5966 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 5967 mForcedAppOrientation, rotation); 5968 5969 if (DEBUG_ORIENTATION) { 5970 Slog.v(TAG, "Application requested orientation " 5971 + mForcedAppOrientation + ", got rotation " + rotation 5972 + " which has " + (altOrientation ? "incompatible" : "compatible") 5973 + " metrics"); 5974 } 5975 5976 if (mRotation == rotation && mAltOrientation == altOrientation) { 5977 // No change. 5978 return false; 5979 } 5980 5981 if (DEBUG_ORIENTATION) { 5982 Slog.v(TAG, 5983 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") 5984 + " from " + mRotation + (mAltOrientation ? " (alt)" : "") 5985 + ", forceApp=" + mForcedAppOrientation); 5986 } 5987 5988 mRotation = rotation; 5989 mAltOrientation = altOrientation; 5990 mPolicy.setRotationLw(mRotation); 5991 5992 mWindowsFreezingScreen = true; 5993 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 5994 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION); 5995 mWaitingForConfig = true; 5996 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 5997 displayContent.layoutNeeded = true; 5998 final int[] anim = new int[2]; 5999 if (displayContent.isDimming()) { 6000 anim[0] = anim[1] = 0; 6001 } else { 6002 mPolicy.selectRotationAnimationLw(anim); 6003 } 6004 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]); 6005 // startFreezingDisplayLocked can reset the ScreenRotationAnimation. 6006 screenRotationAnimation = 6007 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6008 6009 // We need to update our screen size information to match the new 6010 // rotation. Note that this is redundant with the later call to 6011 // sendNewConfiguration() that must be called after this function 6012 // returns... however we need to do the screen size part of that 6013 // before then so we have the correct size to use when initializing 6014 // the rotation animation for the new rotation. 6015 computeScreenConfigurationLocked(null); 6016 6017 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6018 if (!inTransaction) { 6019 if (SHOW_TRANSACTIONS) { 6020 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked"); 6021 } 6022 SurfaceControl.openTransaction(); 6023 } 6024 try { 6025 // NOTE: We disable the rotation in the emulator because 6026 // it doesn't support hardware OpenGL emulation yet. 6027 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 6028 && screenRotationAnimation.hasScreenshot()) { 6029 if (screenRotationAnimation.setRotationInTransaction( 6030 rotation, mFxSession, 6031 MAX_ANIMATION_DURATION, mTransitionAnimationScale, 6032 displayInfo.logicalWidth, displayInfo.logicalHeight)) { 6033 scheduleAnimationLocked(); 6034 } 6035 } 6036 6037 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 6038 } finally { 6039 if (!inTransaction) { 6040 SurfaceControl.closeTransaction(); 6041 if (SHOW_LIGHT_TRANSACTIONS) { 6042 Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked"); 6043 } 6044 } 6045 } 6046 6047 final WindowList windows = displayContent.getWindowList(); 6048 for (int i = windows.size() - 1; i >= 0; i--) { 6049 WindowState w = windows.get(i); 6050 if (w.mHasSurface) { 6051 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w); 6052 w.mOrientationChanging = true; 6053 mInnerFields.mOrientationChangeComplete = false; 6054 } 6055 w.mLastFreezeDuration = 0; 6056 } 6057 6058 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 6059 try { 6060 mRotationWatchers.get(i).onRotationChanged(rotation); 6061 } catch (RemoteException e) { 6062 } 6063 } 6064 6065 //TODO (multidisplay): Magnification is supported only for the default display. 6066 if (mDisplayMagnifier != null 6067 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 6068 mDisplayMagnifier.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation); 6069 } 6070 6071 return true; 6072 } 6073 6074 @Override 6075 public int getRotation() { 6076 return mRotation; 6077 } 6078 6079 @Override 6080 public boolean isRotationFrozen() { 6081 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED; 6082 } 6083 6084 @Override 6085 public int watchRotation(IRotationWatcher watcher) { 6086 final IBinder watcherBinder = watcher.asBinder(); 6087 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 6088 @Override 6089 public void binderDied() { 6090 synchronized (mWindowMap) { 6091 for (int i=0; i<mRotationWatchers.size(); i++) { 6092 if (watcherBinder == mRotationWatchers.get(i).asBinder()) { 6093 IRotationWatcher removed = mRotationWatchers.remove(i); 6094 if (removed != null) { 6095 removed.asBinder().unlinkToDeath(this, 0); 6096 } 6097 i--; 6098 } 6099 } 6100 } 6101 } 6102 }; 6103 6104 synchronized (mWindowMap) { 6105 try { 6106 watcher.asBinder().linkToDeath(dr, 0); 6107 mRotationWatchers.add(watcher); 6108 } catch (RemoteException e) { 6109 // Client died, no cleanup needed. 6110 } 6111 6112 return mRotation; 6113 } 6114 } 6115 6116 @Override 6117 public void removeRotationWatcher(IRotationWatcher watcher) { 6118 final IBinder watcherBinder = watcher.asBinder(); 6119 synchronized (mWindowMap) { 6120 for (int i=0; i<mRotationWatchers.size(); i++) { 6121 if (watcherBinder == mRotationWatchers.get(i).asBinder()) { 6122 mRotationWatchers.remove(i); 6123 i--; 6124 } 6125 } 6126 } 6127 } 6128 6129 /** 6130 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 6131 * theme attribute) on devices that feature a physical options menu key attempt to position 6132 * their menu panel window along the edge of the screen nearest the physical menu key. 6133 * This lowers the travel distance between invoking the menu panel and selecting 6134 * a menu option. 6135 * 6136 * This method helps control where that menu is placed. Its current implementation makes 6137 * assumptions about the menu key and its relationship to the screen based on whether 6138 * the device's natural orientation is portrait (width < height) or landscape. 6139 * 6140 * The menu key is assumed to be located along the bottom edge of natural-portrait 6141 * devices and along the right edge of natural-landscape devices. If these assumptions 6142 * do not hold for the target device, this method should be changed to reflect that. 6143 * 6144 * @return A {@link Gravity} value for placing the options menu window 6145 */ 6146 @Override 6147 public int getPreferredOptionsPanelGravity() { 6148 synchronized (mWindowMap) { 6149 final int rotation = getRotation(); 6150 6151 // TODO(multidisplay): Assume that such devices physical keys are on the main screen. 6152 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6153 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) { 6154 // On devices with a natural orientation of portrait 6155 switch (rotation) { 6156 default: 6157 case Surface.ROTATION_0: 6158 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6159 case Surface.ROTATION_90: 6160 return Gravity.RIGHT | Gravity.BOTTOM; 6161 case Surface.ROTATION_180: 6162 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6163 case Surface.ROTATION_270: 6164 return Gravity.START | Gravity.BOTTOM; 6165 } 6166 } 6167 6168 // On devices with a natural orientation of landscape 6169 switch (rotation) { 6170 default: 6171 case Surface.ROTATION_0: 6172 return Gravity.RIGHT | Gravity.BOTTOM; 6173 case Surface.ROTATION_90: 6174 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6175 case Surface.ROTATION_180: 6176 return Gravity.START | Gravity.BOTTOM; 6177 case Surface.ROTATION_270: 6178 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6179 } 6180 } 6181 } 6182 6183 /** 6184 * Starts the view server on the specified port. 6185 * 6186 * @param port The port to listener to. 6187 * 6188 * @return True if the server was successfully started, false otherwise. 6189 * 6190 * @see com.android.server.wm.ViewServer 6191 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 6192 */ 6193 @Override 6194 public boolean startViewServer(int port) { 6195 if (isSystemSecure()) { 6196 return false; 6197 } 6198 6199 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 6200 return false; 6201 } 6202 6203 if (port < 1024) { 6204 return false; 6205 } 6206 6207 if (mViewServer != null) { 6208 if (!mViewServer.isRunning()) { 6209 try { 6210 return mViewServer.start(); 6211 } catch (IOException e) { 6212 Slog.w(TAG, "View server did not start"); 6213 } 6214 } 6215 return false; 6216 } 6217 6218 try { 6219 mViewServer = new ViewServer(this, port); 6220 return mViewServer.start(); 6221 } catch (IOException e) { 6222 Slog.w(TAG, "View server did not start"); 6223 } 6224 return false; 6225 } 6226 6227 private boolean isSystemSecure() { 6228 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 6229 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 6230 } 6231 6232 /** 6233 * Stops the view server if it exists. 6234 * 6235 * @return True if the server stopped, false if it wasn't started or 6236 * couldn't be stopped. 6237 * 6238 * @see com.android.server.wm.ViewServer 6239 */ 6240 @Override 6241 public boolean stopViewServer() { 6242 if (isSystemSecure()) { 6243 return false; 6244 } 6245 6246 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 6247 return false; 6248 } 6249 6250 if (mViewServer != null) { 6251 return mViewServer.stop(); 6252 } 6253 return false; 6254 } 6255 6256 /** 6257 * Indicates whether the view server is running. 6258 * 6259 * @return True if the server is running, false otherwise. 6260 * 6261 * @see com.android.server.wm.ViewServer 6262 */ 6263 @Override 6264 public boolean isViewServerRunning() { 6265 if (isSystemSecure()) { 6266 return false; 6267 } 6268 6269 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 6270 return false; 6271 } 6272 6273 return mViewServer != null && mViewServer.isRunning(); 6274 } 6275 6276 /** 6277 * Lists all availble windows in the system. The listing is written in the 6278 * specified Socket's output stream with the following syntax: 6279 * windowHashCodeInHexadecimal windowName 6280 * Each line of the ouput represents a different window. 6281 * 6282 * @param client The remote client to send the listing to. 6283 * @return False if an error occured, true otherwise. 6284 */ 6285 boolean viewServerListWindows(Socket client) { 6286 if (isSystemSecure()) { 6287 return false; 6288 } 6289 6290 boolean result = true; 6291 6292 WindowList windows = new WindowList(); 6293 synchronized (mWindowMap) { 6294 //noinspection unchecked 6295 final int numDisplays = mDisplayContents.size(); 6296 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6297 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 6298 windows.addAll(displayContent.getWindowList()); 6299 } 6300 } 6301 6302 BufferedWriter out = null; 6303 6304 // Any uncaught exception will crash the system process 6305 try { 6306 OutputStream clientStream = client.getOutputStream(); 6307 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6308 6309 final int count = windows.size(); 6310 for (int i = 0; i < count; i++) { 6311 final WindowState w = windows.get(i); 6312 out.write(Integer.toHexString(System.identityHashCode(w))); 6313 out.write(' '); 6314 out.append(w.mAttrs.getTitle()); 6315 out.write('\n'); 6316 } 6317 6318 out.write("DONE.\n"); 6319 out.flush(); 6320 } catch (Exception e) { 6321 result = false; 6322 } finally { 6323 if (out != null) { 6324 try { 6325 out.close(); 6326 } catch (IOException e) { 6327 result = false; 6328 } 6329 } 6330 } 6331 6332 return result; 6333 } 6334 6335 // TODO(multidisplay): Extend to multiple displays. 6336 /** 6337 * Returns the focused window in the following format: 6338 * windowHashCodeInHexadecimal windowName 6339 * 6340 * @param client The remote client to send the listing to. 6341 * @return False if an error occurred, true otherwise. 6342 */ 6343 boolean viewServerGetFocusedWindow(Socket client) { 6344 if (isSystemSecure()) { 6345 return false; 6346 } 6347 6348 boolean result = true; 6349 6350 WindowState focusedWindow = getFocusedWindow(); 6351 6352 BufferedWriter out = null; 6353 6354 // Any uncaught exception will crash the system process 6355 try { 6356 OutputStream clientStream = client.getOutputStream(); 6357 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6358 6359 if(focusedWindow != null) { 6360 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 6361 out.write(' '); 6362 out.append(focusedWindow.mAttrs.getTitle()); 6363 } 6364 out.write('\n'); 6365 out.flush(); 6366 } catch (Exception e) { 6367 result = false; 6368 } finally { 6369 if (out != null) { 6370 try { 6371 out.close(); 6372 } catch (IOException e) { 6373 result = false; 6374 } 6375 } 6376 } 6377 6378 return result; 6379 } 6380 6381 /** 6382 * Sends a command to a target window. The result of the command, if any, will be 6383 * written in the output stream of the specified socket. 6384 * 6385 * The parameters must follow this syntax: 6386 * windowHashcode extra 6387 * 6388 * Where XX is the length in characeters of the windowTitle. 6389 * 6390 * The first parameter is the target window. The window with the specified hashcode 6391 * will be the target. If no target can be found, nothing happens. The extra parameters 6392 * will be delivered to the target window and as parameters to the command itself. 6393 * 6394 * @param client The remote client to sent the result, if any, to. 6395 * @param command The command to execute. 6396 * @param parameters The command parameters. 6397 * 6398 * @return True if the command was successfully delivered, false otherwise. This does 6399 * not indicate whether the command itself was successful. 6400 */ 6401 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 6402 if (isSystemSecure()) { 6403 return false; 6404 } 6405 6406 boolean success = true; 6407 Parcel data = null; 6408 Parcel reply = null; 6409 6410 BufferedWriter out = null; 6411 6412 // Any uncaught exception will crash the system process 6413 try { 6414 // Find the hashcode of the window 6415 int index = parameters.indexOf(' '); 6416 if (index == -1) { 6417 index = parameters.length(); 6418 } 6419 final String code = parameters.substring(0, index); 6420 int hashCode = (int) Long.parseLong(code, 16); 6421 6422 // Extract the command's parameter after the window description 6423 if (index < parameters.length()) { 6424 parameters = parameters.substring(index + 1); 6425 } else { 6426 parameters = ""; 6427 } 6428 6429 final WindowState window = findWindow(hashCode); 6430 if (window == null) { 6431 return false; 6432 } 6433 6434 data = Parcel.obtain(); 6435 data.writeInterfaceToken("android.view.IWindow"); 6436 data.writeString(command); 6437 data.writeString(parameters); 6438 data.writeInt(1); 6439 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 6440 6441 reply = Parcel.obtain(); 6442 6443 final IBinder binder = window.mClient.asBinder(); 6444 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 6445 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 6446 6447 reply.readException(); 6448 6449 if (!client.isOutputShutdown()) { 6450 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 6451 out.write("DONE\n"); 6452 out.flush(); 6453 } 6454 6455 } catch (Exception e) { 6456 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); 6457 success = false; 6458 } finally { 6459 if (data != null) { 6460 data.recycle(); 6461 } 6462 if (reply != null) { 6463 reply.recycle(); 6464 } 6465 if (out != null) { 6466 try { 6467 out.close(); 6468 } catch (IOException e) { 6469 6470 } 6471 } 6472 } 6473 6474 return success; 6475 } 6476 6477 public void addWindowChangeListener(WindowChangeListener listener) { 6478 synchronized(mWindowMap) { 6479 mWindowChangeListeners.add(listener); 6480 } 6481 } 6482 6483 public void removeWindowChangeListener(WindowChangeListener listener) { 6484 synchronized(mWindowMap) { 6485 mWindowChangeListeners.remove(listener); 6486 } 6487 } 6488 6489 private void notifyWindowsChanged() { 6490 WindowChangeListener[] windowChangeListeners; 6491 synchronized(mWindowMap) { 6492 if(mWindowChangeListeners.isEmpty()) { 6493 return; 6494 } 6495 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6496 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6497 } 6498 int N = windowChangeListeners.length; 6499 for(int i = 0; i < N; i++) { 6500 windowChangeListeners[i].windowsChanged(); 6501 } 6502 } 6503 6504 private void notifyFocusChanged() { 6505 WindowChangeListener[] windowChangeListeners; 6506 synchronized(mWindowMap) { 6507 if(mWindowChangeListeners.isEmpty()) { 6508 return; 6509 } 6510 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6511 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6512 } 6513 int N = windowChangeListeners.length; 6514 for(int i = 0; i < N; i++) { 6515 windowChangeListeners[i].focusChanged(); 6516 } 6517 } 6518 6519 private WindowState findWindow(int hashCode) { 6520 if (hashCode == -1) { 6521 // TODO(multidisplay): Extend to multiple displays. 6522 return getFocusedWindow(); 6523 } 6524 6525 synchronized (mWindowMap) { 6526 final int numDisplays = mDisplayContents.size(); 6527 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6528 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 6529 final int numWindows = windows.size(); 6530 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 6531 final WindowState w = windows.get(winNdx); 6532 if (System.identityHashCode(w) == hashCode) { 6533 return w; 6534 } 6535 } 6536 } 6537 } 6538 6539 return null; 6540 } 6541 6542 /* 6543 * Instruct the Activity Manager to fetch the current configuration and broadcast 6544 * that to config-changed listeners if appropriate. 6545 */ 6546 void sendNewConfiguration() { 6547 try { 6548 mActivityManager.updateConfiguration(null); 6549 } catch (RemoteException e) { 6550 } 6551 } 6552 6553 public Configuration computeNewConfiguration() { 6554 synchronized (mWindowMap) { 6555 Configuration config = computeNewConfigurationLocked(); 6556 if (config == null && mWaitingForConfig) { 6557 // Nothing changed but we are waiting for something... stop that! 6558 mWaitingForConfig = false; 6559 mLastFinishedFreezeSource = "new-config"; 6560 performLayoutAndPlaceSurfacesLocked(); 6561 } 6562 return config; 6563 } 6564 } 6565 6566 Configuration computeNewConfigurationLocked() { 6567 Configuration config = new Configuration(); 6568 config.fontScale = 0; 6569 if (!computeScreenConfigurationLocked(config)) { 6570 return null; 6571 } 6572 return config; 6573 } 6574 6575 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) { 6576 // TODO: Multidisplay: for now only use with default display. 6577 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation); 6578 if (width < displayInfo.smallestNominalAppWidth) { 6579 displayInfo.smallestNominalAppWidth = width; 6580 } 6581 if (width > displayInfo.largestNominalAppWidth) { 6582 displayInfo.largestNominalAppWidth = width; 6583 } 6584 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation); 6585 if (height < displayInfo.smallestNominalAppHeight) { 6586 displayInfo.smallestNominalAppHeight = height; 6587 } 6588 if (height > displayInfo.largestNominalAppHeight) { 6589 displayInfo.largestNominalAppHeight = height; 6590 } 6591 } 6592 6593 private int reduceConfigLayout(int curLayout, int rotation, float density, 6594 int dw, int dh) { 6595 // TODO: Multidisplay: for now only use with default display. 6596 // Get the app screen size at this rotation. 6597 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6598 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6599 6600 // Compute the screen layout size class for this rotation. 6601 int longSize = w; 6602 int shortSize = h; 6603 if (longSize < shortSize) { 6604 int tmp = longSize; 6605 longSize = shortSize; 6606 shortSize = tmp; 6607 } 6608 longSize = (int)(longSize/density); 6609 shortSize = (int)(shortSize/density); 6610 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 6611 } 6612 6613 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 6614 int dw, int dh, float density, Configuration outConfig) { 6615 // TODO: Multidisplay: for now only use with default display. 6616 6617 // We need to determine the smallest width that will occur under normal 6618 // operation. To this, start with the base screen size and compute the 6619 // width under the different possible rotations. We need to un-rotate 6620 // the current screen dimensions before doing this. 6621 int unrotDw, unrotDh; 6622 if (rotated) { 6623 unrotDw = dh; 6624 unrotDh = dw; 6625 } else { 6626 unrotDw = dw; 6627 unrotDh = dh; 6628 } 6629 displayInfo.smallestNominalAppWidth = 1<<30; 6630 displayInfo.smallestNominalAppHeight = 1<<30; 6631 displayInfo.largestNominalAppWidth = 0; 6632 displayInfo.largestNominalAppHeight = 0; 6633 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh); 6634 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw); 6635 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh); 6636 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw); 6637 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 6638 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh); 6639 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw); 6640 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); 6641 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); 6642 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 6643 outConfig.screenLayout = sl; 6644 } 6645 6646 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, 6647 int dw, int dh) { 6648 // TODO: Multidisplay: for now only use with default display. 6649 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6650 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6651 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 6652 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 6653 if (curSize == 0 || size < curSize) { 6654 curSize = size; 6655 } 6656 return curSize; 6657 } 6658 6659 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) { 6660 // TODO: Multidisplay: for now only use with default display. 6661 mTmpDisplayMetrics.setTo(dm); 6662 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 6663 final int unrotDw, unrotDh; 6664 if (rotated) { 6665 unrotDw = dh; 6666 unrotDh = dw; 6667 } else { 6668 unrotDw = dw; 6669 unrotDh = dh; 6670 } 6671 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh); 6672 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw); 6673 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh); 6674 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw); 6675 return sw; 6676 } 6677 6678 boolean computeScreenConfigurationLocked(Configuration config) { 6679 if (!mDisplayReady) { 6680 return false; 6681 } 6682 6683 // TODO(multidisplay): For now, apply Configuration to main screen only. 6684 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6685 6686 // Use the effective "visual" dimensions based on current rotation 6687 final boolean rotated = (mRotation == Surface.ROTATION_90 6688 || mRotation == Surface.ROTATION_270); 6689 final int realdw = rotated ? 6690 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; 6691 final int realdh = rotated ? 6692 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; 6693 int dw = realdw; 6694 int dh = realdh; 6695 6696 if (mAltOrientation) { 6697 if (realdw > realdh) { 6698 // Turn landscape into portrait. 6699 int maxw = (int)(realdh/1.3f); 6700 if (maxw < realdw) { 6701 dw = maxw; 6702 } 6703 } else { 6704 // Turn portrait into landscape. 6705 int maxh = (int)(realdw/1.3f); 6706 if (maxh < realdh) { 6707 dh = maxh; 6708 } 6709 } 6710 } 6711 6712 if (config != null) { 6713 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : 6714 Configuration.ORIENTATION_LANDSCAPE; 6715 } 6716 6717 // Update application display metrics. 6718 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); 6719 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); 6720 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6721 synchronized(displayContent.mDisplaySizeLock) { 6722 displayInfo.rotation = mRotation; 6723 displayInfo.logicalWidth = dw; 6724 displayInfo.logicalHeight = dh; 6725 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; 6726 displayInfo.appWidth = appWidth; 6727 displayInfo.appHeight = appHeight; 6728 displayInfo.getLogicalMetrics(mRealDisplayMetrics, 6729 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 6730 displayInfo.getAppMetrics(mDisplayMetrics); 6731 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 6732 displayContent.getDisplayId(), displayInfo); 6733 } 6734 if (false) { 6735 Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); 6736 } 6737 6738 final DisplayMetrics dm = mDisplayMetrics; 6739 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, 6740 mCompatDisplayMetrics); 6741 6742 if (config != null) { 6743 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) 6744 / dm.density); 6745 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) 6746 / dm.density); 6747 computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config); 6748 6749 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 6750 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 6751 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); 6752 config.densityDpi = displayContent.mBaseDisplayDensity; 6753 6754 // Update the configuration based on available input devices, lid switch, 6755 // and platform configuration. 6756 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6757 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6758 config.navigation = Configuration.NAVIGATION_NONAV; 6759 6760 int keyboardPresence = 0; 6761 int navigationPresence = 0; 6762 final InputDevice[] devices = mInputManager.getInputDevices(); 6763 final int len = devices.length; 6764 for (int i = 0; i < len; i++) { 6765 InputDevice device = devices[i]; 6766 if (!device.isVirtual()) { 6767 final int sources = device.getSources(); 6768 final int presenceFlag = device.isExternal() ? 6769 WindowManagerPolicy.PRESENCE_EXTERNAL : 6770 WindowManagerPolicy.PRESENCE_INTERNAL; 6771 6772 if (mIsTouchDevice) { 6773 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 6774 InputDevice.SOURCE_TOUCHSCREEN) { 6775 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 6776 } 6777 } else { 6778 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6779 } 6780 6781 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 6782 config.navigation = Configuration.NAVIGATION_TRACKBALL; 6783 navigationPresence |= presenceFlag; 6784 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 6785 && config.navigation == Configuration.NAVIGATION_NONAV) { 6786 config.navigation = Configuration.NAVIGATION_DPAD; 6787 navigationPresence |= presenceFlag; 6788 } 6789 6790 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 6791 config.keyboard = Configuration.KEYBOARD_QWERTY; 6792 keyboardPresence |= presenceFlag; 6793 } 6794 } 6795 } 6796 6797 // Determine whether a hard keyboard is available and enabled. 6798 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 6799 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 6800 mHardKeyboardAvailable = hardKeyboardAvailable; 6801 mHardKeyboardEnabled = hardKeyboardAvailable; 6802 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6803 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6804 } 6805 if (!mHardKeyboardEnabled) { 6806 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6807 } 6808 6809 // Let the policy update hidden states. 6810 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 6811 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 6812 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 6813 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 6814 } 6815 6816 return true; 6817 } 6818 6819 public boolean isHardKeyboardAvailable() { 6820 synchronized (mWindowMap) { 6821 return mHardKeyboardAvailable; 6822 } 6823 } 6824 6825 public boolean isHardKeyboardEnabled() { 6826 synchronized (mWindowMap) { 6827 return mHardKeyboardEnabled; 6828 } 6829 } 6830 6831 public void setHardKeyboardEnabled(boolean enabled) { 6832 synchronized (mWindowMap) { 6833 if (mHardKeyboardEnabled != enabled) { 6834 mHardKeyboardEnabled = enabled; 6835 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6836 } 6837 } 6838 } 6839 6840 public void setOnHardKeyboardStatusChangeListener( 6841 OnHardKeyboardStatusChangeListener listener) { 6842 synchronized (mWindowMap) { 6843 mHardKeyboardStatusChangeListener = listener; 6844 } 6845 } 6846 6847 void notifyHardKeyboardStatusChange() { 6848 final boolean available, enabled; 6849 final OnHardKeyboardStatusChangeListener listener; 6850 synchronized (mWindowMap) { 6851 listener = mHardKeyboardStatusChangeListener; 6852 available = mHardKeyboardAvailable; 6853 enabled = mHardKeyboardEnabled; 6854 } 6855 if (listener != null) { 6856 listener.onHardKeyboardStatusChange(available, enabled); 6857 } 6858 } 6859 6860 // ------------------------------------------------------------- 6861 // Drag and drop 6862 // ------------------------------------------------------------- 6863 6864 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 6865 int flags, int width, int height, Surface outSurface) { 6866 if (DEBUG_DRAG) { 6867 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 6868 + " flags=" + Integer.toHexString(flags) + " win=" + window 6869 + " asbinder=" + window.asBinder()); 6870 } 6871 6872 final int callerPid = Binder.getCallingPid(); 6873 final long origId = Binder.clearCallingIdentity(); 6874 IBinder token = null; 6875 6876 try { 6877 synchronized (mWindowMap) { 6878 try { 6879 if (mDragState == null) { 6880 // TODO(multi-display): support other displays 6881 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6882 final Display display = displayContent.getDisplay(); 6883 SurfaceControl surface = new SurfaceControl(session, "drag surface", 6884 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 6885 surface.setLayerStack(display.getLayerStack()); 6886 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 6887 + surface + ": CREATE"); 6888 outSurface.copyFrom(surface); 6889 final IBinder winBinder = window.asBinder(); 6890 token = new Binder(); 6891 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 6892 token = mDragState.mToken = new Binder(); 6893 6894 // 5 second timeout for this window to actually begin the drag 6895 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 6896 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 6897 mH.sendMessageDelayed(msg, 5000); 6898 } else { 6899 Slog.w(TAG, "Drag already in progress"); 6900 } 6901 } catch (OutOfResourcesException e) { 6902 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 6903 if (mDragState != null) { 6904 mDragState.reset(); 6905 mDragState = null; 6906 } 6907 } 6908 } 6909 } finally { 6910 Binder.restoreCallingIdentity(origId); 6911 } 6912 6913 return token; 6914 } 6915 6916 // ------------------------------------------------------------- 6917 // Input Events and Focus Management 6918 // ------------------------------------------------------------- 6919 6920 final InputMonitor mInputMonitor = new InputMonitor(this); 6921 private boolean mEventDispatchingEnabled; 6922 6923 @Override 6924 public void pauseKeyDispatching(IBinder _token) { 6925 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6926 "pauseKeyDispatching()")) { 6927 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6928 } 6929 6930 synchronized (mWindowMap) { 6931 WindowToken token = mTokenMap.get(_token); 6932 if (token != null) { 6933 mInputMonitor.pauseDispatchingLw(token); 6934 } 6935 } 6936 } 6937 6938 @Override 6939 public void resumeKeyDispatching(IBinder _token) { 6940 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6941 "resumeKeyDispatching()")) { 6942 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6943 } 6944 6945 synchronized (mWindowMap) { 6946 WindowToken token = mTokenMap.get(_token); 6947 if (token != null) { 6948 mInputMonitor.resumeDispatchingLw(token); 6949 } 6950 } 6951 } 6952 6953 @Override 6954 public void setEventDispatching(boolean enabled) { 6955 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6956 "setEventDispatching()")) { 6957 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6958 } 6959 6960 synchronized (mWindowMap) { 6961 mEventDispatchingEnabled = enabled; 6962 if (mDisplayEnabled) { 6963 mInputMonitor.setEventDispatchingLw(enabled); 6964 } 6965 sendScreenStatusToClientsLocked(); 6966 } 6967 } 6968 6969 @Override 6970 public IBinder getFocusedWindowToken() { 6971 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 6972 "getFocusedWindowToken()")) { 6973 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission."); 6974 } 6975 synchronized (mWindowMap) { 6976 WindowState windowState = getFocusedWindowLocked(); 6977 if (windowState != null) { 6978 return windowState.mClient.asBinder(); 6979 } 6980 return null; 6981 } 6982 } 6983 6984 private WindowState getFocusedWindow() { 6985 synchronized (mWindowMap) { 6986 return getFocusedWindowLocked(); 6987 } 6988 } 6989 6990 private WindowState getFocusedWindowLocked() { 6991 return mCurrentFocus; 6992 } 6993 6994 public boolean detectSafeMode() { 6995 if (!mInputMonitor.waitForInputDevicesReady( 6996 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 6997 Slog.w(TAG, "Devices still not ready after waiting " 6998 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 6999 + " milliseconds before attempting to detect safe mode."); 7000 } 7001 7002 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7003 KeyEvent.KEYCODE_MENU); 7004 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 7005 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 7006 KeyEvent.KEYCODE_DPAD_CENTER); 7007 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 7008 InputManagerService.BTN_MOUSE); 7009 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7010 KeyEvent.KEYCODE_VOLUME_DOWN); 7011 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 7012 || volumeDownState > 0; 7013 try { 7014 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 7015 mSafeMode = true; 7016 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 7017 } 7018 } catch (IllegalArgumentException e) { 7019 } 7020 if (mSafeMode) { 7021 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 7022 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 7023 } else { 7024 Log.i(TAG, "SAFE MODE not enabled"); 7025 } 7026 mPolicy.setSafeMode(mSafeMode); 7027 return mSafeMode; 7028 } 7029 7030 public void displayReady() { 7031 displayReady(Display.DEFAULT_DISPLAY); 7032 7033 synchronized(mWindowMap) { 7034 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7035 readForcedDisplaySizeAndDensityLocked(displayContent); 7036 mDisplayReady = true; 7037 } 7038 7039 try { 7040 mActivityManager.updateConfiguration(null); 7041 } catch (RemoteException e) { 7042 } 7043 7044 synchronized(mWindowMap) { 7045 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 7046 PackageManager.FEATURE_TOUCHSCREEN); 7047 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 7048 } 7049 7050 try { 7051 mActivityManager.updateConfiguration(null); 7052 } catch (RemoteException e) { 7053 } 7054 } 7055 7056 private void displayReady(int displayId) { 7057 synchronized(mWindowMap) { 7058 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7059 if (displayContent != null) { 7060 mAnimator.addDisplayLocked(displayId); 7061 synchronized(displayContent.mDisplaySizeLock) { 7062 // Bootstrap the default logical display from the display manager. 7063 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7064 DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId); 7065 if (newDisplayInfo != null) { 7066 displayInfo.copyFrom(newDisplayInfo); 7067 } 7068 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; 7069 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; 7070 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; 7071 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; 7072 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; 7073 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; 7074 displayContent.mBaseDisplayRect.set(0, 0, 7075 displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight); 7076 } 7077 } 7078 } 7079 } 7080 7081 public void systemReady() { 7082 mPolicy.systemReady(); 7083 } 7084 7085 // TODO(multidisplay): Call isScreenOn for each display. 7086 private void sendScreenStatusToClientsLocked() { 7087 final boolean on = mPowerManager.isScreenOn(); 7088 final int numDisplays = mDisplayContents.size(); 7089 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 7090 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 7091 final int numWindows = windows.size(); 7092 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 7093 try { 7094 windows.get(winNdx).mClient.dispatchScreenState(on); 7095 } catch (RemoteException e) { 7096 // Ignored 7097 } 7098 } 7099 } 7100 } 7101 7102 // ------------------------------------------------------------- 7103 // Async Handler 7104 // ------------------------------------------------------------- 7105 7106 final class H extends Handler { 7107 public static final int REPORT_FOCUS_CHANGE = 2; 7108 public static final int REPORT_LOSING_FOCUS = 3; 7109 public static final int DO_TRAVERSAL = 4; 7110 public static final int ADD_STARTING = 5; 7111 public static final int REMOVE_STARTING = 6; 7112 public static final int FINISHED_STARTING = 7; 7113 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 7114 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 7115 public static final int WINDOW_FREEZE_TIMEOUT = 11; 7116 7117 public static final int APP_TRANSITION_TIMEOUT = 13; 7118 public static final int PERSIST_ANIMATION_SCALE = 14; 7119 public static final int FORCE_GC = 15; 7120 public static final int ENABLE_SCREEN = 16; 7121 public static final int APP_FREEZE_TIMEOUT = 17; 7122 public static final int SEND_NEW_CONFIGURATION = 18; 7123 public static final int REPORT_WINDOWS_CHANGE = 19; 7124 public static final int DRAG_START_TIMEOUT = 20; 7125 public static final int DRAG_END_TIMEOUT = 21; 7126 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 7127 public static final int BOOT_TIMEOUT = 23; 7128 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 7129 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 7130 public static final int DO_ANIMATION_CALLBACK = 26; 7131 7132 public static final int DO_DISPLAY_ADDED = 27; 7133 public static final int DO_DISPLAY_REMOVED = 28; 7134 public static final int DO_DISPLAY_CHANGED = 29; 7135 7136 public static final int CLIENT_FREEZE_TIMEOUT = 30; 7137 public static final int TAP_OUTSIDE_STACK = 31; 7138 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 7139 7140 public static final int REMOVE_STARTING_TIMEOUT = 33; 7141 7142 @Override 7143 public void handleMessage(Message msg) { 7144 if (DEBUG_WINDOW_TRACE) { 7145 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 7146 } 7147 switch (msg.what) { 7148 case REPORT_FOCUS_CHANGE: { 7149 WindowState lastFocus; 7150 WindowState newFocus; 7151 7152 synchronized(mWindowMap) { 7153 lastFocus = mLastFocus; 7154 newFocus = mCurrentFocus; 7155 if (lastFocus == newFocus) { 7156 // Focus is not changing, so nothing to do. 7157 return; 7158 } 7159 mLastFocus = newFocus; 7160 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus + 7161 " to " + newFocus); 7162 if (newFocus != null && lastFocus != null 7163 && !newFocus.isDisplayedLw()) { 7164 //Slog.i(TAG, "Delaying loss of focus..."); 7165 mLosingFocus.add(lastFocus); 7166 lastFocus = null; 7167 } 7168 } 7169 7170 //System.out.println("Changing focus from " + lastFocus 7171 // + " to " + newFocus); 7172 if (newFocus != null) { 7173 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus); 7174 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 7175 notifyFocusChanged(); 7176 } 7177 7178 if (lastFocus != null) { 7179 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus); 7180 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 7181 } 7182 } break; 7183 7184 case REPORT_LOSING_FOCUS: { 7185 ArrayList<WindowState> losers; 7186 7187 synchronized(mWindowMap) { 7188 losers = mLosingFocus; 7189 mLosingFocus = new ArrayList<WindowState>(); 7190 } 7191 7192 final int N = losers.size(); 7193 for (int i=0; i<N; i++) { 7194 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " + 7195 losers.get(i)); 7196 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 7197 } 7198 } break; 7199 7200 case DO_TRAVERSAL: { 7201 synchronized(mWindowMap) { 7202 mTraversalScheduled = false; 7203 performLayoutAndPlaceSurfacesLocked(); 7204 } 7205 } break; 7206 7207 case ADD_STARTING: { 7208 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7209 final StartingData sd = wtoken.startingData; 7210 7211 if (sd == null) { 7212 // Animation has been canceled... do nothing. 7213 return; 7214 } 7215 7216 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 7217 + wtoken + ": pkg=" + sd.pkg); 7218 7219 View view = null; 7220 try { 7221 view = mPolicy.addStartingWindow( 7222 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 7223 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags); 7224 } catch (Exception e) { 7225 Slog.w(TAG, "Exception when adding starting window", e); 7226 } 7227 7228 if (view != null) { 7229 boolean abort = false; 7230 7231 synchronized(mWindowMap) { 7232 if (wtoken.removed || wtoken.startingData == null) { 7233 // If the window was successfully added, then 7234 // we need to remove it. 7235 if (wtoken.startingWindow != null) { 7236 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7237 "Aborted starting " + wtoken 7238 + ": removed=" + wtoken.removed 7239 + " startingData=" + wtoken.startingData); 7240 removeStartingWindowTimeout(wtoken); 7241 wtoken.startingWindow = null; 7242 wtoken.startingData = null; 7243 abort = true; 7244 } 7245 } else { 7246 wtoken.startingView = view; 7247 } 7248 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7249 "Added starting " + wtoken 7250 + ": startingWindow=" 7251 + wtoken.startingWindow + " startingView=" 7252 + wtoken.startingView); 7253 } 7254 7255 if (abort) { 7256 try { 7257 mPolicy.removeStartingWindow(wtoken.token, view); 7258 } catch (Exception e) { 7259 Slog.w(TAG, "Exception when removing starting window", e); 7260 } 7261 } 7262 } 7263 } break; 7264 7265 case REMOVE_STARTING_TIMEOUT: { 7266 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7267 Slog.e(TAG, "Starting window " + wtoken + " timed out"); 7268 // Fall through. 7269 } 7270 case REMOVE_STARTING: { 7271 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7272 IBinder token = null; 7273 View view = null; 7274 synchronized (mWindowMap) { 7275 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7276 + wtoken + ": startingWindow=" 7277 + wtoken.startingWindow + " startingView=" 7278 + wtoken.startingView); 7279 if (wtoken.startingWindow != null) { 7280 view = wtoken.startingView; 7281 token = wtoken.token; 7282 wtoken.startingData = null; 7283 wtoken.startingView = null; 7284 wtoken.startingWindow = null; 7285 wtoken.startingDisplayed = false; 7286 } 7287 } 7288 if (view != null) { 7289 try { 7290 mPolicy.removeStartingWindow(token, view); 7291 } catch (Exception e) { 7292 Slog.w(TAG, "Exception when removing starting window", e); 7293 } 7294 } 7295 } break; 7296 7297 case FINISHED_STARTING: { 7298 IBinder token = null; 7299 View view = null; 7300 while (true) { 7301 synchronized (mWindowMap) { 7302 final int N = mFinishedStarting.size(); 7303 if (N <= 0) { 7304 break; 7305 } 7306 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7307 7308 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7309 "Finished starting " + wtoken 7310 + ": startingWindow=" + wtoken.startingWindow 7311 + " startingView=" + wtoken.startingView); 7312 7313 if (wtoken.startingWindow == null) { 7314 continue; 7315 } 7316 7317 view = wtoken.startingView; 7318 token = wtoken.token; 7319 wtoken.startingData = null; 7320 wtoken.startingView = null; 7321 wtoken.startingWindow = null; 7322 wtoken.startingDisplayed = false; 7323 } 7324 7325 try { 7326 mPolicy.removeStartingWindow(token, view); 7327 } catch (Exception e) { 7328 Slog.w(TAG, "Exception when removing starting window", e); 7329 } 7330 } 7331 } break; 7332 7333 case REPORT_APPLICATION_TOKEN_DRAWN: { 7334 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7335 7336 try { 7337 if (DEBUG_VISIBILITY) Slog.v( 7338 TAG, "Reporting drawn in " + wtoken); 7339 wtoken.appToken.windowsDrawn(); 7340 } catch (RemoteException ex) { 7341 } 7342 } break; 7343 7344 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7345 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7346 7347 boolean nowVisible = msg.arg1 != 0; 7348 boolean nowGone = msg.arg2 != 0; 7349 7350 try { 7351 if (DEBUG_VISIBILITY) Slog.v( 7352 TAG, "Reporting visible in " + wtoken 7353 + " visible=" + nowVisible 7354 + " gone=" + nowGone); 7355 if (nowVisible) { 7356 wtoken.appToken.windowsVisible(); 7357 } else { 7358 wtoken.appToken.windowsGone(); 7359 } 7360 } catch (RemoteException ex) { 7361 } 7362 } break; 7363 7364 case WINDOW_FREEZE_TIMEOUT: { 7365 // TODO(multidisplay): Can non-default displays rotate? 7366 synchronized (mWindowMap) { 7367 Slog.w(TAG, "Window freeze timeout expired."); 7368 final WindowList windows = getDefaultWindowListLocked(); 7369 int i = windows.size(); 7370 while (i > 0) { 7371 i--; 7372 WindowState w = windows.get(i); 7373 if (w.mOrientationChanging) { 7374 w.mOrientationChanging = false; 7375 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 7376 - mDisplayFreezeTime); 7377 Slog.w(TAG, "Force clearing orientation change: " + w); 7378 } 7379 } 7380 performLayoutAndPlaceSurfacesLocked(); 7381 } 7382 break; 7383 } 7384 7385 case APP_TRANSITION_TIMEOUT: { 7386 synchronized (mWindowMap) { 7387 if (mAppTransition.isTransitionSet()) { 7388 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT"); 7389 mAppTransition.setTimeout(); 7390 performLayoutAndPlaceSurfacesLocked(); 7391 } 7392 } 7393 break; 7394 } 7395 7396 case PERSIST_ANIMATION_SCALE: { 7397 Settings.Global.putFloat(mContext.getContentResolver(), 7398 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); 7399 Settings.Global.putFloat(mContext.getContentResolver(), 7400 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); 7401 Settings.Global.putFloat(mContext.getContentResolver(), 7402 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale); 7403 break; 7404 } 7405 7406 case FORCE_GC: { 7407 synchronized (mWindowMap) { 7408 // Since we're holding both mWindowMap and mAnimator we don't need to 7409 // hold mAnimator.mLayoutToAnim. 7410 if (mAnimator.mAnimating || mAnimationScheduled) { 7411 // If we are animating, don't do the gc now but 7412 // delay a bit so we don't interrupt the animation. 7413 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 7414 return; 7415 } 7416 // If we are currently rotating the display, it will 7417 // schedule a new message when done. 7418 if (mDisplayFrozen) { 7419 return; 7420 } 7421 } 7422 Runtime.getRuntime().gc(); 7423 break; 7424 } 7425 7426 case ENABLE_SCREEN: { 7427 performEnableScreen(); 7428 break; 7429 } 7430 7431 case APP_FREEZE_TIMEOUT: { 7432 synchronized (mWindowMap) { 7433 Slog.w(TAG, "App freeze timeout expired."); 7434 final int numStacks = mStackIdToStack.size(); 7435 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 7436 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 7437 final ArrayList<Task> tasks = stack.getTasks(); 7438 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 7439 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 7440 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 7441 AppWindowToken tok = tokens.get(tokenNdx); 7442 if (tok.mAppAnimator.freezingScreen) { 7443 Slog.w(TAG, "Force clearing freeze: " + tok); 7444 unsetAppFreezingScreenLocked(tok, true, true); 7445 } 7446 } 7447 } 7448 } 7449 } 7450 break; 7451 } 7452 7453 case CLIENT_FREEZE_TIMEOUT: { 7454 synchronized (mWindowMap) { 7455 if (mClientFreezingScreen) { 7456 mClientFreezingScreen = false; 7457 mLastFinishedFreezeSource = "client-timeout"; 7458 stopFreezingDisplayLocked(); 7459 } 7460 } 7461 break; 7462 } 7463 7464 case SEND_NEW_CONFIGURATION: { 7465 removeMessages(SEND_NEW_CONFIGURATION); 7466 sendNewConfiguration(); 7467 break; 7468 } 7469 7470 case REPORT_WINDOWS_CHANGE: { 7471 if (mWindowsChanged) { 7472 synchronized (mWindowMap) { 7473 mWindowsChanged = false; 7474 } 7475 notifyWindowsChanged(); 7476 } 7477 break; 7478 } 7479 7480 case DRAG_START_TIMEOUT: { 7481 IBinder win = (IBinder)msg.obj; 7482 if (DEBUG_DRAG) { 7483 Slog.w(TAG, "Timeout starting drag by win " + win); 7484 } 7485 synchronized (mWindowMap) { 7486 // !!! TODO: ANR the app that has failed to start the drag in time 7487 if (mDragState != null) { 7488 mDragState.unregister(); 7489 mInputMonitor.updateInputWindowsLw(true /*force*/); 7490 mDragState.reset(); 7491 mDragState = null; 7492 } 7493 } 7494 break; 7495 } 7496 7497 case DRAG_END_TIMEOUT: { 7498 IBinder win = (IBinder)msg.obj; 7499 if (DEBUG_DRAG) { 7500 Slog.w(TAG, "Timeout ending drag to win " + win); 7501 } 7502 synchronized (mWindowMap) { 7503 // !!! TODO: ANR the drag-receiving app 7504 if (mDragState != null) { 7505 mDragState.mDragResult = false; 7506 mDragState.endDragLw(); 7507 } 7508 } 7509 break; 7510 } 7511 7512 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7513 notifyHardKeyboardStatusChange(); 7514 break; 7515 } 7516 7517 case BOOT_TIMEOUT: { 7518 performBootTimeout(); 7519 break; 7520 } 7521 7522 case WAITING_FOR_DRAWN_TIMEOUT: { 7523 Pair<WindowState, IRemoteCallback> pair; 7524 synchronized (mWindowMap) { 7525 pair = (Pair<WindowState, IRemoteCallback>)msg.obj; 7526 Slog.w(TAG, "Timeout waiting for drawn: " + pair.first); 7527 if (!mWaitingForDrawn.remove(pair)) { 7528 return; 7529 } 7530 } 7531 try { 7532 pair.second.sendResult(null); 7533 } catch (RemoteException e) { 7534 } 7535 break; 7536 } 7537 7538 case SHOW_STRICT_MODE_VIOLATION: { 7539 showStrictModeViolation(msg.arg1, msg.arg2); 7540 break; 7541 } 7542 7543 case DO_ANIMATION_CALLBACK: { 7544 try { 7545 ((IRemoteCallback)msg.obj).sendResult(null); 7546 } catch (RemoteException e) { 7547 } 7548 break; 7549 } 7550 7551 case DO_DISPLAY_ADDED: 7552 handleDisplayAdded(msg.arg1); 7553 break; 7554 7555 case DO_DISPLAY_REMOVED: 7556 synchronized (mWindowMap) { 7557 handleDisplayRemovedLocked(msg.arg1); 7558 } 7559 break; 7560 7561 case DO_DISPLAY_CHANGED: 7562 synchronized (mWindowMap) { 7563 handleDisplayChangedLocked(msg.arg1); 7564 } 7565 break; 7566 7567 case TAP_OUTSIDE_STACK: { 7568 int stackId; 7569 synchronized (mWindowMap) { 7570 stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2); 7571 } 7572 if (stackId >= 0) { 7573 try { 7574 mActivityManager.setFocusedStack(stackId); 7575 } catch (RemoteException e) { 7576 } 7577 } 7578 } 7579 break; 7580 case NOTIFY_ACTIVITY_DRAWN: 7581 try { 7582 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 7583 } catch (RemoteException e) { 7584 } 7585 break; 7586 } 7587 if (DEBUG_WINDOW_TRACE) { 7588 Slog.v(TAG, "handleMessage: exit"); 7589 } 7590 } 7591 } 7592 7593 // ------------------------------------------------------------- 7594 // IWindowManager API 7595 // ------------------------------------------------------------- 7596 7597 @Override 7598 public IWindowSession openSession(IInputMethodClient client, 7599 IInputContext inputContext) { 7600 if (client == null) throw new IllegalArgumentException("null client"); 7601 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7602 Session session = new Session(this, client, inputContext); 7603 return session; 7604 } 7605 7606 @Override 7607 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7608 synchronized (mWindowMap) { 7609 // The focus for the client is the window immediately below 7610 // where we would place the input method window. 7611 int idx = findDesiredInputMethodWindowIndexLocked(false); 7612 if (idx > 0) { 7613 // TODO(multidisplay): IMEs are only supported on the default display. 7614 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 7615 if (DEBUG_INPUT_METHOD) { 7616 Slog.i(TAG, "Desired input method target: " + imFocus); 7617 Slog.i(TAG, "Current focus: " + mCurrentFocus); 7618 Slog.i(TAG, "Last focus: " + mLastFocus); 7619 } 7620 if (imFocus != null) { 7621 // This may be a starting window, in which case we still want 7622 // to count it as okay. 7623 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7624 && imFocus.mAppToken != null) { 7625 // The client has definitely started, so it really should 7626 // have a window in this app token. Let's look for it. 7627 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7628 WindowState w = imFocus.mAppToken.windows.get(i); 7629 if (w != imFocus) { 7630 Log.i(TAG, "Switching to real app window: " + w); 7631 imFocus = w; 7632 break; 7633 } 7634 } 7635 } 7636 if (DEBUG_INPUT_METHOD) { 7637 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7638 if (imFocus.mSession.mClient != null) { 7639 Slog.i(TAG, "IM target client binder: " 7640 + imFocus.mSession.mClient.asBinder()); 7641 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 7642 } 7643 } 7644 if (imFocus.mSession.mClient != null && 7645 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7646 return true; 7647 } 7648 } 7649 } 7650 7651 // Okay, how about this... what is the current focus? 7652 // It seems in some cases we may not have moved the IM 7653 // target window, such as when it was in a pop-up window, 7654 // so let's also look at the current focus. (An example: 7655 // go to Gmail, start searching so the keyboard goes up, 7656 // press home. Sometimes the IME won't go down.) 7657 // Would be nice to fix this more correctly, but it's 7658 // way at the end of a release, and this should be good enough. 7659 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 7660 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7661 return true; 7662 } 7663 } 7664 return false; 7665 } 7666 7667 @Override 7668 public void getInitialDisplaySize(int displayId, Point size) { 7669 synchronized (mWindowMap) { 7670 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7671 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7672 synchronized(displayContent.mDisplaySizeLock) { 7673 size.x = displayContent.mInitialDisplayWidth; 7674 size.y = displayContent.mInitialDisplayHeight; 7675 } 7676 } 7677 } 7678 } 7679 7680 @Override 7681 public void getBaseDisplaySize(int displayId, Point size) { 7682 synchronized (mWindowMap) { 7683 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7684 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7685 synchronized(displayContent.mDisplaySizeLock) { 7686 size.x = displayContent.mBaseDisplayWidth; 7687 size.y = displayContent.mBaseDisplayHeight; 7688 } 7689 } 7690 } 7691 } 7692 7693 @Override 7694 public void setForcedDisplaySize(int displayId, int width, int height) { 7695 if (mContext.checkCallingOrSelfPermission( 7696 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7697 PackageManager.PERMISSION_GRANTED) { 7698 throw new SecurityException("Must hold permission " + 7699 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7700 } 7701 if (displayId != Display.DEFAULT_DISPLAY) { 7702 throw new IllegalArgumentException("Can only set the default display"); 7703 } 7704 final long ident = Binder.clearCallingIdentity(); 7705 try { 7706 synchronized(mWindowMap) { 7707 // Set some sort of reasonable bounds on the size of the display that we 7708 // will try to emulate. 7709 final int MIN_WIDTH = 200; 7710 final int MIN_HEIGHT = 200; 7711 final int MAX_SCALE = 2; 7712 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7713 if (displayContent != null) { 7714 width = Math.min(Math.max(width, MIN_WIDTH), 7715 displayContent.mInitialDisplayWidth * MAX_SCALE); 7716 height = Math.min(Math.max(height, MIN_HEIGHT), 7717 displayContent.mInitialDisplayHeight * MAX_SCALE); 7718 setForcedDisplaySizeLocked(displayContent, width, height); 7719 Settings.Global.putString(mContext.getContentResolver(), 7720 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 7721 } 7722 } 7723 } finally { 7724 Binder.restoreCallingIdentity(ident); 7725 } 7726 } 7727 7728 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 7729 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 7730 Settings.Global.DISPLAY_SIZE_FORCED); 7731 if (sizeStr == null || sizeStr.length() == 0) { 7732 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 7733 } 7734 if (sizeStr != null && sizeStr.length() > 0) { 7735 final int pos = sizeStr.indexOf(','); 7736 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 7737 int width, height; 7738 try { 7739 width = Integer.parseInt(sizeStr.substring(0, pos)); 7740 height = Integer.parseInt(sizeStr.substring(pos+1)); 7741 synchronized(displayContent.mDisplaySizeLock) { 7742 if (displayContent.mBaseDisplayWidth != width 7743 || displayContent.mBaseDisplayHeight != height) { 7744 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 7745 displayContent.mBaseDisplayWidth = width; 7746 displayContent.mBaseDisplayHeight = height; 7747 } 7748 } 7749 } catch (NumberFormatException ex) { 7750 } 7751 } 7752 } 7753 String densityStr = Settings.Global.getString(mContext.getContentResolver(), 7754 Settings.Global.DISPLAY_DENSITY_FORCED); 7755 if (densityStr == null || densityStr.length() == 0) { 7756 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 7757 } 7758 if (densityStr != null && densityStr.length() > 0) { 7759 int density; 7760 try { 7761 density = Integer.parseInt(densityStr); 7762 synchronized(displayContent.mDisplaySizeLock) { 7763 if (displayContent.mBaseDisplayDensity != density) { 7764 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 7765 displayContent.mBaseDisplayDensity = density; 7766 } 7767 } 7768 } catch (NumberFormatException ex) { 7769 } 7770 } 7771 } 7772 7773 // displayContent must not be null 7774 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 7775 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7776 7777 synchronized(displayContent.mDisplaySizeLock) { 7778 displayContent.mBaseDisplayWidth = width; 7779 displayContent.mBaseDisplayHeight = height; 7780 } 7781 reconfigureDisplayLocked(displayContent); 7782 } 7783 7784 @Override 7785 public void clearForcedDisplaySize(int displayId) { 7786 if (mContext.checkCallingOrSelfPermission( 7787 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7788 PackageManager.PERMISSION_GRANTED) { 7789 throw new SecurityException("Must hold permission " + 7790 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7791 } 7792 if (displayId != Display.DEFAULT_DISPLAY) { 7793 throw new IllegalArgumentException("Can only set the default display"); 7794 } 7795 final long ident = Binder.clearCallingIdentity(); 7796 try { 7797 synchronized(mWindowMap) { 7798 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7799 if (displayContent != null) { 7800 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 7801 displayContent.mInitialDisplayHeight); 7802 Settings.Global.putString(mContext.getContentResolver(), 7803 Settings.Global.DISPLAY_SIZE_FORCED, ""); 7804 } 7805 } 7806 } finally { 7807 Binder.restoreCallingIdentity(ident); 7808 } 7809 } 7810 7811 @Override 7812 public int getInitialDisplayDensity(int displayId) { 7813 synchronized (mWindowMap) { 7814 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7815 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7816 synchronized(displayContent.mDisplaySizeLock) { 7817 return displayContent.mInitialDisplayDensity; 7818 } 7819 } 7820 } 7821 return -1; 7822 } 7823 7824 @Override 7825 public int getBaseDisplayDensity(int displayId) { 7826 synchronized (mWindowMap) { 7827 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7828 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7829 synchronized(displayContent.mDisplaySizeLock) { 7830 return displayContent.mBaseDisplayDensity; 7831 } 7832 } 7833 } 7834 return -1; 7835 } 7836 7837 @Override 7838 public void setForcedDisplayDensity(int displayId, int density) { 7839 if (mContext.checkCallingOrSelfPermission( 7840 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7841 PackageManager.PERMISSION_GRANTED) { 7842 throw new SecurityException("Must hold permission " + 7843 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7844 } 7845 if (displayId != Display.DEFAULT_DISPLAY) { 7846 throw new IllegalArgumentException("Can only set the default display"); 7847 } 7848 final long ident = Binder.clearCallingIdentity(); 7849 try { 7850 synchronized(mWindowMap) { 7851 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7852 if (displayContent != null) { 7853 setForcedDisplayDensityLocked(displayContent, density); 7854 Settings.Global.putString(mContext.getContentResolver(), 7855 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 7856 } 7857 } 7858 } finally { 7859 Binder.restoreCallingIdentity(ident); 7860 } 7861 } 7862 7863 // displayContent must not be null 7864 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 7865 Slog.i(TAG, "Using new display density: " + density); 7866 7867 synchronized(displayContent.mDisplaySizeLock) { 7868 displayContent.mBaseDisplayDensity = density; 7869 } 7870 reconfigureDisplayLocked(displayContent); 7871 } 7872 7873 @Override 7874 public void clearForcedDisplayDensity(int displayId) { 7875 if (mContext.checkCallingOrSelfPermission( 7876 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7877 PackageManager.PERMISSION_GRANTED) { 7878 throw new SecurityException("Must hold permission " + 7879 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7880 } 7881 if (displayId != Display.DEFAULT_DISPLAY) { 7882 throw new IllegalArgumentException("Can only set the default display"); 7883 } 7884 final long ident = Binder.clearCallingIdentity(); 7885 try { 7886 synchronized(mWindowMap) { 7887 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7888 if (displayContent != null) { 7889 setForcedDisplayDensityLocked(displayContent, 7890 displayContent.mInitialDisplayDensity); 7891 Settings.Global.putString(mContext.getContentResolver(), 7892 Settings.Global.DISPLAY_DENSITY_FORCED, ""); 7893 } 7894 } 7895 } finally { 7896 Binder.restoreCallingIdentity(ident); 7897 } 7898 } 7899 7900 // displayContent must not be null 7901 private void reconfigureDisplayLocked(DisplayContent displayContent) { 7902 // TODO: Multidisplay: for now only use with default display. 7903 configureDisplayPolicyLocked(displayContent); 7904 displayContent.layoutNeeded = true; 7905 7906 boolean configChanged = updateOrientationFromAppTokensLocked(false); 7907 mTempConfiguration.setToDefaults(); 7908 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 7909 if (computeScreenConfigurationLocked(mTempConfiguration)) { 7910 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 7911 configChanged = true; 7912 } 7913 } 7914 7915 if (configChanged) { 7916 mWaitingForConfig = true; 7917 startFreezingDisplayLocked(false, 0, 0); 7918 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 7919 } 7920 7921 performLayoutAndPlaceSurfacesLocked(); 7922 } 7923 7924 private void configureDisplayPolicyLocked(DisplayContent displayContent) { 7925 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 7926 displayContent.mBaseDisplayWidth, 7927 displayContent.mBaseDisplayHeight, 7928 displayContent.mBaseDisplayDensity); 7929 7930 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7931 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 7932 displayInfo.overscanLeft, displayInfo.overscanTop, 7933 displayInfo.overscanRight, displayInfo.overscanBottom); 7934 } 7935 7936 @Override 7937 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 7938 if (mContext.checkCallingOrSelfPermission( 7939 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7940 PackageManager.PERMISSION_GRANTED) { 7941 throw new SecurityException("Must hold permission " + 7942 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7943 } 7944 final long ident = Binder.clearCallingIdentity(); 7945 try { 7946 synchronized(mWindowMap) { 7947 DisplayContent displayContent = getDisplayContentLocked(displayId); 7948 if (displayContent != null) { 7949 setOverscanLocked(displayContent, left, top, right, bottom); 7950 } 7951 } 7952 } finally { 7953 Binder.restoreCallingIdentity(ident); 7954 } 7955 } 7956 7957 private void setOverscanLocked(DisplayContent displayContent, 7958 int left, int top, int right, int bottom) { 7959 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7960 synchronized (displayContent.mDisplaySizeLock) { 7961 displayInfo.overscanLeft = left; 7962 displayInfo.overscanTop = top; 7963 displayInfo.overscanRight = right; 7964 displayInfo.overscanBottom = bottom; 7965 } 7966 7967 mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom); 7968 mDisplaySettings.writeSettingsLocked(); 7969 7970 reconfigureDisplayLocked(displayContent); 7971 } 7972 7973 // ------------------------------------------------------------- 7974 // Internals 7975 // ------------------------------------------------------------- 7976 7977 final WindowState windowForClientLocked(Session session, IWindow client, 7978 boolean throwOnError) { 7979 return windowForClientLocked(session, client.asBinder(), throwOnError); 7980 } 7981 7982 final WindowState windowForClientLocked(Session session, IBinder client, 7983 boolean throwOnError) { 7984 WindowState win = mWindowMap.get(client); 7985 if (localLOGV) Slog.v( 7986 TAG, "Looking up client " + client + ": " + win); 7987 if (win == null) { 7988 RuntimeException ex = new IllegalArgumentException( 7989 "Requested window " + client + " does not exist"); 7990 if (throwOnError) { 7991 throw ex; 7992 } 7993 Slog.w(TAG, "Failed looking up window", ex); 7994 return null; 7995 } 7996 if (session != null && win.mSession != session) { 7997 RuntimeException ex = new IllegalArgumentException( 7998 "Requested window " + client + " is in session " + 7999 win.mSession + ", not " + session); 8000 if (throwOnError) { 8001 throw ex; 8002 } 8003 Slog.w(TAG, "Failed looking up window", ex); 8004 return null; 8005 } 8006 8007 return win; 8008 } 8009 8010 final void rebuildAppWindowListLocked() { 8011 rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); 8012 } 8013 8014 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 8015 final WindowList windows = displayContent.getWindowList(); 8016 int NW = windows.size(); 8017 int i; 8018 int lastBelow = -1; 8019 int numRemoved = 0; 8020 8021 if (mRebuildTmp.length < NW) { 8022 mRebuildTmp = new WindowState[NW+10]; 8023 } 8024 8025 // First remove all existing app windows. 8026 i=0; 8027 while (i < NW) { 8028 WindowState w = windows.get(i); 8029 if (w.mAppToken != null) { 8030 WindowState win = windows.remove(i); 8031 win.mRebuilding = true; 8032 mRebuildTmp[numRemoved] = win; 8033 mWindowsChanged = true; 8034 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win); 8035 NW--; 8036 numRemoved++; 8037 continue; 8038 } else if (lastBelow == i-1) { 8039 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8040 lastBelow = i; 8041 } 8042 } 8043 i++; 8044 } 8045 8046 // Keep whatever windows were below the app windows still below, 8047 // by skipping them. 8048 lastBelow++; 8049 i = lastBelow; 8050 8051 // First add all of the exiting app tokens... these are no longer 8052 // in the main app list, but still have windows shown. We put them 8053 // in the back because now that the animation is over we no longer 8054 // will care about them. 8055 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 8056 final int numStacks = stacks.size(); 8057 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8058 AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens; 8059 int NT = exitingAppTokens.size(); 8060 for (int j = 0; j < NT; j++) { 8061 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 8062 } 8063 } 8064 8065 // And add in the still active app tokens in Z order. 8066 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8067 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8068 final int numTasks = tasks.size(); 8069 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 8070 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8071 final int numTokens = tokens.size(); 8072 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 8073 final AppWindowToken wtoken = tokens.get(tokenNdx); 8074 if (wtoken.mDeferRemoval) { 8075 continue; 8076 } 8077 i = reAddAppWindowsLocked(displayContent, i, wtoken); 8078 } 8079 } 8080 } 8081 8082 i -= lastBelow; 8083 if (i != numRemoved) { 8084 Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " + 8085 numRemoved + " windows but added " + i, 8086 new RuntimeException("here").fillInStackTrace()); 8087 for (i=0; i<numRemoved; i++) { 8088 WindowState ws = mRebuildTmp[i]; 8089 if (ws.mRebuilding) { 8090 StringWriter sw = new StringWriter(); 8091 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 8092 ws.dump(pw, "", true); 8093 pw.flush(); 8094 Slog.w(TAG, "This window was lost: " + ws); 8095 Slog.w(TAG, sw.toString()); 8096 ws.mWinAnimator.destroySurfaceLocked(); 8097 } 8098 } 8099 Slog.w(TAG, "Current app token list:"); 8100 dumpAppTokensLocked(); 8101 Slog.w(TAG, "Final window list:"); 8102 dumpWindowsLocked(); 8103 } 8104 } 8105 8106 private final void assignLayersLocked(WindowList windows) { 8107 int N = windows.size(); 8108 int curBaseLayer = 0; 8109 int curLayer = 0; 8110 int i; 8111 8112 if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows, 8113 new RuntimeException("here").fillInStackTrace()); 8114 8115 boolean anyLayerChanged = false; 8116 8117 for (i=0; i<N; i++) { 8118 final WindowState w = windows.get(i); 8119 final WindowStateAnimator winAnimator = w.mWinAnimator; 8120 boolean layerChanged = false; 8121 int oldLayer = w.mLayer; 8122 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 8123 || (i > 0 && w.mIsWallpaper)) { 8124 curLayer += WINDOW_LAYER_MULTIPLIER; 8125 w.mLayer = curLayer; 8126 } else { 8127 curBaseLayer = curLayer = w.mBaseLayer; 8128 w.mLayer = curLayer; 8129 } 8130 if (w.mLayer != oldLayer) { 8131 layerChanged = true; 8132 anyLayerChanged = true; 8133 } 8134 final AppWindowToken wtoken = w.mAppToken; 8135 oldLayer = winAnimator.mAnimLayer; 8136 if (w.mTargetAppToken != null) { 8137 winAnimator.mAnimLayer = 8138 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 8139 } else if (wtoken != null) { 8140 winAnimator.mAnimLayer = 8141 w.mLayer + wtoken.mAppAnimator.animLayerAdjustment; 8142 } else { 8143 winAnimator.mAnimLayer = w.mLayer; 8144 } 8145 if (w.mIsImWindow) { 8146 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 8147 } else if (w.mIsWallpaper) { 8148 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 8149 } 8150 if (winAnimator.mAnimLayer != oldLayer) { 8151 layerChanged = true; 8152 anyLayerChanged = true; 8153 } 8154 if (layerChanged && w.getStack().isDimming(winAnimator)) { 8155 // Force an animation pass just to update the mDimLayer layer. 8156 scheduleAnimationLocked(); 8157 } 8158 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 8159 + "mBase=" + w.mBaseLayer 8160 + " mLayer=" + w.mLayer 8161 + (wtoken == null ? 8162 "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment) 8163 + " =mAnimLayer=" + winAnimator.mAnimLayer); 8164 //System.out.println( 8165 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 8166 } 8167 8168 //TODO (multidisplay): Magnification is supported only for the default display. 8169 if (mDisplayMagnifier != null && anyLayerChanged 8170 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) { 8171 mDisplayMagnifier.onWindowLayersChangedLocked(); 8172 } 8173 } 8174 8175 private final void performLayoutAndPlaceSurfacesLocked() { 8176 int loopCount = 6; 8177 do { 8178 mTraversalScheduled = false; 8179 performLayoutAndPlaceSurfacesLockedLoop(); 8180 mH.removeMessages(H.DO_TRAVERSAL); 8181 loopCount--; 8182 } while (mTraversalScheduled && loopCount > 0); 8183 mInnerFields.mWallpaperActionPending = false; 8184 } 8185 8186 private boolean mInLayout = false; 8187 private final void performLayoutAndPlaceSurfacesLockedLoop() { 8188 if (mInLayout) { 8189 if (DEBUG) { 8190 throw new RuntimeException("Recursive call!"); 8191 } 8192 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 8193 + Debug.getCallers(3)); 8194 return; 8195 } 8196 8197 if (mWaitingForConfig) { 8198 // Our configuration has changed (most likely rotation), but we 8199 // don't yet have the complete configuration to report to 8200 // applications. Don't do any window layout until we have it. 8201 return; 8202 } 8203 8204 if (!mDisplayReady) { 8205 // Not yet initialized, nothing to do. 8206 return; 8207 } 8208 8209 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 8210 mInLayout = true; 8211 boolean recoveringMemory = false; 8212 8213 try { 8214 if (mForceRemoves != null) { 8215 recoveringMemory = true; 8216 // Wait a little bit for things to settle down, and off we go. 8217 for (int i=0; i<mForceRemoves.size(); i++) { 8218 WindowState ws = mForceRemoves.get(i); 8219 Slog.i(TAG, "Force removing: " + ws); 8220 removeWindowInnerLocked(ws.mSession, ws); 8221 } 8222 mForceRemoves = null; 8223 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 8224 Object tmp = new Object(); 8225 synchronized (tmp) { 8226 try { 8227 tmp.wait(250); 8228 } catch (InterruptedException e) { 8229 } 8230 } 8231 } 8232 } catch (RuntimeException e) { 8233 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 8234 } 8235 8236 try { 8237 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 8238 8239 mInLayout = false; 8240 8241 if (needsLayout()) { 8242 if (++mLayoutRepeatCount < 6) { 8243 requestTraversalLocked(); 8244 } else { 8245 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 8246 mLayoutRepeatCount = 0; 8247 } 8248 } else { 8249 mLayoutRepeatCount = 0; 8250 } 8251 8252 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 8253 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 8254 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE); 8255 } 8256 } catch (RuntimeException e) { 8257 mInLayout = false; 8258 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 8259 } 8260 8261 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 8262 } 8263 8264 private final void performLayoutLockedInner(final DisplayContent displayContent, 8265 boolean initial, boolean updateInputWindows) { 8266 if (!displayContent.layoutNeeded) { 8267 return; 8268 } 8269 displayContent.layoutNeeded = false; 8270 WindowList windows = displayContent.getWindowList(); 8271 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 8272 8273 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8274 final int dw = displayInfo.logicalWidth; 8275 final int dh = displayInfo.logicalHeight; 8276 8277 final int NFW = mFakeWindows.size(); 8278 for (int i=0; i<NFW; i++) { 8279 mFakeWindows.get(i).layout(dw, dh); 8280 } 8281 8282 final int N = windows.size(); 8283 int i; 8284 8285 if (DEBUG_LAYOUT) { 8286 Slog.v(TAG, "-------------------------------------"); 8287 Slog.v(TAG, "performLayout: needed=" 8288 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 8289 } 8290 8291 WindowStateAnimator universeBackground = null; 8292 8293 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); 8294 if (isDefaultDisplay) { 8295 // Not needed on non-default displays. 8296 mSystemDecorLayer = mPolicy.getSystemDecorLayerLw(); 8297 mScreenRect.set(0, 0, dw, dh); 8298 } 8299 8300 mPolicy.getContentRectLw(mTmpContentRect); 8301 displayContent.resize(mTmpContentRect); 8302 8303 int seq = mLayoutSeq+1; 8304 if (seq < 0) seq = 0; 8305 mLayoutSeq = seq; 8306 8307 boolean behindDream = false; 8308 8309 // First perform layout of any root windows (not attached 8310 // to another window). 8311 int topAttached = -1; 8312 for (i = N-1; i >= 0; i--) { 8313 final WindowState win = windows.get(i); 8314 8315 // Don't do layout of a window if it is not visible, or 8316 // soon won't be visible, to avoid wasting time and funky 8317 // changes while a window is animating away. 8318 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) 8319 || win.isGoneForLayoutLw(); 8320 8321 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 8322 Slog.v(TAG, "1ST PASS " + win 8323 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 8324 + " mLayoutAttached=" + win.mLayoutAttached 8325 + " screen changed=" + win.isConfigChanged()); 8326 final AppWindowToken atoken = win.mAppToken; 8327 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 8328 + win.mViewVisibility + " mRelayoutCalled=" 8329 + win.mRelayoutCalled + " hidden=" 8330 + win.mRootToken.hidden + " hiddenRequested=" 8331 + (atoken != null && atoken.hiddenRequested) 8332 + " mAttachedHidden=" + win.mAttachedHidden); 8333 else Slog.v(TAG, " VIS: mViewVisibility=" 8334 + win.mViewVisibility + " mRelayoutCalled=" 8335 + win.mRelayoutCalled + " hidden=" 8336 + win.mRootToken.hidden + " hiddenRequested=" 8337 + (atoken != null && atoken.hiddenRequested) 8338 + " mAttachedHidden=" + win.mAttachedHidden); 8339 } 8340 8341 // If this view is GONE, then skip it -- keep the current 8342 // frame, and let the caller know so they can ignore it 8343 // if they want. (We do the normal layout for INVISIBLE 8344 // windows, since that means "perform layout as normal, 8345 // just don't display"). 8346 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 8347 || ((win.isConfigChanged() || win.setInsetsChanged()) && 8348 (win.mAttrs.type == TYPE_KEYGUARD || 8349 win.mAppToken != null && win.mAppToken.layoutConfigChanges)) 8350 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8351 if (!win.mLayoutAttached) { 8352 if (initial) { 8353 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8354 win.mContentChanged = false; 8355 } 8356 if (win.mAttrs.type == TYPE_DREAM) { 8357 // Don't layout windows behind a dream, so that if it 8358 // does stuff like hide the status bar we won't get a 8359 // bad transition when it goes away. 8360 behindDream = true; 8361 } 8362 win.mLayoutNeeded = false; 8363 win.prelayout(); 8364 mPolicy.layoutWindowLw(win, win.mAttrs, null); 8365 win.mLayoutSeq = seq; 8366 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8367 + win.mFrame + " mContainingFrame=" 8368 + win.mContainingFrame + " mDisplayFrame=" 8369 + win.mDisplayFrame); 8370 } else { 8371 if (topAttached < 0) topAttached = i; 8372 } 8373 } 8374 if (win.mViewVisibility == View.VISIBLE 8375 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 8376 && universeBackground == null) { 8377 universeBackground = win.mWinAnimator; 8378 } 8379 } 8380 8381 if (mAnimator.mUniverseBackground != universeBackground) { 8382 mFocusMayChange = true; 8383 mAnimator.mUniverseBackground = universeBackground; 8384 } 8385 8386 boolean attachedBehindDream = false; 8387 8388 // Now perform layout of attached windows, which usually 8389 // depend on the position of the window they are attached to. 8390 // XXX does not deal with windows that are attached to windows 8391 // that are themselves attached. 8392 for (i = topAttached; i >= 0; i--) { 8393 final WindowState win = windows.get(i); 8394 8395 if (win.mLayoutAttached) { 8396 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 8397 + " mHaveFrame=" + win.mHaveFrame 8398 + " mViewVisibility=" + win.mViewVisibility 8399 + " mRelayoutCalled=" + win.mRelayoutCalled); 8400 // If this view is GONE, then skip it -- keep the current 8401 // frame, and let the caller know so they can ignore it 8402 // if they want. (We do the normal layout for INVISIBLE 8403 // windows, since that means "perform layout as normal, 8404 // just don't display"). 8405 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) { 8406 continue; 8407 } 8408 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8409 || !win.mHaveFrame || win.mLayoutNeeded) { 8410 if (initial) { 8411 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8412 win.mContentChanged = false; 8413 } 8414 win.mLayoutNeeded = false; 8415 win.prelayout(); 8416 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 8417 win.mLayoutSeq = seq; 8418 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8419 + win.mFrame + " mContainingFrame=" 8420 + win.mContainingFrame + " mDisplayFrame=" 8421 + win.mDisplayFrame); 8422 } 8423 } else if (win.mAttrs.type == TYPE_DREAM) { 8424 // Don't layout windows behind a dream, so that if it 8425 // does stuff like hide the status bar we won't get a 8426 // bad transition when it goes away. 8427 attachedBehindDream = behindDream; 8428 } 8429 } 8430 8431 // Window frames may have changed. Tell the input dispatcher about it. 8432 mInputMonitor.setUpdateInputWindowsNeededLw(); 8433 if (updateInputWindows) { 8434 mInputMonitor.updateInputWindowsLw(false /*force*/); 8435 } 8436 8437 mPolicy.finishLayoutLw(); 8438 } 8439 8440 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8441 // If the screen is currently frozen or off, then keep 8442 // it frozen/off until this window draws at its new 8443 // orientation. 8444 if (!okToDisplay()) { 8445 if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w); 8446 w.mOrientationChanging = true; 8447 w.mLastFreezeDuration = 0; 8448 mInnerFields.mOrientationChangeComplete = false; 8449 if (!mWindowsFreezingScreen) { 8450 mWindowsFreezingScreen = true; 8451 // XXX should probably keep timeout from 8452 // when we first froze the display. 8453 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8454 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 8455 WINDOW_FREEZE_TIMEOUT_DURATION); 8456 } 8457 } 8458 } 8459 8460 /** 8461 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8462 * @param windows List of windows on default display. 8463 * @return bitmap indicating if another pass through layout must be made. 8464 */ 8465 public int handleAppTransitionReadyLocked(WindowList windows) { 8466 int changes = 0; 8467 int i; 8468 int NN = mOpeningApps.size(); 8469 boolean goodToGo = true; 8470 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8471 "Checking " + NN + " opening apps (frozen=" 8472 + mDisplayFrozen + " timeout=" 8473 + mAppTransition.isTimeout() + ")..."); 8474 if (!mDisplayFrozen && !mAppTransition.isTimeout()) { 8475 // If the display isn't frozen, wait to do anything until 8476 // all of the apps are ready. Otherwise just go because 8477 // we'll unfreeze the display when everyone is ready. 8478 for (i=0; i<NN && goodToGo; i++) { 8479 AppWindowToken wtoken = mOpeningApps.get(i); 8480 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8481 "Check opening app=" + wtoken + ": allDrawn=" 8482 + wtoken.allDrawn + " startingDisplayed=" 8483 + wtoken.startingDisplayed + " startingMoved=" 8484 + wtoken.startingMoved); 8485 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8486 && !wtoken.startingMoved) { 8487 goodToGo = false; 8488 } 8489 } 8490 } 8491 if (goodToGo) { 8492 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8493 int transit = mAppTransition.getAppTransition(); 8494 if (mSkipAppTransitionAnimation) { 8495 transit = AppTransition.TRANSIT_UNSET; 8496 } 8497 mAppTransition.goodToGo(); 8498 mStartingIconInTransition = false; 8499 mSkipAppTransitionAnimation = false; 8500 8501 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8502 8503 rebuildAppWindowListLocked(); 8504 8505 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8506 WindowState oldWallpaper = 8507 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8508 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8509 ? null : mWallpaperTarget; 8510 8511 mInnerFields.mWallpaperMayChange = false; 8512 8513 // The top-most window will supply the layout params, 8514 // and we will determine it below. 8515 LayoutParams animLp = null; 8516 int bestAnimLayer = -1; 8517 boolean fullscreenAnim = false; 8518 8519 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8520 "New wallpaper target=" + mWallpaperTarget 8521 + ", oldWallpaper=" + oldWallpaper 8522 + ", lower target=" + mLowerWallpaperTarget 8523 + ", upper target=" + mUpperWallpaperTarget); 8524 8525 boolean openingAppHasWallpaper = false; 8526 boolean closingAppHasWallpaper = false; 8527 final AppWindowToken lowerWallpaperAppToken; 8528 final AppWindowToken upperWallpaperAppToken; 8529 if (mLowerWallpaperTarget == null) { 8530 lowerWallpaperAppToken = upperWallpaperAppToken = null; 8531 } else { 8532 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken; 8533 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken; 8534 } 8535 8536 // Do a first pass through the tokens for two 8537 // things: 8538 // (1) Determine if both the closing and opening 8539 // app token sets are wallpaper targets, in which 8540 // case special animations are needed 8541 // (since the wallpaper needs to stay static 8542 // behind them). 8543 // (2) Find the layout params of the top-most 8544 // application window in the tokens, which is 8545 // what will control the animation theme. 8546 final int NC = mClosingApps.size(); 8547 NN = NC + mOpeningApps.size(); 8548 for (i=0; i<NN; i++) { 8549 final AppWindowToken wtoken; 8550 if (i < NC) { 8551 wtoken = mClosingApps.get(i); 8552 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8553 closingAppHasWallpaper = true; 8554 } 8555 } else { 8556 wtoken = mOpeningApps.get(i - NC); 8557 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8558 openingAppHasWallpaper = true; 8559 } 8560 } 8561 8562 if (wtoken.appFullscreen) { 8563 WindowState ws = wtoken.findMainWindow(); 8564 if (ws != null) { 8565 animLp = ws.mAttrs; 8566 bestAnimLayer = ws.mLayer; 8567 fullscreenAnim = true; 8568 } 8569 } else if (!fullscreenAnim) { 8570 WindowState ws = wtoken.findMainWindow(); 8571 if (ws != null) { 8572 if (ws.mLayer > bestAnimLayer) { 8573 animLp = ws.mAttrs; 8574 bestAnimLayer = ws.mLayer; 8575 } 8576 } 8577 } 8578 } 8579 8580 mAnimateWallpaperWithTarget = false; 8581 if (closingAppHasWallpaper && openingAppHasWallpaper) { 8582 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!"); 8583 switch (transit) { 8584 case AppTransition.TRANSIT_ACTIVITY_OPEN: 8585 case AppTransition.TRANSIT_TASK_OPEN: 8586 case AppTransition.TRANSIT_TASK_TO_FRONT: 8587 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN; 8588 break; 8589 case AppTransition.TRANSIT_ACTIVITY_CLOSE: 8590 case AppTransition.TRANSIT_TASK_CLOSE: 8591 case AppTransition.TRANSIT_TASK_TO_BACK: 8592 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; 8593 break; 8594 } 8595 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); 8596 } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty() 8597 && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 8598 // We are transitioning from an activity with 8599 // a wallpaper to one without. 8600 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; 8601 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8602 "New transit away from wallpaper: " + transit); 8603 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) { 8604 // We are transitioning from an activity without 8605 // a wallpaper to now showing the wallpaper 8606 transit = AppTransition.TRANSIT_WALLPAPER_OPEN; 8607 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8608 "New transit into wallpaper: " + transit); 8609 } else { 8610 mAnimateWallpaperWithTarget = true; 8611 } 8612 8613 // If all closing windows are obscured, then there is 8614 // no need to do an animation. This is the case, for 8615 // example, when this transition is being done behind 8616 // the lock screen. 8617 if (!mPolicy.allowAppAnimationsLw()) { 8618 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8619 "Animations disallowed by keyguard or dream."); 8620 animLp = null; 8621 } 8622 8623 AppWindowToken topOpeningApp = null; 8624 int topOpeningLayer = 0; 8625 8626 NN = mOpeningApps.size(); 8627 for (i=0; i<NN; i++) { 8628 AppWindowToken wtoken = mOpeningApps.get(i); 8629 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 8630 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 8631 appAnimator.clearThumbnail(); 8632 wtoken.inPendingTransaction = false; 8633 appAnimator.animation = null; 8634 setTokenVisibilityLocked(wtoken, animLp, true, transit, false); 8635 wtoken.updateReportedVisibilityLocked(); 8636 wtoken.waitingToShow = false; 8637 8638 appAnimator.mAllAppWinAnimators.clear(); 8639 final int N = wtoken.allAppWindows.size(); 8640 for (int j = 0; j < N; j++) { 8641 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 8642 } 8643 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 8644 8645 if (animLp != null) { 8646 int layer = -1; 8647 for (int j=0; j<wtoken.windows.size(); j++) { 8648 WindowState win = wtoken.windows.get(j); 8649 if (win.mWinAnimator.mAnimLayer > layer) { 8650 layer = win.mWinAnimator.mAnimLayer; 8651 } 8652 } 8653 if (topOpeningApp == null || layer > topOpeningLayer) { 8654 topOpeningApp = wtoken; 8655 topOpeningLayer = layer; 8656 } 8657 } 8658 } 8659 NN = mClosingApps.size(); 8660 for (i=0; i<NN; i++) { 8661 AppWindowToken wtoken = mClosingApps.get(i); 8662 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken); 8663 wtoken.mAppAnimator.clearThumbnail(); 8664 wtoken.inPendingTransaction = false; 8665 wtoken.mAppAnimator.animation = null; 8666 setTokenVisibilityLocked(wtoken, animLp, false, transit, false); 8667 wtoken.updateReportedVisibilityLocked(); 8668 wtoken.waitingToHide = false; 8669 // Force the allDrawn flag, because we want to start 8670 // this guy's animations regardless of whether it's 8671 // gotten drawn. 8672 wtoken.allDrawn = true; 8673 wtoken.deferClearAllDrawn = false; 8674 } 8675 8676 AppWindowAnimator appAnimator = 8677 topOpeningApp == null ? null : topOpeningApp.mAppAnimator; 8678 Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail(); 8679 if (nextAppTransitionThumbnail != null && appAnimator != null 8680 && appAnimator.animation != null) { 8681 // This thumbnail animation is very special, we need to have 8682 // an extra surface with the thumbnail included with the animation. 8683 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(), 8684 nextAppTransitionThumbnail.getHeight()); 8685 try { 8686 // TODO(multi-display): support other displays 8687 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8688 final Display display = displayContent.getDisplay(); 8689 SurfaceControl surfaceControl = new SurfaceControl(mFxSession, 8690 "thumbnail anim", 8691 dirty.width(), dirty.height(), 8692 PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 8693 surfaceControl.setLayerStack(display.getLayerStack()); 8694 appAnimator.thumbnail = surfaceControl; 8695 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE"); 8696 Surface drawSurface = new Surface(); 8697 drawSurface.copyFrom(surfaceControl); 8698 Canvas c = drawSurface.lockCanvas(dirty); 8699 c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null); 8700 drawSurface.unlockCanvasAndPost(c); 8701 drawSurface.release(); 8702 appAnimator.thumbnailLayer = topOpeningLayer; 8703 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 8704 Animation anim = mAppTransition.createThumbnailAnimationLocked( 8705 transit, true, true, displayInfo.appWidth, displayInfo.appHeight); 8706 appAnimator.thumbnailAnimation = anim; 8707 anim.restrictDuration(MAX_ANIMATION_DURATION); 8708 anim.scaleCurrentDuration(mTransitionAnimationScale); 8709 Point p = new Point(); 8710 mAppTransition.getStartingPoint(p); 8711 appAnimator.thumbnailX = p.x; 8712 appAnimator.thumbnailY = p.y; 8713 } catch (OutOfResourcesException e) { 8714 Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width() 8715 + " h=" + dirty.height(), e); 8716 appAnimator.clearThumbnail(); 8717 } 8718 } 8719 8720 mAppTransition.postAnimationCallback(); 8721 mAppTransition.clear(); 8722 8723 mOpeningApps.clear(); 8724 mClosingApps.clear(); 8725 8726 // This has changed the visibility of windows, so perform 8727 // a new layout to get them all up-to-date. 8728 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT 8729 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 8730 getDefaultDisplayContentLocked().layoutNeeded = true; 8731 8732 // TODO(multidisplay): IMEs are only supported on the default display. 8733 if (windows == getDefaultWindowListLocked() 8734 && !moveInputMethodWindowsIfNeededLocked(true)) { 8735 assignLayersLocked(windows); 8736 } 8737 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/); 8738 mFocusMayChange = false; 8739 } 8740 8741 return changes; 8742 } 8743 8744 /** 8745 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8746 * @return bitmap indicating if another pass through layout must be made. 8747 */ 8748 private int handleAnimatingStoppedAndTransitionLocked() { 8749 int changes = 0; 8750 8751 mAppTransition.setIdle(); 8752 // Restore window app tokens to the ActivityManager views 8753 ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks(); 8754 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 8755 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8756 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 8757 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8758 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 8759 tokens.get(tokenNdx).sendingToBottom = false; 8760 } 8761 } 8762 } 8763 rebuildAppWindowListLocked(); 8764 8765 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8766 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 8767 "Wallpaper layer changed: assigning layers + relayout"); 8768 moveInputMethodWindowsIfNeededLocked(true); 8769 mInnerFields.mWallpaperMayChange = true; 8770 // Since the window list has been rebuilt, focus might 8771 // have to be recomputed since the actual order of windows 8772 // might have changed again. 8773 mFocusMayChange = true; 8774 8775 return changes; 8776 } 8777 8778 private void updateResizingWindows(final WindowState w) { 8779 final WindowStateAnimator winAnimator = w.mWinAnimator; 8780 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { 8781 w.setInsetsChanged(); 8782 boolean configChanged = w.isConfigChanged(); 8783 if (DEBUG_CONFIGURATION && configChanged) { 8784 Slog.v(TAG, "Win " + w + " config changed: " 8785 + mCurConfiguration); 8786 } 8787 if (localLOGV) Slog.v(TAG, "Resizing " + w 8788 + ": configChanged=" + configChanged 8789 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8790 w.mLastFrame.set(w.mFrame); 8791 if (w.mContentInsetsChanged 8792 || w.mVisibleInsetsChanged 8793 || winAnimator.mSurfaceResized 8794 || configChanged) { 8795 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8796 Slog.v(TAG, "Resize reasons for w=" + w + ": " 8797 + " contentInsetsChanged=" + w.mContentInsetsChanged 8798 + " " + w.mContentInsets.toShortString() 8799 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8800 + " " + w.mVisibleInsets.toShortString() 8801 + " surfaceResized=" + winAnimator.mSurfaceResized 8802 + " configChanged=" + configChanged); 8803 } 8804 8805 w.mLastOverscanInsets.set(w.mOverscanInsets); 8806 w.mLastContentInsets.set(w.mContentInsets); 8807 w.mLastVisibleInsets.set(w.mVisibleInsets); 8808 makeWindowFreezingScreenIfNeededLocked(w); 8809 // If the orientation is changing, then we need to 8810 // hold off on unfreezing the display until this 8811 // window has been redrawn; to do that, we need 8812 // to go through the process of getting informed 8813 // by the application when it has finished drawing. 8814 if (w.mOrientationChanging) { 8815 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 8816 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 8817 + w + ", surface " + winAnimator.mSurfaceControl); 8818 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 8819 if (w.mAppToken != null) { 8820 w.mAppToken.allDrawn = false; 8821 w.mAppToken.deferClearAllDrawn = false; 8822 } 8823 } 8824 if (!mResizingWindows.contains(w)) { 8825 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8826 "Resizing window " + w + " to " + winAnimator.mSurfaceW 8827 + "x" + winAnimator.mSurfaceH); 8828 mResizingWindows.add(w); 8829 } 8830 } else if (w.mOrientationChanging) { 8831 if (w.isDrawnLw()) { 8832 if (DEBUG_ORIENTATION) Slog.v(TAG, 8833 "Orientation not waiting for draw in " 8834 + w + ", surface " + winAnimator.mSurfaceControl); 8835 w.mOrientationChanging = false; 8836 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 8837 - mDisplayFreezeTime); 8838 } 8839 } 8840 } 8841 } 8842 8843 /** 8844 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8845 * 8846 * @param w WindowState this method is applied to. 8847 * @param currentTime The time which animations use for calculating transitions. 8848 * @param innerDw Width of app window. 8849 * @param innerDh Height of app window. 8850 */ 8851 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 8852 final int innerDw, final int innerDh) { 8853 final WindowManager.LayoutParams attrs = w.mAttrs; 8854 final int attrFlags = attrs.flags; 8855 final boolean canBeSeen = w.isDisplayedLw(); 8856 final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8857 8858 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8859 // This window completely covers everything behind it, 8860 // so we want to leave all of them as undimmed (for 8861 // performance reasons). 8862 mInnerFields.mObscured = true; 8863 } 8864 8865 if (w.mHasSurface) { 8866 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8867 mInnerFields.mHoldScreen = w.mSession; 8868 } 8869 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 8870 && mInnerFields.mScreenBrightness < 0) { 8871 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 8872 } 8873 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 8874 && mInnerFields.mButtonBrightness < 0) { 8875 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 8876 } 8877 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0 8878 && mInnerFields.mUserActivityTimeout < 0) { 8879 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout; 8880 } 8881 8882 final int type = attrs.type; 8883 if (canBeSeen 8884 && (type == TYPE_SYSTEM_DIALOG 8885 || type == TYPE_RECENTS_OVERLAY 8886 || type == TYPE_KEYGUARD 8887 || type == TYPE_SYSTEM_ERROR)) { 8888 mInnerFields.mSyswin = true; 8889 } 8890 8891 if (canBeSeen) { 8892 // This function assumes that the contents of the default display are 8893 // processed first before secondary displays. 8894 final DisplayContent displayContent = w.getDisplayContent(); 8895 if (displayContent != null && displayContent.isDefaultDisplay) { 8896 // While a dream or keyguard is showing, obscure ordinary application 8897 // content on secondary displays (by forcibly enabling mirroring unless 8898 // there is other content we want to show) but still allow opaque 8899 // keyguard dialogs to be shown. 8900 if (type == TYPE_DREAM || type == TYPE_KEYGUARD) { 8901 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true; 8902 } 8903 mInnerFields.mDisplayHasContent = true; 8904 } else if (displayContent != null && 8905 (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays 8906 || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) { 8907 // Allow full screen keyguard presentation dialogs to be seen. 8908 mInnerFields.mDisplayHasContent = true; 8909 } 8910 } 8911 } 8912 } 8913 8914 private void handleFlagDimBehind(WindowState w) { 8915 final WindowManager.LayoutParams attrs = w.mAttrs; 8916 if ((attrs.flags & FLAG_DIM_BEHIND) != 0 8917 && w.isDisplayedLw() 8918 && !w.mExiting) { 8919 final WindowStateAnimator winAnimator = w.mWinAnimator; 8920 final TaskStack stack = w.getStack(); 8921 stack.setDimmingTag(); 8922 if (!stack.isDimming(winAnimator)) { 8923 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming."); 8924 stack.startDimmingIfNeeded(winAnimator); 8925 } 8926 } 8927 } 8928 8929 private void updateAllDrawnLocked(DisplayContent displayContent) { 8930 // See if any windows have been drawn, so they (and others 8931 // associated with them) can now be shown. 8932 ArrayList<TaskStack> stacks = displayContent.getStacks(); 8933 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 8934 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8935 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 8936 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8937 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 8938 final AppWindowToken wtoken = tokens.get(tokenNdx); 8939 if (!wtoken.allDrawn) { 8940 int numInteresting = wtoken.numInterestingWindows; 8941 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 8942 if (DEBUG_VISIBILITY) Slog.v(TAG, 8943 "allDrawn: " + wtoken 8944 + " interesting=" + numInteresting 8945 + " drawn=" + wtoken.numDrawnWindows); 8946 wtoken.allDrawn = true; 8947 mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget(); 8948 } 8949 } 8950 } 8951 } 8952 } 8953 } 8954 8955 // "Something has changed! Let's make it correct now." 8956 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 8957 if (DEBUG_WINDOW_TRACE) { 8958 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 8959 + Debug.getCallers(3)); 8960 } 8961 8962 final long currentTime = SystemClock.uptimeMillis(); 8963 8964 int i; 8965 8966 if (mFocusMayChange) { 8967 mFocusMayChange = false; 8968 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 8969 false /*updateInputWindows*/); 8970 } 8971 8972 // Initialize state of exiting tokens. 8973 final int numDisplays = mDisplayContents.size(); 8974 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 8975 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 8976 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) { 8977 displayContent.mExitingTokens.get(i).hasVisible = false; 8978 } 8979 } 8980 8981 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 8982 // Initialize state of exiting applications. 8983 final AppTokenList exitingAppTokens = 8984 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 8985 for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 8986 exitingAppTokens.get(tokenNdx).hasVisible = false; 8987 } 8988 } 8989 8990 mInnerFields.mHoldScreen = null; 8991 mInnerFields.mScreenBrightness = -1; 8992 mInnerFields.mButtonBrightness = -1; 8993 mInnerFields.mUserActivityTimeout = -1; 8994 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false; 8995 8996 mTransactionSequence++; 8997 8998 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked(); 8999 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 9000 final int defaultDw = defaultInfo.logicalWidth; 9001 final int defaultDh = defaultInfo.logicalHeight; 9002 9003 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9004 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 9005 SurfaceControl.openTransaction(); 9006 try { 9007 9008 if (mWatermark != null) { 9009 mWatermark.positionSurface(defaultDw, defaultDh); 9010 } 9011 if (mStrictModeFlash != null) { 9012 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 9013 } 9014 9015 boolean focusDisplayed = false; 9016 9017 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9018 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9019 boolean updateAllDrawn = false; 9020 WindowList windows = displayContent.getWindowList(); 9021 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9022 final int displayId = displayContent.getDisplayId(); 9023 final int dw = displayInfo.logicalWidth; 9024 final int dh = displayInfo.logicalHeight; 9025 final int innerDw = displayInfo.appWidth; 9026 final int innerDh = displayInfo.appHeight; 9027 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 9028 9029 // Reset for each display. 9030 mInnerFields.mDisplayHasContent = false; 9031 9032 int repeats = 0; 9033 do { 9034 repeats++; 9035 if (repeats > 6) { 9036 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 9037 displayContent.layoutNeeded = false; 9038 break; 9039 } 9040 9041 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 9042 displayContent.pendingLayoutChanges); 9043 9044 if ((displayContent.pendingLayoutChanges & 9045 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 && 9046 (adjustWallpaperWindowsLocked() & 9047 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 9048 assignLayersLocked(windows); 9049 displayContent.layoutNeeded = true; 9050 } 9051 9052 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 9053 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 9054 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 9055 if (updateOrientationFromAppTokensLocked(true)) { 9056 displayContent.layoutNeeded = true; 9057 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9058 } 9059 } 9060 9061 if ((displayContent.pendingLayoutChanges 9062 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9063 displayContent.layoutNeeded = true; 9064 } 9065 9066 // FIRST LOOP: Perform a layout, if needed. 9067 if (repeats < 4) { 9068 performLayoutLockedInner(displayContent, repeats == 1, 9069 false /*updateInputWindows*/); 9070 } else { 9071 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 9072 } 9073 9074 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 9075 // it is animating. 9076 displayContent.pendingLayoutChanges = 0; 9077 9078 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 9079 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 9080 9081 if (isDefaultDisplay) { 9082 mPolicy.beginPostLayoutPolicyLw(dw, dh); 9083 for (i = windows.size() - 1; i >= 0; i--) { 9084 WindowState w = windows.get(i); 9085 if (w.mHasSurface) { 9086 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); 9087 } 9088 } 9089 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 9090 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 9091 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges); 9092 } 9093 } while (displayContent.pendingLayoutChanges != 0); 9094 9095 mInnerFields.mObscured = false; 9096 mInnerFields.mSyswin = false; 9097 displayContent.resetDimming(); 9098 9099 // Only used if default window 9100 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 9101 9102 final int N = windows.size(); 9103 for (i=N-1; i>=0; i--) { 9104 WindowState w = windows.get(i); 9105 final TaskStack stack = w.getStack(); 9106 if (stack == null) { 9107 continue; 9108 } 9109 9110 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 9111 9112 // Update effect. 9113 w.mObscured = mInnerFields.mObscured; 9114 if (!mInnerFields.mObscured) { 9115 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 9116 } 9117 9118 if (!stack.testDimmingTag()) { 9119 handleFlagDimBehind(w); 9120 } 9121 9122 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 9123 && w.isVisibleLw()) { 9124 // This is the wallpaper target and its obscured state 9125 // changed... make sure the current wallaper's visibility 9126 // has been updated accordingly. 9127 updateWallpaperVisibilityLocked(); 9128 } 9129 9130 final WindowStateAnimator winAnimator = w.mWinAnimator; 9131 9132 // If the window has moved due to its containing 9133 // content frame changing, then we'd like to animate 9134 // it. 9135 if (w.mHasSurface && w.shouldAnimateMove()) { 9136 // Frame has moved, containing content frame 9137 // has also moved, and we're not currently animating... 9138 // let's do something. 9139 Animation a = AnimationUtils.loadAnimation(mContext, 9140 com.android.internal.R.anim.window_move_from_decor); 9141 winAnimator.setAnimation(a); 9142 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 9143 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 9144 try { 9145 w.mClient.moved(w.mFrame.left, w.mFrame.top); 9146 } catch (RemoteException e) { 9147 } 9148 } 9149 9150 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 9151 w.mContentChanged = false; 9152 9153 // Moved from updateWindowsAndWallpaperLocked(). 9154 if (w.mHasSurface) { 9155 // Take care of the window being ready to display. 9156 final boolean committed = 9157 winAnimator.commitFinishDrawingLocked(currentTime); 9158 if (isDefaultDisplay && committed) { 9159 if (w.mAttrs.type == TYPE_DREAM) { 9160 // HACK: When a dream is shown, it may at that 9161 // point hide the lock screen. So we need to 9162 // redo the layout to let the phone window manager 9163 // make this happen. 9164 displayContent.pendingLayoutChanges |= 9165 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9166 if (DEBUG_LAYOUT_REPEATS) { 9167 debugLayoutRepeats( 9168 "dream and commitFinishDrawingLocked true", 9169 displayContent.pendingLayoutChanges); 9170 } 9171 } 9172 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 9173 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 9174 "First draw done in potential wallpaper target " + w); 9175 mInnerFields.mWallpaperMayChange = true; 9176 displayContent.pendingLayoutChanges |= 9177 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9178 if (DEBUG_LAYOUT_REPEATS) { 9179 debugLayoutRepeats( 9180 "wallpaper and commitFinishDrawingLocked true", 9181 displayContent.pendingLayoutChanges); 9182 } 9183 } 9184 } 9185 9186 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 9187 9188 final AppWindowToken atoken = w.mAppToken; 9189 if (DEBUG_STARTING_WINDOW && atoken != null 9190 && w == atoken.startingWindow) { 9191 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 9192 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 9193 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 9194 } 9195 if (atoken != null 9196 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 9197 if (atoken.lastTransactionSequence != mTransactionSequence) { 9198 atoken.lastTransactionSequence = mTransactionSequence; 9199 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 9200 atoken.startingDisplayed = false; 9201 } 9202 if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 9203 && !w.mExiting && !w.mDestroying) { 9204 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 9205 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 9206 + ", isAnimating=" + winAnimator.isAnimating()); 9207 if (!w.isDrawnLw()) { 9208 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl 9209 + " pv=" + w.mPolicyVisibility 9210 + " mDrawState=" + winAnimator.mDrawState 9211 + " ah=" + w.mAttachedHidden 9212 + " th=" + atoken.hiddenRequested 9213 + " a=" + winAnimator.mAnimating); 9214 } 9215 } 9216 if (w != atoken.startingWindow) { 9217 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 9218 atoken.numInterestingWindows++; 9219 if (w.isDrawnLw()) { 9220 atoken.numDrawnWindows++; 9221 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 9222 "tokenMayBeDrawn: " + atoken 9223 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 9224 + " mAppFreezing=" + w.mAppFreezing); 9225 updateAllDrawn = true; 9226 } 9227 } 9228 } else if (w.isDrawnLw()) { 9229 atoken.startingDisplayed = true; 9230 } 9231 } 9232 } 9233 } 9234 9235 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 9236 && w.isDisplayedLw()) { 9237 focusDisplayed = true; 9238 } 9239 9240 updateResizingWindows(w); 9241 } 9242 9243 mDisplayManagerInternal.setDisplayHasContent(displayId, 9244 mInnerFields.mDisplayHasContent, 9245 true /* inTraversal, must call performTraversalInTrans... below */); 9246 9247 getDisplayContentLocked(displayId).stopDimmingIfNeeded(); 9248 9249 if (updateAllDrawn) { 9250 updateAllDrawnLocked(displayContent); 9251 } 9252 } 9253 9254 if (focusDisplayed) { 9255 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 9256 } 9257 9258 // Give the display manager a chance to adjust properties 9259 // like display rotation if it needs to. 9260 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 9261 9262 } catch (RuntimeException e) { 9263 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 9264 } finally { 9265 SurfaceControl.closeTransaction(); 9266 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9267 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 9268 } 9269 9270 final WindowList defaultWindows = defaultDisplay.getWindowList(); 9271 9272 // If we are ready to perform an app transition, check through 9273 // all of the app tokens to be shown and see if they are ready 9274 // to go. 9275 if (mAppTransition.isReady()) { 9276 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 9277 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 9278 defaultDisplay.pendingLayoutChanges); 9279 } 9280 9281 if (!mAnimator.mAnimating && mAppTransition.isRunning()) { 9282 // We have finished the animation of an app transition. To do 9283 // this, we have delayed a lot of operations like showing and 9284 // hiding apps, moving apps in Z-order, etc. The app token list 9285 // reflects the correct Z-order, but the window list may now 9286 // be out of sync with it. So here we will just rebuild the 9287 // entire app window list. Fun! 9288 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 9289 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 9290 defaultDisplay.pendingLayoutChanges); 9291 } 9292 9293 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 9294 && !mAppTransition.isReady()) { 9295 // At this point, there was a window with a wallpaper that 9296 // was force hiding other windows behind it, but now it 9297 // is going away. This may be simple -- just animate 9298 // away the wallpaper and its window -- or it may be 9299 // hard -- the wallpaper now needs to be shown behind 9300 // something that was hidden. 9301 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9302 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 9303 defaultDisplay.pendingLayoutChanges); 9304 } 9305 mInnerFields.mWallpaperForceHidingChanged = false; 9306 9307 if (mInnerFields.mWallpaperMayChange) { 9308 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting"); 9309 defaultDisplay.pendingLayoutChanges |= 9310 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9311 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange", 9312 defaultDisplay.pendingLayoutChanges); 9313 } 9314 9315 if (mFocusMayChange) { 9316 mFocusMayChange = false; 9317 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 9318 false /*updateInputWindows*/)) { 9319 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 9320 } 9321 } 9322 9323 if (needsLayout()) { 9324 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9325 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 9326 defaultDisplay.pendingLayoutChanges); 9327 } 9328 9329 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 9330 WindowState win = mResizingWindows.get(i); 9331 if (win.mAppFreezing) { 9332 // Don't remove this window until rotation has completed. 9333 continue; 9334 } 9335 win.reportResized(); 9336 mResizingWindows.remove(i); 9337 } 9338 9339 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 9340 "With display frozen, orientationChangeComplete=" 9341 + mInnerFields.mOrientationChangeComplete); 9342 if (mInnerFields.mOrientationChangeComplete) { 9343 if (mWindowsFreezingScreen) { 9344 mWindowsFreezingScreen = false; 9345 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource; 9346 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9347 } 9348 stopFreezingDisplayLocked(); 9349 } 9350 9351 // Destroy the surface of any windows that are no longer visible. 9352 boolean wallpaperDestroyed = false; 9353 i = mDestroySurface.size(); 9354 if (i > 0) { 9355 do { 9356 i--; 9357 WindowState win = mDestroySurface.get(i); 9358 win.mDestroying = false; 9359 if (mInputMethodWindow == win) { 9360 mInputMethodWindow = null; 9361 } 9362 if (win == mWallpaperTarget) { 9363 wallpaperDestroyed = true; 9364 } 9365 win.mWinAnimator.destroySurfaceLocked(); 9366 } while (i > 0); 9367 mDestroySurface.clear(); 9368 } 9369 9370 // Time to remove any exiting tokens? 9371 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9372 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9373 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens; 9374 for (i = exitingTokens.size() - 1; i >= 0; i--) { 9375 WindowToken token = exitingTokens.get(i); 9376 if (!token.hasVisible) { 9377 exitingTokens.remove(i); 9378 if (token.windowType == TYPE_WALLPAPER) { 9379 mWallpaperTokens.remove(token); 9380 } 9381 } 9382 } 9383 } 9384 9385 // Time to remove any exiting applications? 9386 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9387 // Initialize state of exiting applications. 9388 final AppTokenList exitingAppTokens = 9389 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9390 for (i = exitingAppTokens.size() - 1; i >= 0; i--) { 9391 AppWindowToken token = exitingAppTokens.get(i); 9392 if (!token.hasVisible && !mClosingApps.contains(token)) { 9393 // Make sure there is no animation running on this token, 9394 // so any windows associated with it will be removed as 9395 // soon as their animations are complete 9396 token.mAppAnimator.clearAnimation(); 9397 token.mAppAnimator.animating = false; 9398 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 9399 "performLayout: App token exiting now removed" + token); 9400 removeAppFromTaskLocked(token); 9401 exitingAppTokens.remove(i); 9402 } 9403 } 9404 } 9405 9406 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 9407 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 9408 try { 9409 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 9410 } catch (RemoteException e) { 9411 } 9412 } 9413 mRelayoutWhileAnimating.clear(); 9414 } 9415 9416 if (wallpaperDestroyed) { 9417 defaultDisplay.pendingLayoutChanges |= 9418 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9419 defaultDisplay.layoutNeeded = true; 9420 } 9421 9422 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9423 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9424 if (displayContent.pendingLayoutChanges != 0) { 9425 displayContent.layoutNeeded = true; 9426 } 9427 } 9428 9429 // Finally update all input windows now that the window changes have stabilized. 9430 mInputMonitor.updateInputWindowsLw(true /*force*/); 9431 9432 setHoldScreenLocked(mInnerFields.mHoldScreen); 9433 if (!mDisplayFrozen) { 9434 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 9435 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1); 9436 } else { 9437 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager( 9438 toBrightnessOverride(mInnerFields.mScreenBrightness)); 9439 } 9440 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 9441 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1); 9442 } else { 9443 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager( 9444 toBrightnessOverride(mInnerFields.mButtonBrightness)); 9445 } 9446 mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager( 9447 mInnerFields.mUserActivityTimeout); 9448 } 9449 9450 if (mTurnOnScreen) { 9451 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 9452 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 9453 mTurnOnScreen = false; 9454 } 9455 9456 if (mInnerFields.mUpdateRotation) { 9457 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9458 if (updateRotationUncheckedLocked(false)) { 9459 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9460 } else { 9461 mInnerFields.mUpdateRotation = false; 9462 } 9463 } 9464 9465 if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded 9466 && !mInnerFields.mUpdateRotation) { 9467 checkDrawnWindowsLocked(); 9468 } 9469 9470 final int N = mPendingRemove.size(); 9471 if (N > 0) { 9472 if (mPendingRemoveTmp.length < N) { 9473 mPendingRemoveTmp = new WindowState[N+10]; 9474 } 9475 mPendingRemove.toArray(mPendingRemoveTmp); 9476 mPendingRemove.clear(); 9477 DisplayContentList displayList = new DisplayContentList(); 9478 for (i = 0; i < N; i++) { 9479 WindowState w = mPendingRemoveTmp[i]; 9480 removeWindowInnerLocked(w.mSession, w); 9481 final DisplayContent displayContent = w.getDisplayContent(); 9482 if (displayContent != null && !displayList.contains(displayContent)) { 9483 displayList.add(displayContent); 9484 } 9485 } 9486 9487 for (DisplayContent displayContent : displayList) { 9488 assignLayersLocked(displayContent.getWindowList()); 9489 displayContent.layoutNeeded = true; 9490 } 9491 } 9492 9493 // Remove all deferred Stacks, tasks, and activities. 9494 for (int stackNdx = mPendingStacksRemove.size() - 1; stackNdx >= 0; --stackNdx) { 9495 mPendingStacksRemove.removeAt(stackNdx).checkForDeferredActions(); 9496 } 9497 9498 setFocusedStackFrame(); 9499 9500 // Check to see if we are now in a state where the screen should 9501 // be enabled, because the window obscured flags have changed. 9502 enableScreenIfNeededLocked(); 9503 9504 scheduleAnimationLocked(); 9505 9506 if (DEBUG_WINDOW_TRACE) { 9507 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" 9508 + mAnimator.mAnimating); 9509 } 9510 } 9511 9512 private int toBrightnessOverride(float value) { 9513 return (int)(value * PowerManager.BRIGHTNESS_ON); 9514 } 9515 9516 void checkDrawnWindowsLocked() { 9517 if (mWaitingForDrawn.size() > 0) { 9518 for (int j=mWaitingForDrawn.size()-1; j>=0; j--) { 9519 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j); 9520 WindowState win = pair.first; 9521 //Slog.i(TAG, "Waiting for drawn " + win + ": removed=" 9522 // + win.mRemoved + " visible=" + win.isVisibleLw() 9523 // + " shown=" + win.mSurfaceShown); 9524 if (win.mRemoved) { 9525 // Window has been removed; no draw will now happen, so stop waiting. 9526 Slog.w(TAG, "Aborted waiting for drawn: " + pair.first); 9527 try { 9528 pair.second.sendResult(null); 9529 } catch (RemoteException e) { 9530 } 9531 mWaitingForDrawn.remove(pair); 9532 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9533 } else if (win.mWinAnimator.mSurfaceShown) { 9534 // Window is now drawn (and shown). 9535 try { 9536 pair.second.sendResult(null); 9537 } catch (RemoteException e) { 9538 } 9539 mWaitingForDrawn.remove(pair); 9540 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9541 } 9542 } 9543 } 9544 } 9545 9546 @Override 9547 public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) { 9548 if (token != null && callback != null) { 9549 synchronized (mWindowMap) { 9550 WindowState win = windowForClientLocked(null, token, true); 9551 if (win != null) { 9552 Pair<WindowState, IRemoteCallback> pair = 9553 new Pair<WindowState, IRemoteCallback>(win, callback); 9554 Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9555 mH.sendMessageDelayed(m, 2000); 9556 mWaitingForDrawn.add(pair); 9557 checkDrawnWindowsLocked(); 9558 return true; 9559 } 9560 Slog.i(TAG, "waitForWindowDrawn: win null"); 9561 } 9562 } 9563 return false; 9564 } 9565 9566 void setHoldScreenLocked(final Session newHoldScreen) { 9567 final boolean hold = newHoldScreen != null; 9568 9569 if (hold && mHoldingScreenOn != newHoldScreen) { 9570 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 9571 } 9572 mHoldingScreenOn = newHoldScreen; 9573 9574 final boolean state = mHoldingScreenWakeLock.isHeld(); 9575 if (hold != state) { 9576 if (hold) { 9577 mHoldingScreenWakeLock.acquire(); 9578 mPolicy.keepScreenOnStartedLw(); 9579 } else { 9580 mPolicy.keepScreenOnStoppedLw(); 9581 mHoldingScreenWakeLock.release(); 9582 } 9583 } 9584 } 9585 9586 void requestTraversal() { 9587 synchronized (mWindowMap) { 9588 requestTraversalLocked(); 9589 } 9590 } 9591 9592 void requestTraversalLocked() { 9593 if (!mTraversalScheduled) { 9594 mTraversalScheduled = true; 9595 mH.sendEmptyMessage(H.DO_TRAVERSAL); 9596 } 9597 } 9598 9599 /** Note that Locked in this case is on mLayoutToAnim */ 9600 void scheduleAnimationLocked() { 9601 if (!mAnimationScheduled) { 9602 mAnimationScheduled = true; 9603 mChoreographer.postCallback( 9604 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 9605 } 9606 } 9607 9608 private boolean needsLayout() { 9609 final int numDisplays = mDisplayContents.size(); 9610 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9611 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9612 if (displayContent.layoutNeeded) { 9613 return true; 9614 } 9615 } 9616 return false; 9617 } 9618 9619 boolean copyAnimToLayoutParamsLocked() { 9620 boolean doRequest = false; 9621 9622 final int bulkUpdateParams = mAnimator.mBulkUpdateParams; 9623 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 9624 mInnerFields.mUpdateRotation = true; 9625 doRequest = true; 9626 } 9627 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 9628 mInnerFields.mWallpaperMayChange = true; 9629 doRequest = true; 9630 } 9631 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 9632 mInnerFields.mWallpaperForceHidingChanged = true; 9633 doRequest = true; 9634 } 9635 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 9636 mInnerFields.mOrientationChangeComplete = false; 9637 } else { 9638 mInnerFields.mOrientationChangeComplete = true; 9639 mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource; 9640 if (mWindowsFreezingScreen) { 9641 doRequest = true; 9642 } 9643 } 9644 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 9645 mTurnOnScreen = true; 9646 } 9647 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) { 9648 mInnerFields.mWallpaperActionPending = true; 9649 } 9650 9651 return doRequest; 9652 } 9653 9654 /** If a window that has an animation specifying a colored background and the current wallpaper 9655 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 9656 * suddenly disappear. */ 9657 int adjustAnimationBackground(WindowStateAnimator winAnimator) { 9658 WindowList windows = winAnimator.mWin.getWindowList(); 9659 for (int i = windows.size() - 1; i >= 0; --i) { 9660 WindowState testWin = windows.get(i); 9661 if (testWin.mIsWallpaper && testWin.isVisibleNow()) { 9662 return testWin.mWinAnimator.mAnimLayer; 9663 } 9664 } 9665 return winAnimator.mAnimLayer; 9666 } 9667 9668 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9669 boolean secure) { 9670 final SurfaceControl surface = winAnimator.mSurfaceControl; 9671 boolean leakedSurface = false; 9672 boolean killedApps = false; 9673 9674 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9675 winAnimator.mSession.mPid, operation); 9676 9677 if (mForceRemoves == null) { 9678 mForceRemoves = new ArrayList<WindowState>(); 9679 } 9680 9681 long callingIdentity = Binder.clearCallingIdentity(); 9682 try { 9683 // There was some problem... first, do a sanity check of the 9684 // window list to make sure we haven't left any dangling surfaces 9685 // around. 9686 9687 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 9688 final int numDisplays = mDisplayContents.size(); 9689 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9690 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9691 final int numWindows = windows.size(); 9692 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9693 final WindowState ws = windows.get(winNdx); 9694 WindowStateAnimator wsa = ws.mWinAnimator; 9695 if (wsa.mSurfaceControl != null) { 9696 if (!mSessions.contains(wsa.mSession)) { 9697 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 9698 + ws + " surface=" + wsa.mSurfaceControl 9699 + " token=" + ws.mToken 9700 + " pid=" + ws.mSession.mPid 9701 + " uid=" + ws.mSession.mUid); 9702 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9703 wsa.mSurfaceControl.destroy(); 9704 wsa.mSurfaceShown = false; 9705 wsa.mSurfaceControl = null; 9706 ws.mHasSurface = false; 9707 mForceRemoves.add(ws); 9708 leakedSurface = true; 9709 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9710 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 9711 + ws + " surface=" + wsa.mSurfaceControl 9712 + " token=" + ws.mAppToken); 9713 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9714 wsa.mSurfaceControl.destroy(); 9715 wsa.mSurfaceShown = false; 9716 wsa.mSurfaceControl = null; 9717 ws.mHasSurface = false; 9718 leakedSurface = true; 9719 } 9720 } 9721 } 9722 } 9723 9724 if (!leakedSurface) { 9725 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 9726 SparseIntArray pidCandidates = new SparseIntArray(); 9727 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9728 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9729 final int numWindows = windows.size(); 9730 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9731 final WindowState ws = windows.get(winNdx); 9732 if (mForceRemoves.contains(ws)) { 9733 continue; 9734 } 9735 WindowStateAnimator wsa = ws.mWinAnimator; 9736 if (wsa.mSurfaceControl != null) { 9737 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9738 } 9739 } 9740 if (pidCandidates.size() > 0) { 9741 int[] pids = new int[pidCandidates.size()]; 9742 for (int i=0; i<pids.length; i++) { 9743 pids[i] = pidCandidates.keyAt(i); 9744 } 9745 try { 9746 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9747 killedApps = true; 9748 } 9749 } catch (RemoteException e) { 9750 } 9751 } 9752 } 9753 } 9754 9755 if (leakedSurface || killedApps) { 9756 // We managed to reclaim some memory, so get rid of the trouble 9757 // surface and ask the app to request another one. 9758 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 9759 if (surface != null) { 9760 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9761 "RECOVER DESTROY", null); 9762 surface.destroy(); 9763 winAnimator.mSurfaceShown = false; 9764 winAnimator.mSurfaceControl = null; 9765 winAnimator.mWin.mHasSurface = false; 9766 scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken); 9767 } 9768 9769 try { 9770 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9771 } catch (RemoteException e) { 9772 } 9773 } 9774 } finally { 9775 Binder.restoreCallingIdentity(callingIdentity); 9776 } 9777 9778 return leakedSurface || killedApps; 9779 } 9780 9781 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9782 WindowState newFocus = computeFocusedWindowLocked(); 9783 if (mCurrentFocus != newFocus) { 9784 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9785 // This check makes sure that we don't already have the focus 9786 // change message pending. 9787 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9788 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9789 // TODO(multidisplay): Focused windows on default display only. 9790 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9791 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked( 9792 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 9793 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES); 9794 if (imWindowChanged) { 9795 displayContent.layoutNeeded = true; 9796 newFocus = computeFocusedWindowLocked(); 9797 } 9798 9799 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " + 9800 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 9801 final WindowState oldFocus = mCurrentFocus; 9802 mCurrentFocus = newFocus; 9803 mLosingFocus.remove(newFocus); 9804 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9805 9806 if (imWindowChanged && oldFocus != mInputMethodWindow) { 9807 // Focus of the input method window changed. Perform layout if needed. 9808 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9809 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9810 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9811 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9812 // Client will do the layout, but we need to assign layers 9813 // for handleNewWindowLocked() below. 9814 assignLayersLocked(displayContent.getWindowList()); 9815 } 9816 } 9817 9818 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9819 // The change in focus caused us to need to do a layout. Okay. 9820 displayContent.layoutNeeded = true; 9821 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9822 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9823 } 9824 } 9825 9826 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9827 // If we defer assigning layers, then the caller is responsible for 9828 // doing this part. 9829 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 9830 } 9831 9832 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9833 return true; 9834 } 9835 return false; 9836 } 9837 9838 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 9839 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9840 } 9841 9842 private WindowState computeFocusedWindowLocked() { 9843 if (mAnimator.mUniverseBackground != null 9844 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 9845 return mAnimator.mUniverseBackground.mWin; 9846 } 9847 9848 final int displayCount = mDisplayContents.size(); 9849 for (int i = 0; i < displayCount; i++) { 9850 final DisplayContent displayContent = mDisplayContents.valueAt(i); 9851 WindowState win = findFocusedWindowLocked(displayContent); 9852 if (win != null) { 9853 return win; 9854 } 9855 } 9856 return null; 9857 } 9858 9859 private WindowState findFocusedWindowLocked(DisplayContent displayContent) { 9860 final WindowList windows = displayContent.getWindowList(); 9861 for (int i = windows.size() - 1; i >= 0; i--) { 9862 final WindowState win = windows.get(i); 9863 9864 if (localLOGV || DEBUG_FOCUS) Slog.v( 9865 TAG, "Looking for focus: " + i 9866 + " = " + win 9867 + ", flags=" + win.mAttrs.flags 9868 + ", canReceive=" + win.canReceiveKeys()); 9869 9870 AppWindowToken wtoken = win.mAppToken; 9871 9872 // If this window's application has been removed, just skip it. 9873 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 9874 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because " 9875 + (wtoken.removed ? "removed" : "sendingToBottom")); 9876 continue; 9877 } 9878 9879 if (!win.canReceiveKeys()) { 9880 continue; 9881 } 9882 9883 // Descend through all of the app tokens and find the first that either matches 9884 // win.mAppToken (return win) or mFocusedApp (return null). 9885 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && 9886 mFocusedApp != null) { 9887 ArrayList<Task> tasks = displayContent.getTasks(); 9888 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9889 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9890 int tokenNdx = tokens.size() - 1; 9891 for ( ; tokenNdx >= 0; --tokenNdx) { 9892 final AppWindowToken token = tokens.get(tokenNdx); 9893 if (wtoken == token) { 9894 break; 9895 } 9896 if (mFocusedApp == token) { 9897 // Whoops, we are below the focused app... no focus for you! 9898 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG, 9899 "findFocusedWindow: Reached focused app=" + mFocusedApp); 9900 return null; 9901 } 9902 } 9903 if (tokenNdx >= 0) { 9904 // Early exit from loop, must have found the matching token. 9905 break; 9906 } 9907 } 9908 } 9909 9910 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i + 9911 " = " + win); 9912 return win; 9913 } 9914 9915 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows."); 9916 return null; 9917 } 9918 9919 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 9920 if (mDisplayFrozen) { 9921 return; 9922 } 9923 9924 if (!mDisplayReady || !mPolicy.isScreenOnFully()) { 9925 // No need to freeze the screen before the system is ready or if 9926 // the screen is off. 9927 return; 9928 } 9929 9930 mScreenFrozenLock.acquire(); 9931 9932 mDisplayFrozen = true; 9933 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 9934 mLastFinishedFreezeSource = null; 9935 9936 mInputMonitor.freezeInputDispatchingLw(); 9937 9938 // Clear the last input window -- that is just used for 9939 // clean transitions between IMEs, and if we are freezing 9940 // the screen then the whole world is changing behind the scenes. 9941 mPolicy.setLastInputMethodWindowLw(null, null); 9942 9943 if (mAppTransition.isTransitionSet()) { 9944 mAppTransition.freeze(); 9945 } 9946 9947 if (PROFILE_ORIENTATION) { 9948 File file = new File("/data/system/frozen"); 9949 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 9950 } 9951 9952 if (CUSTOM_SCREEN_ROTATION) { 9953 mExitAnimId = exitAnim; 9954 mEnterAnimId = enterAnim; 9955 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9956 final int displayId = displayContent.getDisplayId(); 9957 ScreenRotationAnimation screenRotationAnimation = 9958 mAnimator.getScreenRotationAnimationLocked(displayId); 9959 if (screenRotationAnimation != null) { 9960 screenRotationAnimation.kill(); 9961 } 9962 9963 // TODO(multidisplay): rotation on main screen only. 9964 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 9965 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced()); 9966 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 9967 } 9968 } 9969 9970 private void stopFreezingDisplayLocked() { 9971 if (!mDisplayFrozen) { 9972 return; 9973 } 9974 9975 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen 9976 || mClientFreezingScreen) { 9977 if (DEBUG_ORIENTATION) Slog.d(TAG, 9978 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 9979 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 9980 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 9981 + ", mClientFreezingScreen=" + mClientFreezingScreen); 9982 return; 9983 } 9984 9985 mDisplayFrozen = false; 9986 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 9987 StringBuilder sb = new StringBuilder(128); 9988 sb.append("Screen frozen for "); 9989 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 9990 if (mLastFinishedFreezeSource != null) { 9991 sb.append(" due to "); 9992 sb.append(mLastFinishedFreezeSource); 9993 } 9994 Slog.i(TAG, sb.toString()); 9995 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 9996 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 9997 if (PROFILE_ORIENTATION) { 9998 Debug.stopMethodTracing(); 9999 } 10000 10001 boolean updateRotation = false; 10002 10003 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10004 final int displayId = displayContent.getDisplayId(); 10005 ScreenRotationAnimation screenRotationAnimation = 10006 mAnimator.getScreenRotationAnimationLocked(displayId); 10007 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 10008 && screenRotationAnimation.hasScreenshot()) { 10009 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 10010 // TODO(multidisplay): rotation on main screen only. 10011 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10012 // Get rotation animation again, with new top window 10013 boolean isDimming = displayContent.isDimming(); 10014 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 10015 mExitAnimId = mEnterAnimId = 0; 10016 } 10017 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 10018 mTransitionAnimationScale, displayInfo.logicalWidth, 10019 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 10020 scheduleAnimationLocked(); 10021 } else { 10022 screenRotationAnimation.kill(); 10023 screenRotationAnimation = null; 10024 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10025 updateRotation = true; 10026 } 10027 } else { 10028 if (screenRotationAnimation != null) { 10029 screenRotationAnimation.kill(); 10030 screenRotationAnimation = null; 10031 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10032 } 10033 updateRotation = true; 10034 } 10035 10036 mInputMonitor.thawInputDispatchingLw(); 10037 10038 boolean configChanged; 10039 10040 // While the display is frozen we don't re-compute the orientation 10041 // to avoid inconsistent states. However, something interesting 10042 // could have actually changed during that time so re-evaluate it 10043 // now to catch that. 10044 configChanged = updateOrientationFromAppTokensLocked(false); 10045 10046 // A little kludge: a lot could have happened while the 10047 // display was frozen, so now that we are coming back we 10048 // do a gc so that any remote references the system 10049 // processes holds on others can be released if they are 10050 // no longer needed. 10051 mH.removeMessages(H.FORCE_GC); 10052 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 10053 10054 mScreenFrozenLock.release(); 10055 10056 if (updateRotation) { 10057 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 10058 configChanged |= updateRotationUncheckedLocked(false); 10059 } 10060 10061 if (configChanged) { 10062 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10063 } 10064 } 10065 10066 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 10067 DisplayMetrics dm) { 10068 if (index < tokens.length) { 10069 String str = tokens[index]; 10070 if (str != null && str.length() > 0) { 10071 try { 10072 int val = Integer.parseInt(str); 10073 return val; 10074 } catch (Exception e) { 10075 } 10076 } 10077 } 10078 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 10079 return defDps; 10080 } 10081 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 10082 return val; 10083 } 10084 10085 void createWatermarkInTransaction() { 10086 if (mWatermark != null) { 10087 return; 10088 } 10089 10090 File file = new File("/system/etc/setup.conf"); 10091 FileInputStream in = null; 10092 DataInputStream ind = null; 10093 try { 10094 in = new FileInputStream(file); 10095 ind = new DataInputStream(in); 10096 String line = ind.readLine(); 10097 if (line != null) { 10098 String[] toks = line.split("%"); 10099 if (toks != null && toks.length > 0) { 10100 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 10101 mRealDisplayMetrics, mFxSession, toks); 10102 } 10103 } 10104 } catch (FileNotFoundException e) { 10105 } catch (IOException e) { 10106 } finally { 10107 if (ind != null) { 10108 try { 10109 ind.close(); 10110 } catch (IOException e) { 10111 } 10112 } else if (in != null) { 10113 try { 10114 in.close(); 10115 } catch (IOException e) { 10116 } 10117 } 10118 } 10119 } 10120 10121 @Override 10122 public void statusBarVisibilityChanged(int visibility) { 10123 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10124 != PackageManager.PERMISSION_GRANTED) { 10125 throw new SecurityException("Caller does not hold permission " 10126 + android.Manifest.permission.STATUS_BAR); 10127 } 10128 10129 synchronized (mWindowMap) { 10130 mLastStatusBarVisibility = visibility; 10131 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 10132 updateStatusBarVisibilityLocked(visibility); 10133 } 10134 } 10135 10136 // TOOD(multidisplay): StatusBar on multiple screens? 10137 void updateStatusBarVisibilityLocked(int visibility) { 10138 mInputManager.setSystemUiVisibility(visibility); 10139 final WindowList windows = getDefaultWindowListLocked(); 10140 final int N = windows.size(); 10141 for (int i = 0; i < N; i++) { 10142 WindowState ws = windows.get(i); 10143 try { 10144 int curValue = ws.mSystemUiVisibility; 10145 int diff = curValue ^ visibility; 10146 // We are only interested in differences of one of the 10147 // clearable flags... 10148 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 10149 // ...if it has actually been cleared. 10150 diff &= ~visibility; 10151 int newValue = (curValue&~diff) | (visibility&diff); 10152 if (newValue != curValue) { 10153 ws.mSeq++; 10154 ws.mSystemUiVisibility = newValue; 10155 } 10156 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 10157 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 10158 visibility, newValue, diff); 10159 } 10160 } catch (RemoteException e) { 10161 // so sorry 10162 } 10163 } 10164 } 10165 10166 @Override 10167 public void reevaluateStatusBarVisibility() { 10168 synchronized (mWindowMap) { 10169 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 10170 updateStatusBarVisibilityLocked(visibility); 10171 performLayoutAndPlaceSurfacesLocked(); 10172 } 10173 } 10174 10175 @Override 10176 public FakeWindow addFakeWindow(Looper looper, 10177 InputEventReceiver.Factory inputEventReceiverFactory, 10178 String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags, 10179 boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) { 10180 synchronized (mWindowMap) { 10181 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 10182 name, windowType, 10183 layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys, 10184 hasFocus, touchFullscreen); 10185 int i=0; 10186 while (i<mFakeWindows.size()) { 10187 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 10188 break; 10189 } 10190 } 10191 mFakeWindows.add(i, fw); 10192 mInputMonitor.updateInputWindowsLw(true); 10193 return fw; 10194 } 10195 } 10196 10197 boolean removeFakeWindowLocked(FakeWindow window) { 10198 synchronized (mWindowMap) { 10199 if (mFakeWindows.remove(window)) { 10200 mInputMonitor.updateInputWindowsLw(true); 10201 return true; 10202 } 10203 return false; 10204 } 10205 } 10206 10207 // It is assumed that this method is called only by InputMethodManagerService. 10208 public void saveLastInputMethodWindowForTransition() { 10209 synchronized (mWindowMap) { 10210 // TODO(multidisplay): Pass in the displayID. 10211 DisplayContent displayContent = getDefaultDisplayContentLocked(); 10212 if (mInputMethodWindow != null) { 10213 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 10214 } 10215 } 10216 } 10217 10218 @Override 10219 public boolean hasNavigationBar() { 10220 return mPolicy.hasNavigationBar(); 10221 } 10222 10223 @Override 10224 public void lockNow(Bundle options) { 10225 mPolicy.lockNow(options); 10226 } 10227 10228 @Override 10229 public boolean isSafeModeEnabled() { 10230 return mSafeMode; 10231 } 10232 10233 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10234 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 10235 mPolicy.dump(" ", pw, args); 10236 } 10237 10238 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10239 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 10240 mAnimator.dumpLocked(pw, " ", dumpAll); 10241 } 10242 10243 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 10244 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 10245 if (mTokenMap.size() > 0) { 10246 pw.println(" All tokens:"); 10247 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10248 while (it.hasNext()) { 10249 WindowToken token = it.next(); 10250 pw.print(" "); pw.print(token); 10251 if (dumpAll) { 10252 pw.println(':'); 10253 token.dump(pw, " "); 10254 } else { 10255 pw.println(); 10256 } 10257 } 10258 } 10259 if (mWallpaperTokens.size() > 0) { 10260 pw.println(); 10261 pw.println(" Wallpaper tokens:"); 10262 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 10263 WindowToken token = mWallpaperTokens.get(i); 10264 pw.print(" Wallpaper #"); pw.print(i); 10265 pw.print(' '); pw.print(token); 10266 if (dumpAll) { 10267 pw.println(':'); 10268 token.dump(pw, " "); 10269 } else { 10270 pw.println(); 10271 } 10272 } 10273 } 10274 if (mFinishedStarting.size() > 0) { 10275 pw.println(); 10276 pw.println(" Finishing start of application tokens:"); 10277 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10278 WindowToken token = mFinishedStarting.get(i); 10279 pw.print(" Finished Starting #"); pw.print(i); 10280 pw.print(' '); pw.print(token); 10281 if (dumpAll) { 10282 pw.println(':'); 10283 token.dump(pw, " "); 10284 } else { 10285 pw.println(); 10286 } 10287 } 10288 } 10289 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 10290 pw.println(); 10291 if (mOpeningApps.size() > 0) { 10292 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10293 } 10294 if (mClosingApps.size() > 0) { 10295 pw.print(" mClosingApps="); pw.println(mClosingApps); 10296 } 10297 } 10298 } 10299 10300 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 10301 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 10302 if (mSessions.size() > 0) { 10303 Iterator<Session> it = mSessions.iterator(); 10304 while (it.hasNext()) { 10305 Session s = it.next(); 10306 pw.print(" Session "); pw.print(s); pw.println(':'); 10307 s.dump(pw, " "); 10308 } 10309 } 10310 } 10311 10312 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 10313 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 10314 if (mDisplayReady) { 10315 final int numDisplays = mDisplayContents.size(); 10316 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10317 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10318 displayContent.dump(" ", pw); 10319 } 10320 } else { 10321 pw.println(" NO DISPLAY"); 10322 } 10323 } 10324 10325 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 10326 ArrayList<WindowState> windows) { 10327 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 10328 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 10329 } 10330 10331 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 10332 ArrayList<WindowState> windows) { 10333 final int numDisplays = mDisplayContents.size(); 10334 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10335 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); 10336 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10337 final WindowState w = windowList.get(winNdx); 10338 if (windows == null || windows.contains(w)) { 10339 pw.print(" Window #"); pw.print(winNdx); pw.print(' '); 10340 pw.print(w); pw.println(":"); 10341 w.dump(pw, " ", dumpAll || windows != null); 10342 } 10343 } 10344 } 10345 if (mInputMethodDialogs.size() > 0) { 10346 pw.println(); 10347 pw.println(" Input method dialogs:"); 10348 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 10349 WindowState w = mInputMethodDialogs.get(i); 10350 if (windows == null || windows.contains(w)) { 10351 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 10352 } 10353 } 10354 } 10355 if (mPendingRemove.size() > 0) { 10356 pw.println(); 10357 pw.println(" Remove pending for:"); 10358 for (int i=mPendingRemove.size()-1; i>=0; i--) { 10359 WindowState w = mPendingRemove.get(i); 10360 if (windows == null || windows.contains(w)) { 10361 pw.print(" Remove #"); pw.print(i); pw.print(' '); 10362 pw.print(w); 10363 if (dumpAll) { 10364 pw.println(":"); 10365 w.dump(pw, " ", true); 10366 } else { 10367 pw.println(); 10368 } 10369 } 10370 } 10371 } 10372 if (mForceRemoves != null && mForceRemoves.size() > 0) { 10373 pw.println(); 10374 pw.println(" Windows force removing:"); 10375 for (int i=mForceRemoves.size()-1; i>=0; i--) { 10376 WindowState w = mForceRemoves.get(i); 10377 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10378 pw.print(w); 10379 if (dumpAll) { 10380 pw.println(":"); 10381 w.dump(pw, " ", true); 10382 } else { 10383 pw.println(); 10384 } 10385 } 10386 } 10387 if (mDestroySurface.size() > 0) { 10388 pw.println(); 10389 pw.println(" Windows waiting to destroy their surface:"); 10390 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10391 WindowState w = mDestroySurface.get(i); 10392 if (windows == null || windows.contains(w)) { 10393 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10394 pw.print(w); 10395 if (dumpAll) { 10396 pw.println(":"); 10397 w.dump(pw, " ", true); 10398 } else { 10399 pw.println(); 10400 } 10401 } 10402 } 10403 } 10404 if (mLosingFocus.size() > 0) { 10405 pw.println(); 10406 pw.println(" Windows losing focus:"); 10407 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10408 WindowState w = mLosingFocus.get(i); 10409 if (windows == null || windows.contains(w)) { 10410 pw.print(" Losing #"); 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 (mResizingWindows.size() > 0) { 10422 pw.println(); 10423 pw.println(" Windows waiting to resize:"); 10424 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10425 WindowState w = mResizingWindows.get(i); 10426 if (windows == null || windows.contains(w)) { 10427 pw.print(" Resizing #"); 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 (mWaitingForDrawn.size() > 0) { 10439 pw.println(); 10440 pw.println(" Clients waiting for these windows to be drawn:"); 10441 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10442 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i); 10443 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first); 10444 pw.print(": "); pw.println(pair.second); 10445 } 10446 } 10447 pw.println(); 10448 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10449 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10450 if (mLastFocus != mCurrentFocus) { 10451 pw.print(" mLastFocus="); pw.println(mLastFocus); 10452 } 10453 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10454 if (mInputMethodTarget != null) { 10455 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10456 } 10457 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10458 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10459 pw.print(" mLastDisplayFreezeDuration="); 10460 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 10461 if ( mLastFinishedFreezeSource != null) { 10462 pw.print(" due to "); 10463 pw.print(mLastFinishedFreezeSource); 10464 } 10465 pw.println(); 10466 if (dumpAll) { 10467 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 10468 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 10469 if (mLastStatusBarVisibility != 0) { 10470 pw.print(" mLastStatusBarVisibility=0x"); 10471 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 10472 } 10473 if (mInputMethodWindow != null) { 10474 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10475 } 10476 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 10477 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) { 10478 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 10479 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 10480 } 10481 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 10482 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 10483 if (mInputMethodAnimLayerAdjustment != 0 || 10484 mWallpaperAnimLayerAdjustment != 0) { 10485 pw.print(" mInputMethodAnimLayerAdjustment="); 10486 pw.print(mInputMethodAnimLayerAdjustment); 10487 pw.print(" mWallpaperAnimLayerAdjustment="); 10488 pw.println(mWallpaperAnimLayerAdjustment); 10489 } 10490 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10491 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10492 if (needsLayout()) { 10493 pw.print(" layoutNeeded on displays="); 10494 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10495 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10496 if (displayContent.layoutNeeded) { 10497 pw.print(displayContent.getDisplayId()); 10498 } 10499 } 10500 pw.println(); 10501 } 10502 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 10503 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10504 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 10505 pw.print(" client="); pw.print(mClientFreezingScreen); 10506 pw.print(" apps="); pw.print(mAppsFreezingScreen); 10507 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 10508 pw.print(" mRotation="); pw.print(mRotation); 10509 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 10510 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 10511 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 10512 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 10513 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); 10514 pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale); 10515 pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale); 10516 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); 10517 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 10518 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 10519 pw.println(" mLayoutToAnim:"); 10520 mAppTransition.dump(pw); 10521 } 10522 } 10523 10524 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10525 int opti, boolean dumpAll) { 10526 WindowList windows = new WindowList(); 10527 if ("visible".equals(name)) { 10528 synchronized(mWindowMap) { 10529 final int numDisplays = mDisplayContents.size(); 10530 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10531 final WindowList windowList = 10532 mDisplayContents.valueAt(displayNdx).getWindowList(); 10533 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10534 final WindowState w = windowList.get(winNdx); 10535 if (w.mWinAnimator.mSurfaceShown) { 10536 windows.add(w); 10537 } 10538 } 10539 } 10540 } 10541 } else { 10542 int objectId = 0; 10543 // See if this is an object ID. 10544 try { 10545 objectId = Integer.parseInt(name, 16); 10546 name = null; 10547 } catch (RuntimeException e) { 10548 } 10549 synchronized(mWindowMap) { 10550 final int numDisplays = mDisplayContents.size(); 10551 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10552 final WindowList windowList = 10553 mDisplayContents.valueAt(displayNdx).getWindowList(); 10554 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10555 final WindowState w = windowList.get(winNdx); 10556 if (name != null) { 10557 if (w.mAttrs.getTitle().toString().contains(name)) { 10558 windows.add(w); 10559 } 10560 } else if (System.identityHashCode(w) == objectId) { 10561 windows.add(w); 10562 } 10563 } 10564 } 10565 } 10566 } 10567 10568 if (windows.size() <= 0) { 10569 return false; 10570 } 10571 10572 synchronized(mWindowMap) { 10573 dumpWindowsLocked(pw, dumpAll, windows); 10574 } 10575 return true; 10576 } 10577 10578 void dumpLastANRLocked(PrintWriter pw) { 10579 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10580 if (mLastANRState == null) { 10581 pw.println(" <no ANR has occurred since boot>"); 10582 } else { 10583 pw.println(mLastANRState); 10584 } 10585 } 10586 10587 /** 10588 * Saves information about the state of the window manager at 10589 * the time an ANR occurred before anything else in the system changes 10590 * in response. 10591 * 10592 * @param appWindowToken The application that ANR'd, may be null. 10593 * @param windowState The window that ANR'd, may be null. 10594 * @param reason The reason for the ANR, may be null. 10595 */ 10596 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, 10597 String reason) { 10598 StringWriter sw = new StringWriter(); 10599 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 10600 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10601 if (appWindowToken != null) { 10602 pw.println(" Application at fault: " + appWindowToken.stringName); 10603 } 10604 if (windowState != null) { 10605 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10606 } 10607 if (reason != null) { 10608 pw.println(" Reason: " + reason); 10609 } 10610 pw.println(); 10611 dumpWindowsNoHeaderLocked(pw, true, null); 10612 pw.close(); 10613 mLastANRState = sw.toString(); 10614 } 10615 10616 @Override 10617 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10618 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10619 != PackageManager.PERMISSION_GRANTED) { 10620 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10621 + Binder.getCallingPid() 10622 + ", uid=" + Binder.getCallingUid()); 10623 return; 10624 } 10625 10626 boolean dumpAll = false; 10627 10628 int opti = 0; 10629 while (opti < args.length) { 10630 String opt = args[opti]; 10631 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10632 break; 10633 } 10634 opti++; 10635 if ("-a".equals(opt)) { 10636 dumpAll = true; 10637 } else if ("-h".equals(opt)) { 10638 pw.println("Window manager dump options:"); 10639 pw.println(" [-a] [-h] [cmd] ..."); 10640 pw.println(" cmd may be one of:"); 10641 pw.println(" l[astanr]: last ANR information"); 10642 pw.println(" p[policy]: policy state"); 10643 pw.println(" a[animator]: animator state"); 10644 pw.println(" s[essions]: active sessions"); 10645 pw.println(" d[isplays]: active display contents"); 10646 pw.println(" t[okens]: token list"); 10647 pw.println(" w[indows]: window list"); 10648 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10649 pw.println(" be a partial substring in a window name, a"); 10650 pw.println(" Window hex object identifier, or"); 10651 pw.println(" \"all\" for all windows, or"); 10652 pw.println(" \"visible\" for the visible windows."); 10653 pw.println(" -a: include all available server state."); 10654 return; 10655 } else { 10656 pw.println("Unknown argument: " + opt + "; use -h for help"); 10657 } 10658 } 10659 10660 // Is the caller requesting to dump a particular piece of data? 10661 if (opti < args.length) { 10662 String cmd = args[opti]; 10663 opti++; 10664 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10665 synchronized(mWindowMap) { 10666 dumpLastANRLocked(pw); 10667 } 10668 return; 10669 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10670 synchronized(mWindowMap) { 10671 dumpPolicyLocked(pw, args, true); 10672 } 10673 return; 10674 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 10675 synchronized(mWindowMap) { 10676 dumpAnimatorLocked(pw, args, true); 10677 } 10678 return; 10679 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10680 synchronized(mWindowMap) { 10681 dumpSessionsLocked(pw, true); 10682 } 10683 return; 10684 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 10685 synchronized(mWindowMap) { 10686 dumpDisplayContentsLocked(pw, true); 10687 } 10688 return; 10689 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10690 synchronized(mWindowMap) { 10691 dumpTokensLocked(pw, true); 10692 } 10693 return; 10694 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10695 synchronized(mWindowMap) { 10696 dumpWindowsLocked(pw, true, null); 10697 } 10698 return; 10699 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10700 synchronized(mWindowMap) { 10701 dumpWindowsLocked(pw, true, null); 10702 } 10703 return; 10704 } else { 10705 // Dumping a single name? 10706 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10707 pw.println("Bad window command, or no windows match: " + cmd); 10708 pw.println("Use -h for help."); 10709 } 10710 return; 10711 } 10712 } 10713 10714 synchronized(mWindowMap) { 10715 pw.println(); 10716 if (dumpAll) { 10717 pw.println("-------------------------------------------------------------------------------"); 10718 } 10719 dumpLastANRLocked(pw); 10720 pw.println(); 10721 if (dumpAll) { 10722 pw.println("-------------------------------------------------------------------------------"); 10723 } 10724 dumpPolicyLocked(pw, args, dumpAll); 10725 pw.println(); 10726 if (dumpAll) { 10727 pw.println("-------------------------------------------------------------------------------"); 10728 } 10729 dumpAnimatorLocked(pw, args, dumpAll); 10730 pw.println(); 10731 if (dumpAll) { 10732 pw.println("-------------------------------------------------------------------------------"); 10733 } 10734 dumpSessionsLocked(pw, dumpAll); 10735 pw.println(); 10736 if (dumpAll) { 10737 pw.println("-------------------------------------------------------------------------------"); 10738 } 10739 dumpDisplayContentsLocked(pw, dumpAll); 10740 pw.println(); 10741 if (dumpAll) { 10742 pw.println("-------------------------------------------------------------------------------"); 10743 } 10744 dumpTokensLocked(pw, dumpAll); 10745 pw.println(); 10746 if (dumpAll) { 10747 pw.println("-------------------------------------------------------------------------------"); 10748 } 10749 dumpWindowsLocked(pw, dumpAll, null); 10750 } 10751 } 10752 10753 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10754 @Override 10755 public void monitor() { 10756 synchronized (mWindowMap) { } 10757 } 10758 10759 public interface OnHardKeyboardStatusChangeListener { 10760 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 10761 } 10762 10763 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 10764 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 10765 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 10766 Integer.toHexString(pendingLayoutChanges)); 10767 } 10768 } 10769 10770 private DisplayContent newDisplayContentLocked(final Display display) { 10771 DisplayContent displayContent = new DisplayContent(display, this); 10772 final int displayId = display.getDisplayId(); 10773 mDisplayContents.put(displayId, displayContent); 10774 10775 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10776 final Rect rect = new Rect(); 10777 mDisplaySettings.getOverscanLocked(displayInfo.name, rect); 10778 synchronized (displayContent.mDisplaySizeLock) { 10779 displayInfo.overscanLeft = rect.left; 10780 displayInfo.overscanTop = rect.top; 10781 displayInfo.overscanRight = rect.right; 10782 displayInfo.overscanBottom = rect.bottom; 10783 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 10784 displayId, displayInfo); 10785 } 10786 configureDisplayPolicyLocked(displayContent); 10787 10788 // TODO: Create an input channel for each display with touch capability. 10789 if (displayId == Display.DEFAULT_DISPLAY) { 10790 displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent); 10791 registerPointerEventListener(displayContent.mTapDetector); 10792 } 10793 10794 return displayContent; 10795 } 10796 10797 public void createDisplayContentLocked(final Display display) { 10798 if (display == null) { 10799 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 10800 } 10801 getDisplayContentLocked(display.getDisplayId()); 10802 } 10803 10804 /** 10805 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 10806 * there is a Display for the displayId. 10807 * @param displayId The display the caller is interested in. 10808 * @return The DisplayContent associated with displayId or null if there is no Display for it. 10809 */ 10810 public DisplayContent getDisplayContentLocked(final int displayId) { 10811 DisplayContent displayContent = mDisplayContents.get(displayId); 10812 if (displayContent == null) { 10813 final Display display = mDisplayManager.getDisplay(displayId); 10814 if (display != null) { 10815 displayContent = newDisplayContentLocked(display); 10816 } 10817 } 10818 return displayContent; 10819 } 10820 10821 // There is an inherent assumption that this will never return null. 10822 public DisplayContent getDefaultDisplayContentLocked() { 10823 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 10824 } 10825 10826 public WindowList getDefaultWindowListLocked() { 10827 return getDefaultDisplayContentLocked().getWindowList(); 10828 } 10829 10830 public DisplayInfo getDefaultDisplayInfoLocked() { 10831 return getDefaultDisplayContentLocked().getDisplayInfo(); 10832 } 10833 10834 /** 10835 * Return the list of WindowStates associated on the passed display. 10836 * @param display The screen to return windows from. 10837 * @return The list of WindowStates on the screen, or null if the there is no screen. 10838 */ 10839 public WindowList getWindowListLocked(final Display display) { 10840 return getWindowListLocked(display.getDisplayId()); 10841 } 10842 10843 /** 10844 * Return the list of WindowStates associated on the passed display. 10845 * @param displayId The screen to return windows from. 10846 * @return The list of WindowStates on the screen, or null if the there is no screen. 10847 */ 10848 public WindowList getWindowListLocked(final int displayId) { 10849 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10850 return displayContent != null ? displayContent.getWindowList() : null; 10851 } 10852 10853 public void onDisplayAdded(int displayId) { 10854 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 10855 } 10856 10857 public void handleDisplayAdded(int displayId) { 10858 synchronized (mWindowMap) { 10859 final Display display = mDisplayManager.getDisplay(displayId); 10860 if (display != null) { 10861 createDisplayContentLocked(display); 10862 displayReady(displayId); 10863 } 10864 } 10865 } 10866 10867 public void onDisplayRemoved(int displayId) { 10868 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 10869 } 10870 10871 private void handleDisplayRemovedLocked(int displayId) { 10872 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10873 if (displayContent != null) { 10874 if ((displayContent.mDeferredActions & DisplayContent.DEFER_DETACH) != 0) { 10875 displayContent.mDeferredActions |= DisplayContent.DEFER_REMOVAL; 10876 return; 10877 } 10878 mDisplayContents.delete(displayId); 10879 displayContent.close(); 10880 if (displayId == Display.DEFAULT_DISPLAY) { 10881 unregisterPointerEventListener(displayContent.mTapDetector); 10882 } 10883 } 10884 mAnimator.removeDisplayLocked(displayId); 10885 } 10886 10887 public void onDisplayChanged(int displayId) { 10888 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 10889 } 10890 10891 private void handleDisplayChangedLocked(int displayId) { 10892 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10893 if (displayContent != null) { 10894 displayContent.updateDisplayInfo(); 10895 } 10896 } 10897 10898 @Override 10899 public Object getWindowManagerLock() { 10900 return mWindowMap; 10901 } 10902 10903 private final class LocalService extends WindowManagerInternal { 10904 @Override 10905 public void requestTraversalFromDisplayManager() { 10906 requestTraversal(); 10907 } 10908 } 10909} 10910