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