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