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