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