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