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