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