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