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