WindowManagerService.java revision 368c5adaf7a1141bfee3cf622efbc7285e370979
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 ArraySet<AppWindowToken> mOpeningApps = new ArraySet<AppWindowToken>(); 501 final ArraySet<AppWindowToken> mClosingApps = new ArraySet<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 if (atoken.mLaunchTaskBehind) { 3238 // Differentiate the two animations. This one which is briefly on the screen 3239 // gets the !enter animation, and the other activity which remains on the 3240 // screen gets the enter animation. Both appear in the mOpeningApps set. 3241 enter = false; 3242 } 3243 Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height, 3244 mCurConfiguration.orientation, containingFrame, contentInsets, isFullScreen, 3245 isVoiceInteraction); 3246 if (a != null) { 3247 if (DEBUG_ANIM) { 3248 RuntimeException e = null; 3249 if (!HIDE_STACK_CRAWLS) { 3250 e = new RuntimeException(); 3251 e.fillInStackTrace(); 3252 } 3253 Slog.v(TAG, "Loaded animation " + a + " for " + atoken, e); 3254 } 3255 atoken.mAppAnimator.setAnimation(a, width, height); 3256 } 3257 } else { 3258 atoken.mAppAnimator.clearAnimation(); 3259 } 3260 3261 return atoken.mAppAnimator.animation != null; 3262 } 3263 3264 // ------------------------------------------------------------- 3265 // Application Window Tokens 3266 // ------------------------------------------------------------- 3267 3268 public void validateAppTokens(int stackId, List<TaskGroup> tasks) { 3269 synchronized (mWindowMap) { 3270 int t = tasks.size() - 1; 3271 if (t < 0) { 3272 Slog.w(TAG, "validateAppTokens: empty task list"); 3273 return; 3274 } 3275 3276 TaskGroup task = tasks.get(0); 3277 int taskId = task.taskId; 3278 Task targetTask = mTaskIdToTask.get(taskId); 3279 DisplayContent displayContent = targetTask.getDisplayContent(); 3280 if (displayContent == null) { 3281 Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId); 3282 return; 3283 } 3284 3285 final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks(); 3286 int taskNdx; 3287 for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) { 3288 AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens; 3289 task = tasks.get(t); 3290 List<IApplicationToken> tokens = task.tokens; 3291 3292 DisplayContent lastDisplayContent = displayContent; 3293 displayContent = mTaskIdToTask.get(taskId).getDisplayContent(); 3294 if (displayContent != lastDisplayContent) { 3295 Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!"); 3296 return; 3297 } 3298 3299 int tokenNdx; 3300 int v; 3301 for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1; 3302 tokenNdx >= 0 && v >= 0; ) { 3303 final AppWindowToken atoken = localTokens.get(tokenNdx); 3304 if (atoken.removed) { 3305 --tokenNdx; 3306 continue; 3307 } 3308 if (tokens.get(v) != atoken.token) { 3309 break; 3310 } 3311 --tokenNdx; 3312 v--; 3313 } 3314 3315 if (tokenNdx >= 0 || v >= 0) { 3316 break; 3317 } 3318 } 3319 3320 if (taskNdx >= 0 || t >= 0) { 3321 Slog.w(TAG, "validateAppTokens: Mismatch! ActivityManager=" + tasks); 3322 Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager=" + localTasks); 3323 Slog.w(TAG, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4)); 3324 } 3325 } 3326 } 3327 3328 public void validateStackOrder(Integer[] remoteStackIds) { 3329 // TODO: 3330 } 3331 3332 boolean checkCallingPermission(String permission, String func) { 3333 // Quick check: if the calling permission is me, it's all okay. 3334 if (Binder.getCallingPid() == Process.myPid()) { 3335 return true; 3336 } 3337 3338 if (mContext.checkCallingPermission(permission) 3339 == PackageManager.PERMISSION_GRANTED) { 3340 return true; 3341 } 3342 String msg = "Permission Denial: " + func + " from pid=" 3343 + Binder.getCallingPid() 3344 + ", uid=" + Binder.getCallingUid() 3345 + " requires " + permission; 3346 Slog.w(TAG, msg); 3347 return false; 3348 } 3349 3350 boolean okToDisplay() { 3351 return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully(); 3352 } 3353 3354 AppWindowToken findAppWindowToken(IBinder token) { 3355 WindowToken wtoken = mTokenMap.get(token); 3356 if (wtoken == null) { 3357 return null; 3358 } 3359 return wtoken.appWindowToken; 3360 } 3361 3362 @Override 3363 public void addWindowToken(IBinder token, int type) { 3364 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3365 "addWindowToken()")) { 3366 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3367 } 3368 3369 synchronized(mWindowMap) { 3370 WindowToken wtoken = mTokenMap.get(token); 3371 if (wtoken != null) { 3372 Slog.w(TAG, "Attempted to add existing input method token: " + token); 3373 return; 3374 } 3375 wtoken = new WindowToken(this, token, type, true); 3376 mTokenMap.put(token, wtoken); 3377 if (type == TYPE_WALLPAPER) { 3378 mWallpaperTokens.add(wtoken); 3379 } 3380 } 3381 } 3382 3383 @Override 3384 public void removeWindowToken(IBinder token) { 3385 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3386 "removeWindowToken()")) { 3387 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3388 } 3389 3390 final long origId = Binder.clearCallingIdentity(); 3391 synchronized(mWindowMap) { 3392 DisplayContent displayContent = null; 3393 WindowToken wtoken = mTokenMap.remove(token); 3394 if (wtoken != null) { 3395 boolean delayed = false; 3396 if (!wtoken.hidden) { 3397 final int N = wtoken.windows.size(); 3398 boolean changed = false; 3399 3400 for (int i=0; i<N; i++) { 3401 WindowState win = wtoken.windows.get(i); 3402 displayContent = win.getDisplayContent(); 3403 3404 if (win.mWinAnimator.isAnimating()) { 3405 delayed = true; 3406 } 3407 3408 if (win.isVisibleNow()) { 3409 win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, 3410 false); 3411 //TODO (multidisplay): Magnification is supported only for the default 3412 if (mAccessibilityController != null && win.isDefaultDisplay()) { 3413 mAccessibilityController.onWindowTransitionLocked(win, 3414 WindowManagerPolicy.TRANSIT_EXIT); 3415 } 3416 changed = true; 3417 if (displayContent != null) { 3418 displayContent.layoutNeeded = true; 3419 } 3420 } 3421 } 3422 3423 wtoken.hidden = true; 3424 3425 if (changed) { 3426 performLayoutAndPlaceSurfacesLocked(); 3427 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, 3428 false /*updateInputWindows*/); 3429 } 3430 3431 if (delayed) { 3432 if (displayContent != null) { 3433 displayContent.mExitingTokens.add(wtoken); 3434 } 3435 } else if (wtoken.windowType == TYPE_WALLPAPER) { 3436 mWallpaperTokens.remove(wtoken); 3437 } 3438 } 3439 3440 mInputMonitor.updateInputWindowsLw(true /*force*/); 3441 } else { 3442 Slog.w(TAG, "Attempted to remove non-existing token: " + token); 3443 } 3444 } 3445 Binder.restoreCallingIdentity(origId); 3446 } 3447 3448 private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) { 3449 if (DEBUG_STACK) Slog.i(TAG, "createTask: taskId=" + taskId + " stackId=" + stackId 3450 + " atoken=" + atoken); 3451 final TaskStack stack = mStackIdToStack.get(stackId); 3452 if (stack == null) { 3453 throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId); 3454 } 3455 EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId); 3456 Task task = new Task(atoken, stack, userId); 3457 mTaskIdToTask.put(taskId, task); 3458 stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */); 3459 return task; 3460 } 3461 3462 @Override 3463 public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId, 3464 int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId, 3465 int configChanges, boolean voiceInteraction, boolean launchTaskBehind) { 3466 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3467 "addAppToken()")) { 3468 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3469 } 3470 3471 // Get the dispatching timeout here while we are not holding any locks so that it 3472 // can be cached by the AppWindowToken. The timeout value is used later by the 3473 // input dispatcher in code that does hold locks. If we did not cache the value 3474 // here we would run the chance of introducing a deadlock between the window manager 3475 // (which holds locks while updating the input dispatcher state) and the activity manager 3476 // (which holds locks while querying the application token). 3477 long inputDispatchingTimeoutNanos; 3478 try { 3479 inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L; 3480 } catch (RemoteException ex) { 3481 Slog.w(TAG, "Could not get dispatching timeout.", ex); 3482 inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 3483 } 3484 3485 synchronized(mWindowMap) { 3486 AppWindowToken atoken = findAppWindowToken(token.asBinder()); 3487 if (atoken != null) { 3488 Slog.w(TAG, "Attempted to add existing app token: " + token); 3489 return; 3490 } 3491 atoken = new AppWindowToken(this, token, voiceInteraction); 3492 atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos; 3493 atoken.groupId = taskId; 3494 atoken.appFullscreen = fullscreen; 3495 atoken.showWhenLocked = showWhenLocked; 3496 atoken.requestedOrientation = requestedOrientation; 3497 atoken.layoutConfigChanges = (configChanges & 3498 (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0; 3499 atoken.mLaunchTaskBehind = launchTaskBehind; 3500 if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken 3501 + " to stack=" + stackId + " task=" + taskId + " at " + addPos); 3502 3503 Task task = mTaskIdToTask.get(taskId); 3504 if (task == null) { 3505 createTask(taskId, stackId, userId, atoken); 3506 } else { 3507 task.addAppToken(addPos, atoken); 3508 } 3509 3510 mTokenMap.put(token.asBinder(), atoken); 3511 3512 // Application tokens start out hidden. 3513 atoken.hidden = true; 3514 atoken.hiddenRequested = true; 3515 3516 //dump(); 3517 } 3518 } 3519 3520 @Override 3521 public void setAppGroupId(IBinder token, int groupId) { 3522 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3523 "setAppGroupId()")) { 3524 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3525 } 3526 3527 synchronized(mWindowMap) { 3528 final AppWindowToken atoken = findAppWindowToken(token); 3529 if (atoken == null) { 3530 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token); 3531 return; 3532 } 3533 final Task oldTask = mTaskIdToTask.get(atoken.groupId); 3534 removeAppFromTaskLocked(atoken); 3535 3536 atoken.groupId = groupId; 3537 Task newTask = mTaskIdToTask.get(groupId); 3538 if (newTask == null) { 3539 newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken); 3540 } else { 3541 newTask.mAppTokens.add(atoken); 3542 } 3543 } 3544 } 3545 3546 public int getOrientationFromWindowsLocked() { 3547 if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 3548 // If the display is frozen, some activities may be in the middle 3549 // of restarting, and thus have removed their old window. If the 3550 // window has the flag to hide the lock screen, then the lock screen 3551 // can re-appear and inflict its own orientation on us. Keep the 3552 // orientation stable until this all settles down. 3553 return mLastWindowForcedOrientation; 3554 } 3555 3556 // TODO(multidisplay): Change to the correct display. 3557 final WindowList windows = getDefaultWindowListLocked(); 3558 int pos = windows.size() - 1; 3559 while (pos >= 0) { 3560 WindowState win = windows.get(pos); 3561 pos--; 3562 if (win.mAppToken != null) { 3563 // We hit an application window. so the orientation will be determined by the 3564 // app window. No point in continuing further. 3565 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3566 } 3567 if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) { 3568 continue; 3569 } 3570 int req = win.mAttrs.screenOrientation; 3571 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) || 3572 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){ 3573 continue; 3574 } 3575 3576 if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req); 3577 return (mLastWindowForcedOrientation=req); 3578 } 3579 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3580 } 3581 3582 public int getOrientationFromAppTokensLocked() { 3583 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3584 boolean findingBehind = false; 3585 boolean lastFullscreen = false; 3586 // TODO: Multi window. 3587 DisplayContent displayContent = getDefaultDisplayContentLocked(); 3588 final ArrayList<Task> tasks = displayContent.getTasks(); 3589 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 3590 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 3591 final int firstToken = tokens.size() - 1; 3592 for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) { 3593 final AppWindowToken atoken = tokens.get(tokenNdx); 3594 3595 if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken); 3596 3597 // if we're about to tear down this window and not seek for 3598 // the behind activity, don't use it for orientation 3599 if (!findingBehind 3600 && (!atoken.hidden && atoken.hiddenRequested)) { 3601 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken 3602 + " -- going to hide"); 3603 continue; 3604 } 3605 3606 if (tokenNdx == firstToken) { 3607 // If we have hit a new Task, and the bottom 3608 // of the previous group didn't explicitly say to use 3609 // the orientation behind it, and the last app was 3610 // full screen, then we'll stick with the 3611 // user's orientation. 3612 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND 3613 && lastFullscreen) { 3614 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3615 + " -- end of group, return " + lastOrientation); 3616 return lastOrientation; 3617 } 3618 } 3619 3620 // We ignore any hidden applications on the top. 3621 if (atoken.hiddenRequested || atoken.willBeHidden) { 3622 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken 3623 + " -- hidden on top"); 3624 continue; 3625 } 3626 3627 if (tokenNdx == 0) { 3628 // Last token in this task. 3629 lastOrientation = atoken.requestedOrientation; 3630 } 3631 3632 int or = atoken.requestedOrientation; 3633 // If this application is fullscreen, and didn't explicitly say 3634 // to use the orientation behind it, then just take whatever 3635 // orientation it has and ignores whatever is under it. 3636 lastFullscreen = atoken.appFullscreen; 3637 if (lastFullscreen 3638 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { 3639 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3640 + " -- full screen, return " + or); 3641 return or; 3642 } 3643 // If this application has requested an explicit orientation, 3644 // then use it. 3645 if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 3646 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { 3647 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3648 + " -- explicitly set, return " + or); 3649 return or; 3650 } 3651 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND); 3652 } 3653 } 3654 if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation"); 3655 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3656 } 3657 3658 @Override 3659 public Configuration updateOrientationFromAppTokens( 3660 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3661 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3662 "updateOrientationFromAppTokens()")) { 3663 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3664 } 3665 3666 Configuration config = null; 3667 long ident = Binder.clearCallingIdentity(); 3668 3669 synchronized(mWindowMap) { 3670 config = updateOrientationFromAppTokensLocked(currentConfig, 3671 freezeThisOneIfNeeded); 3672 } 3673 3674 Binder.restoreCallingIdentity(ident); 3675 return config; 3676 } 3677 3678 private Configuration updateOrientationFromAppTokensLocked( 3679 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3680 Configuration config = null; 3681 3682 if (updateOrientationFromAppTokensLocked(false)) { 3683 if (freezeThisOneIfNeeded != null) { 3684 AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded); 3685 if (atoken != null) { 3686 startAppFreezingScreenLocked(atoken); 3687 } 3688 } 3689 config = computeNewConfigurationLocked(); 3690 3691 } else if (currentConfig != null) { 3692 // No obvious action we need to take, but if our current 3693 // state mismatches the activity manager's, update it, 3694 // disregarding font scale, which should remain set to 3695 // the value of the previous configuration. 3696 mTempConfiguration.setToDefaults(); 3697 mTempConfiguration.fontScale = currentConfig.fontScale; 3698 if (computeScreenConfigurationLocked(mTempConfiguration)) { 3699 if (currentConfig.diff(mTempConfiguration) != 0) { 3700 mWaitingForConfig = true; 3701 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 3702 displayContent.layoutNeeded = true; 3703 int anim[] = new int[2]; 3704 if (displayContent.isDimming()) { 3705 anim[0] = anim[1] = 0; 3706 } else { 3707 mPolicy.selectRotationAnimationLw(anim); 3708 } 3709 startFreezingDisplayLocked(false, anim[0], anim[1]); 3710 config = new Configuration(mTempConfiguration); 3711 } 3712 } 3713 } 3714 3715 return config; 3716 } 3717 3718 /* 3719 * Determine the new desired orientation of the display, returning 3720 * a non-null new Configuration if it has changed from the current 3721 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL 3722 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE 3723 * SCREEN. This will typically be done for you if you call 3724 * sendNewConfiguration(). 3725 * 3726 * The orientation is computed from non-application windows first. If none of 3727 * the non-application windows specify orientation, the orientation is computed from 3728 * application tokens. 3729 * @see android.view.IWindowManager#updateOrientationFromAppTokens( 3730 * android.os.IBinder) 3731 */ 3732 boolean updateOrientationFromAppTokensLocked(boolean inTransaction) { 3733 long ident = Binder.clearCallingIdentity(); 3734 try { 3735 int req = getOrientationFromWindowsLocked(); 3736 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) { 3737 req = getOrientationFromAppTokensLocked(); 3738 } 3739 3740 if (req != mForcedAppOrientation) { 3741 mForcedAppOrientation = req; 3742 //send a message to Policy indicating orientation change to take 3743 //action like disabling/enabling sensors etc., 3744 mPolicy.setCurrentOrientationLw(req); 3745 if (updateRotationUncheckedLocked(inTransaction)) { 3746 // changed 3747 return true; 3748 } 3749 } 3750 3751 return false; 3752 } finally { 3753 Binder.restoreCallingIdentity(ident); 3754 } 3755 } 3756 3757 @Override 3758 public void setNewConfiguration(Configuration config) { 3759 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3760 "setNewConfiguration()")) { 3761 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3762 } 3763 3764 synchronized(mWindowMap) { 3765 mCurConfiguration = new Configuration(config); 3766 if (mWaitingForConfig) { 3767 mWaitingForConfig = false; 3768 mLastFinishedFreezeSource = "new-config"; 3769 } 3770 performLayoutAndPlaceSurfacesLocked(); 3771 } 3772 } 3773 3774 @Override 3775 public void setAppOrientation(IApplicationToken token, int requestedOrientation) { 3776 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3777 "setAppOrientation()")) { 3778 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3779 } 3780 3781 synchronized(mWindowMap) { 3782 AppWindowToken atoken = findAppWindowToken(token.asBinder()); 3783 if (atoken == null) { 3784 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token); 3785 return; 3786 } 3787 3788 atoken.requestedOrientation = requestedOrientation; 3789 } 3790 } 3791 3792 @Override 3793 public int getAppOrientation(IApplicationToken token) { 3794 synchronized(mWindowMap) { 3795 AppWindowToken wtoken = findAppWindowToken(token.asBinder()); 3796 if (wtoken == null) { 3797 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3798 } 3799 3800 return wtoken.requestedOrientation; 3801 } 3802 } 3803 3804 /** Call while in a Surface transaction. */ 3805 void setFocusedStackLayer() { 3806 mFocusedStackLayer = 0; 3807 if (mFocusedApp != null) { 3808 final WindowList windows = mFocusedApp.allAppWindows; 3809 for (int i = windows.size() - 1; i >= 0; --i) { 3810 final WindowState win = windows.get(i); 3811 final int animLayer = win.mWinAnimator.mAnimLayer; 3812 if (win.mAttachedWindow == null && win.isVisibleLw() && 3813 animLayer > mFocusedStackLayer) { 3814 mFocusedStackLayer = animLayer + LAYER_OFFSET_FOCUSED_STACK; 3815 } 3816 } 3817 } 3818 if (DEBUG_LAYERS) Slog.v(TAG, "Setting FocusedStackFrame to layer=" + 3819 mFocusedStackLayer); 3820 mFocusedStackFrame.setLayer(mFocusedStackLayer); 3821 } 3822 3823 void setFocusedStackFrame() { 3824 final TaskStack stack; 3825 if (mFocusedApp != null) { 3826 Task task = mTaskIdToTask.get(mFocusedApp.groupId); 3827 stack = task.mStack; 3828 final DisplayContent displayContent = task.getDisplayContent(); 3829 if (displayContent != null) { 3830 displayContent.setTouchExcludeRegion(stack); 3831 } 3832 } else { 3833 stack = null; 3834 } 3835 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame"); 3836 SurfaceControl.openTransaction(); 3837 try { 3838 if (stack == null) { 3839 mFocusedStackFrame.setVisibility(false); 3840 } else { 3841 mFocusedStackFrame.setBounds(stack); 3842 final boolean multipleStacks = !stack.isFullscreen(); 3843 mFocusedStackFrame.setVisibility(multipleStacks); 3844 } 3845 } finally { 3846 SurfaceControl.closeTransaction(); 3847 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame"); 3848 } 3849 } 3850 3851 @Override 3852 public void setFocusedApp(IBinder token, boolean moveFocusNow) { 3853 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3854 "setFocusedApp()")) { 3855 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3856 } 3857 3858 synchronized(mWindowMap) { 3859 final AppWindowToken newFocus; 3860 if (token == null) { 3861 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp); 3862 newFocus = null; 3863 } else { 3864 newFocus = findAppWindowToken(token); 3865 if (newFocus == null) { 3866 Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token); 3867 } 3868 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus 3869 + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow); 3870 } 3871 3872 final boolean changed = mFocusedApp != newFocus; 3873 if (changed) { 3874 mFocusedApp = newFocus; 3875 mInputMonitor.setFocusedAppLw(null); 3876 } 3877 3878 if (moveFocusNow && changed) { 3879 final long origId = Binder.clearCallingIdentity(); 3880 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 3881 Binder.restoreCallingIdentity(origId); 3882 } 3883 } 3884 } 3885 3886 @Override 3887 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) { 3888 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3889 "prepareAppTransition()")) { 3890 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3891 } 3892 3893 synchronized(mWindowMap) { 3894 if (DEBUG_APP_TRANSITIONS) Slog.v( 3895 TAG, "Prepare app transition: transit=" + transit 3896 + " " + mAppTransition 3897 + " alwaysKeepCurrent=" + alwaysKeepCurrent 3898 + " Callers=" + Debug.getCallers(3)); 3899 if (!mAppTransition.isTransitionSet() || mAppTransition.isTransitionNone()) { 3900 mAppTransition.setAppTransition(transit); 3901 } else if (!alwaysKeepCurrent) { 3902 if (transit == AppTransition.TRANSIT_TASK_OPEN 3903 && mAppTransition.isTransitionEqual( 3904 AppTransition.TRANSIT_TASK_CLOSE)) { 3905 // Opening a new task always supersedes a close for the anim. 3906 mAppTransition.setAppTransition(transit); 3907 } else if (transit == AppTransition.TRANSIT_ACTIVITY_OPEN 3908 && mAppTransition.isTransitionEqual( 3909 AppTransition.TRANSIT_ACTIVITY_CLOSE)) { 3910 // Opening a new activity always supersedes a close for the anim. 3911 mAppTransition.setAppTransition(transit); 3912 } 3913 } 3914 if (okToDisplay()) { 3915 mAppTransition.prepare(); 3916 mStartingIconInTransition = false; 3917 mSkipAppTransitionAnimation = false; 3918 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 3919 mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000); 3920 } 3921 } 3922 } 3923 3924 @Override 3925 public int getPendingAppTransition() { 3926 return mAppTransition.getAppTransition(); 3927 } 3928 3929 @Override 3930 public void overridePendingAppTransition(String packageName, 3931 int enterAnim, int exitAnim, IRemoteCallback startedCallback) { 3932 synchronized(mWindowMap) { 3933 mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim, 3934 startedCallback); 3935 } 3936 } 3937 3938 @Override 3939 public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, 3940 int startHeight) { 3941 synchronized(mWindowMap) { 3942 mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth, 3943 startHeight); 3944 } 3945 } 3946 3947 @Override 3948 public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, 3949 int startY, IRemoteCallback startedCallback, boolean scaleUp) { 3950 synchronized(mWindowMap) { 3951 mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY, 3952 startedCallback, scaleUp); 3953 } 3954 } 3955 3956 @Override 3957 public void executeAppTransition() { 3958 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3959 "executeAppTransition()")) { 3960 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3961 } 3962 3963 synchronized(mWindowMap) { 3964 if (DEBUG_APP_TRANSITIONS) Slog.w(TAG, "Execute app transition: " + mAppTransition, 3965 new RuntimeException("here").fillInStackTrace()); 3966 if (mAppTransition.isTransitionSet()) { 3967 mAppTransition.setReady(); 3968 final long origId = Binder.clearCallingIdentity(); 3969 try { 3970 performLayoutAndPlaceSurfacesLocked(); 3971 } finally { 3972 Binder.restoreCallingIdentity(origId); 3973 } 3974 } 3975 } 3976 } 3977 3978 @Override 3979 public void setAppStartingWindow(IBinder token, String pkg, 3980 int theme, CompatibilityInfo compatInfo, 3981 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, 3982 int windowFlags, IBinder transferFrom, boolean createIfNeeded) { 3983 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3984 "setAppStartingWindow()")) { 3985 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3986 } 3987 3988 synchronized(mWindowMap) { 3989 if (DEBUG_STARTING_WINDOW) Slog.v( 3990 TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg 3991 + " transferFrom=" + transferFrom); 3992 3993 AppWindowToken wtoken = findAppWindowToken(token); 3994 if (wtoken == null) { 3995 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token); 3996 return; 3997 } 3998 3999 // If the display is frozen, we won't do anything until the 4000 // actual window is displayed so there is no reason to put in 4001 // the starting window. 4002 if (!okToDisplay()) { 4003 return; 4004 } 4005 4006 if (wtoken.startingData != null) { 4007 return; 4008 } 4009 4010 if (transferFrom != null) { 4011 AppWindowToken ttoken = findAppWindowToken(transferFrom); 4012 if (ttoken != null) { 4013 WindowState startingWindow = ttoken.startingWindow; 4014 if (startingWindow != null) { 4015 if (mStartingIconInTransition) { 4016 // In this case, the starting icon has already 4017 // been displayed, so start letting windows get 4018 // shown immediately without any more transitions. 4019 mSkipAppTransitionAnimation = true; 4020 } 4021 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4022 "Moving existing starting " + startingWindow + " from " + ttoken 4023 + " to " + wtoken); 4024 final long origId = Binder.clearCallingIdentity(); 4025 4026 // Transfer the starting window over to the new 4027 // token. 4028 wtoken.startingData = ttoken.startingData; 4029 wtoken.startingView = ttoken.startingView; 4030 wtoken.startingDisplayed = ttoken.startingDisplayed; 4031 ttoken.startingDisplayed = false; 4032 wtoken.startingWindow = startingWindow; 4033 wtoken.reportedVisible = ttoken.reportedVisible; 4034 ttoken.startingData = null; 4035 ttoken.startingView = null; 4036 ttoken.startingWindow = null; 4037 ttoken.startingMoved = true; 4038 startingWindow.mToken = wtoken; 4039 startingWindow.mRootToken = wtoken; 4040 startingWindow.mAppToken = wtoken; 4041 startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator; 4042 4043 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) { 4044 Slog.v(TAG, "Removing starting window: " + startingWindow); 4045 } 4046 startingWindow.getWindowList().remove(startingWindow); 4047 mWindowsChanged = true; 4048 if (DEBUG_ADD_REMOVE) Slog.v(TAG, 4049 "Removing starting " + startingWindow + " from " + ttoken); 4050 ttoken.windows.remove(startingWindow); 4051 ttoken.allAppWindows.remove(startingWindow); 4052 addWindowToListInOrderLocked(startingWindow, true); 4053 4054 // Propagate other interesting state between the 4055 // tokens. If the old token is displayed, we should 4056 // immediately force the new one to be displayed. If 4057 // it is animating, we need to move that animation to 4058 // the new one. 4059 if (ttoken.allDrawn) { 4060 wtoken.allDrawn = true; 4061 wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn; 4062 } 4063 if (ttoken.firstWindowDrawn) { 4064 wtoken.firstWindowDrawn = true; 4065 } 4066 if (!ttoken.hidden) { 4067 wtoken.hidden = false; 4068 wtoken.hiddenRequested = false; 4069 wtoken.willBeHidden = false; 4070 } 4071 if (wtoken.clientHidden != ttoken.clientHidden) { 4072 wtoken.clientHidden = ttoken.clientHidden; 4073 wtoken.sendAppVisibilityToClients(); 4074 } 4075 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4076 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4077 if (tAppAnimator.animation != null) { 4078 wAppAnimator.animation = tAppAnimator.animation; 4079 wAppAnimator.animating = tAppAnimator.animating; 4080 wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment; 4081 tAppAnimator.animation = null; 4082 tAppAnimator.animLayerAdjustment = 0; 4083 wAppAnimator.updateLayers(); 4084 tAppAnimator.updateLayers(); 4085 } 4086 4087 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4088 true /*updateInputWindows*/); 4089 getDefaultDisplayContentLocked().layoutNeeded = true; 4090 performLayoutAndPlaceSurfacesLocked(); 4091 Binder.restoreCallingIdentity(origId); 4092 return; 4093 } else if (ttoken.startingData != null) { 4094 // The previous app was getting ready to show a 4095 // starting window, but hasn't yet done so. Steal it! 4096 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4097 "Moving pending starting from " + ttoken 4098 + " to " + wtoken); 4099 wtoken.startingData = ttoken.startingData; 4100 ttoken.startingData = null; 4101 ttoken.startingMoved = true; 4102 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4103 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4104 // want to process the message ASAP, before any other queued 4105 // messages. 4106 mH.sendMessageAtFrontOfQueue(m); 4107 return; 4108 } 4109 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4110 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4111 if (tAppAnimator.thumbnail != null) { 4112 // The old token is animating with a thumbnail, transfer 4113 // that to the new token. 4114 if (wAppAnimator.thumbnail != null) { 4115 wAppAnimator.thumbnail.destroy(); 4116 } 4117 wAppAnimator.thumbnail = tAppAnimator.thumbnail; 4118 wAppAnimator.thumbnailX = tAppAnimator.thumbnailX; 4119 wAppAnimator.thumbnailY = tAppAnimator.thumbnailY; 4120 wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer; 4121 wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation; 4122 tAppAnimator.thumbnail = null; 4123 } 4124 } 4125 } 4126 4127 // There is no existing starting window, and the caller doesn't 4128 // want us to create one, so that's it! 4129 if (!createIfNeeded) { 4130 return; 4131 } 4132 4133 // If this is a translucent window, then don't 4134 // show a starting window -- the current effect (a full-screen 4135 // opaque starting window that fades away to the real contents 4136 // when it is ready) does not work for this. 4137 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x" 4138 + Integer.toHexString(theme)); 4139 if (theme != 0) { 4140 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme, 4141 com.android.internal.R.styleable.Window, mCurrentUserId); 4142 if (ent == null) { 4143 // Whoops! App doesn't exist. Um. Okay. We'll just 4144 // pretend like we didn't see that. 4145 return; 4146 } 4147 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent=" 4148 + ent.array.getBoolean( 4149 com.android.internal.R.styleable.Window_windowIsTranslucent, false) 4150 + " Floating=" 4151 + ent.array.getBoolean( 4152 com.android.internal.R.styleable.Window_windowIsFloating, false) 4153 + " ShowWallpaper=" 4154 + ent.array.getBoolean( 4155 com.android.internal.R.styleable.Window_windowShowWallpaper, false)); 4156 if (ent.array.getBoolean( 4157 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) { 4158 return; 4159 } 4160 if (ent.array.getBoolean( 4161 com.android.internal.R.styleable.Window_windowIsFloating, false)) { 4162 return; 4163 } 4164 if (ent.array.getBoolean( 4165 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) { 4166 if (mWallpaperTarget == null) { 4167 // If this theme is requesting a wallpaper, and the wallpaper 4168 // is not curently visible, then this effectively serves as 4169 // an opaque window and our starting window transition animation 4170 // can still work. We just need to make sure the starting window 4171 // is also showing the wallpaper. 4172 windowFlags |= FLAG_SHOW_WALLPAPER; 4173 } else { 4174 return; 4175 } 4176 } 4177 } 4178 4179 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData"); 4180 mStartingIconInTransition = true; 4181 wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel, 4182 labelRes, icon, logo, windowFlags); 4183 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4184 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4185 // want to process the message ASAP, before any other queued 4186 // messages. 4187 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING"); 4188 mH.sendMessageAtFrontOfQueue(m); 4189 } 4190 } 4191 4192 public void removeAppStartingWindow(IBinder token) { 4193 synchronized (mWindowMap) { 4194 AppWindowToken wtoken = mTokenMap.get(token).appWindowToken; 4195 if (wtoken.startingWindow != null) { 4196 scheduleRemoveStartingWindow(wtoken); 4197 } 4198 } 4199 } 4200 4201 @Override 4202 public void setAppWillBeHidden(IBinder token) { 4203 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4204 "setAppWillBeHidden()")) { 4205 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4206 } 4207 4208 AppWindowToken wtoken; 4209 4210 synchronized(mWindowMap) { 4211 wtoken = findAppWindowToken(token); 4212 if (wtoken == null) { 4213 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token); 4214 return; 4215 } 4216 wtoken.willBeHidden = true; 4217 } 4218 } 4219 4220 public void setAppFullscreen(IBinder token, boolean toOpaque) { 4221 AppWindowToken atoken = findAppWindowToken(token); 4222 if (atoken != null) { 4223 atoken.appFullscreen = toOpaque; 4224 // When making translucent, wait until windows below have been drawn. 4225 if (toOpaque) { 4226 // Making opaque so do it now. 4227 setWindowOpaque(token, true); 4228 } 4229 requestTraversal(); 4230 } 4231 } 4232 4233 public void setWindowOpaque(IBinder token, boolean isOpaque) { 4234 AppWindowToken wtoken = findAppWindowToken(token); 4235 if (wtoken != null) { 4236 WindowState win = wtoken.findMainWindow(); 4237 if (win != null) { 4238 win.mWinAnimator.setOpaque(isOpaque); 4239 } 4240 } 4241 } 4242 4243 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp, 4244 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) { 4245 boolean delayed = false; 4246 4247 if (wtoken.clientHidden == visible) { 4248 wtoken.clientHidden = !visible; 4249 wtoken.sendAppVisibilityToClients(); 4250 } 4251 4252 wtoken.willBeHidden = false; 4253 if (wtoken.hidden == visible) { 4254 boolean changed = false; 4255 if (DEBUG_APP_TRANSITIONS) Slog.v( 4256 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden 4257 + " performLayout=" + performLayout); 4258 4259 boolean runningAppAnimation = false; 4260 4261 if (transit != AppTransition.TRANSIT_UNSET) { 4262 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { 4263 wtoken.mAppAnimator.animation = null; 4264 } 4265 if (applyAnimationLocked(wtoken, lp, transit, visible, isVoiceInteraction)) { 4266 delayed = runningAppAnimation = true; 4267 } 4268 WindowState window = wtoken.findMainWindow(); 4269 //TODO (multidisplay): Magnification is supported only for the default display. 4270 if (window != null && mAccessibilityController != null 4271 && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 4272 mAccessibilityController.onAppWindowTransitionLocked(window, transit); 4273 } 4274 changed = true; 4275 } 4276 4277 final int N = wtoken.allAppWindows.size(); 4278 for (int i=0; i<N; i++) { 4279 WindowState win = wtoken.allAppWindows.get(i); 4280 if (win == wtoken.startingWindow) { 4281 continue; 4282 } 4283 4284 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible()); 4285 //win.dump(" "); 4286 if (visible) { 4287 if (!win.isVisibleNow()) { 4288 if (!runningAppAnimation) { 4289 win.mWinAnimator.applyAnimationLocked( 4290 WindowManagerPolicy.TRANSIT_ENTER, true); 4291 //TODO (multidisplay): Magnification is supported only for the default 4292 if (mAccessibilityController != null 4293 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4294 mAccessibilityController.onWindowTransitionLocked(win, 4295 WindowManagerPolicy.TRANSIT_ENTER); 4296 } 4297 } 4298 changed = true; 4299 final DisplayContent displayContent = win.getDisplayContent(); 4300 if (displayContent != null) { 4301 displayContent.layoutNeeded = true; 4302 } 4303 } 4304 } else if (win.isVisibleNow()) { 4305 if (!runningAppAnimation) { 4306 win.mWinAnimator.applyAnimationLocked( 4307 WindowManagerPolicy.TRANSIT_EXIT, false); 4308 //TODO (multidisplay): Magnification is supported only for the default 4309 if (mAccessibilityController != null 4310 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4311 mAccessibilityController.onWindowTransitionLocked(win, 4312 WindowManagerPolicy.TRANSIT_EXIT); 4313 } 4314 } 4315 changed = true; 4316 final DisplayContent displayContent = win.getDisplayContent(); 4317 if (displayContent != null) { 4318 displayContent.layoutNeeded = true; 4319 } 4320 } 4321 } 4322 4323 wtoken.hidden = wtoken.hiddenRequested = !visible; 4324 if (!visible) { 4325 unsetAppFreezingScreenLocked(wtoken, true, true); 4326 } else { 4327 // If we are being set visible, and the starting window is 4328 // not yet displayed, then make sure it doesn't get displayed. 4329 WindowState swin = wtoken.startingWindow; 4330 if (swin != null && !swin.isDrawnLw()) { 4331 swin.mPolicyVisibility = false; 4332 swin.mPolicyVisibilityAfterAnim = false; 4333 } 4334 } 4335 4336 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken 4337 + ": hidden=" + wtoken.hidden + " hiddenRequested=" 4338 + wtoken.hiddenRequested); 4339 4340 if (changed) { 4341 mInputMonitor.setUpdateInputWindowsNeededLw(); 4342 if (performLayout) { 4343 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4344 false /*updateInputWindows*/); 4345 performLayoutAndPlaceSurfacesLocked(); 4346 } 4347 mInputMonitor.updateInputWindowsLw(false /*force*/); 4348 } 4349 } 4350 4351 if (wtoken.mAppAnimator.animation != null) { 4352 delayed = true; 4353 } 4354 4355 for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) { 4356 if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) { 4357 delayed = true; 4358 } 4359 } 4360 4361 return delayed; 4362 } 4363 4364 @Override 4365 public void setAppVisibility(IBinder token, boolean visible) { 4366 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4367 "setAppVisibility()")) { 4368 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4369 } 4370 4371 AppWindowToken wtoken; 4372 4373 synchronized(mWindowMap) { 4374 wtoken = findAppWindowToken(token); 4375 if (wtoken == null) { 4376 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token); 4377 return; 4378 } 4379 4380 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG, "setAppVisibility(" + 4381 token + ", visible=" + visible + "): " + mAppTransition + 4382 " hidden=" + wtoken.hidden + " hiddenRequested=" + 4383 wtoken.hiddenRequested, HIDE_STACK_CRAWLS ? 4384 null : new RuntimeException("here").fillInStackTrace()); 4385 4386 // If we are preparing an app transition, then delay changing 4387 // the visibility of this token until we execute that transition. 4388 if (okToDisplay() && mAppTransition.isTransitionSet()) { 4389 wtoken.hiddenRequested = !visible; 4390 4391 if (!wtoken.startingDisplayed) { 4392 if (DEBUG_APP_TRANSITIONS) Slog.v( 4393 TAG, "Setting dummy animation on: " + wtoken); 4394 wtoken.mAppAnimator.setDummyAnimation(); 4395 } 4396 mOpeningApps.remove(wtoken); 4397 mClosingApps.remove(wtoken); 4398 wtoken.waitingToShow = wtoken.waitingToHide = false; 4399 wtoken.inPendingTransaction = true; 4400 if (visible) { 4401 mOpeningApps.add(wtoken); 4402 wtoken.startingMoved = false; 4403 4404 // If the token is currently hidden (should be the 4405 // common case), then we need to set up to wait for 4406 // its windows to be ready. 4407 if (wtoken.hidden) { 4408 wtoken.allDrawn = false; 4409 wtoken.deferClearAllDrawn = false; 4410 wtoken.waitingToShow = true; 4411 4412 if (wtoken.clientHidden) { 4413 // In the case where we are making an app visible 4414 // but holding off for a transition, we still need 4415 // to tell the client to make its windows visible so 4416 // they get drawn. Otherwise, we will wait on 4417 // performing the transition until all windows have 4418 // been drawn, they never will be, and we are sad. 4419 wtoken.clientHidden = false; 4420 wtoken.sendAppVisibilityToClients(); 4421 } 4422 } 4423 } else { 4424 mClosingApps.add(wtoken); 4425 4426 // If the token is currently visible (should be the 4427 // common case), then set up to wait for it to be hidden. 4428 if (!wtoken.hidden) { 4429 wtoken.waitingToHide = true; 4430 } 4431 } 4432 if (mAppTransition.getAppTransition() == AppTransition.TRANSIT_TASK_OPEN_BEHIND) { 4433 // We're launchingBehind, add the launching activity to mOpeningApps. 4434 final WindowState win = 4435 findFocusedWindowLocked(getDefaultDisplayContentLocked()); 4436 if (win != null) { 4437 final AppWindowToken focusedToken = win.mAppToken; 4438 if (focusedToken != null) { 4439 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "TRANSIT_TASK_OPEN_BEHIND, " + 4440 " adding " + focusedToken + " to mOpeningApps"); 4441 // Force animation to be loaded. 4442 focusedToken.hidden = true; 4443 mOpeningApps.add(focusedToken); 4444 } 4445 } 4446 } 4447 return; 4448 } 4449 4450 final long origId = Binder.clearCallingIdentity(); 4451 setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET, 4452 true, wtoken.voiceInteraction); 4453 wtoken.updateReportedVisibilityLocked(); 4454 Binder.restoreCallingIdentity(origId); 4455 } 4456 } 4457 4458 void unsetAppFreezingScreenLocked(AppWindowToken wtoken, 4459 boolean unfreezeSurfaceNow, boolean force) { 4460 if (wtoken.mAppAnimator.freezingScreen) { 4461 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken 4462 + " force=" + force); 4463 final int N = wtoken.allAppWindows.size(); 4464 boolean unfrozeWindows = false; 4465 for (int i=0; i<N; i++) { 4466 WindowState w = wtoken.allAppWindows.get(i); 4467 if (w.mAppFreezing) { 4468 w.mAppFreezing = false; 4469 if (w.mHasSurface && !w.mOrientationChanging) { 4470 if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w); 4471 w.mOrientationChanging = true; 4472 mInnerFields.mOrientationChangeComplete = false; 4473 } 4474 w.mLastFreezeDuration = 0; 4475 unfrozeWindows = true; 4476 final DisplayContent displayContent = w.getDisplayContent(); 4477 if (displayContent != null) { 4478 displayContent.layoutNeeded = true; 4479 } 4480 } 4481 } 4482 if (force || unfrozeWindows) { 4483 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken); 4484 wtoken.mAppAnimator.freezingScreen = false; 4485 wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime() 4486 - mDisplayFreezeTime); 4487 mAppsFreezingScreen--; 4488 mLastFinishedFreezeSource = wtoken; 4489 } 4490 if (unfreezeSurfaceNow) { 4491 if (unfrozeWindows) { 4492 performLayoutAndPlaceSurfacesLocked(); 4493 } 4494 stopFreezingDisplayLocked(); 4495 } 4496 } 4497 } 4498 4499 private void startAppFreezingScreenLocked(AppWindowToken wtoken) { 4500 if (DEBUG_ORIENTATION) { 4501 RuntimeException e = null; 4502 if (!HIDE_STACK_CRAWLS) { 4503 e = new RuntimeException(); 4504 e.fillInStackTrace(); 4505 } 4506 Slog.i(TAG, "Set freezing of " + wtoken.appToken 4507 + ": hidden=" + wtoken.hidden + " freezing=" 4508 + wtoken.mAppAnimator.freezingScreen, e); 4509 } 4510 if (!wtoken.hiddenRequested) { 4511 if (!wtoken.mAppAnimator.freezingScreen) { 4512 wtoken.mAppAnimator.freezingScreen = true; 4513 wtoken.mAppAnimator.lastFreezeDuration = 0; 4514 mAppsFreezingScreen++; 4515 if (mAppsFreezingScreen == 1) { 4516 startFreezingDisplayLocked(false, 0, 0); 4517 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 4518 mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000); 4519 } 4520 } 4521 final int N = wtoken.allAppWindows.size(); 4522 for (int i=0; i<N; i++) { 4523 WindowState w = wtoken.allAppWindows.get(i); 4524 w.mAppFreezing = true; 4525 } 4526 } 4527 } 4528 4529 @Override 4530 public void startAppFreezingScreen(IBinder token, int configChanges) { 4531 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4532 "setAppFreezingScreen()")) { 4533 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4534 } 4535 4536 synchronized(mWindowMap) { 4537 if (configChanges == 0 && okToDisplay()) { 4538 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token); 4539 return; 4540 } 4541 4542 AppWindowToken wtoken = findAppWindowToken(token); 4543 if (wtoken == null || wtoken.appToken == null) { 4544 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken); 4545 return; 4546 } 4547 final long origId = Binder.clearCallingIdentity(); 4548 startAppFreezingScreenLocked(wtoken); 4549 Binder.restoreCallingIdentity(origId); 4550 } 4551 } 4552 4553 @Override 4554 public void stopAppFreezingScreen(IBinder token, boolean force) { 4555 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4556 "setAppFreezingScreen()")) { 4557 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4558 } 4559 4560 synchronized(mWindowMap) { 4561 AppWindowToken wtoken = findAppWindowToken(token); 4562 if (wtoken == null || wtoken.appToken == null) { 4563 return; 4564 } 4565 final long origId = Binder.clearCallingIdentity(); 4566 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token 4567 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen); 4568 unsetAppFreezingScreenLocked(wtoken, true, force); 4569 Binder.restoreCallingIdentity(origId); 4570 } 4571 } 4572 4573 void removeAppFromTaskLocked(AppWindowToken wtoken) { 4574 final Task task = mTaskIdToTask.get(wtoken.groupId); 4575 if (task != null) { 4576 if (!task.removeAppToken(wtoken)) { 4577 Slog.e(TAG, "removeAppFromTaskLocked: token=" + wtoken + " not found."); 4578 } 4579 } 4580 } 4581 4582 @Override 4583 public void removeAppToken(IBinder token) { 4584 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4585 "removeAppToken()")) { 4586 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4587 } 4588 4589 AppWindowToken wtoken = null; 4590 AppWindowToken startingToken = null; 4591 boolean delayed = false; 4592 4593 final long origId = Binder.clearCallingIdentity(); 4594 synchronized(mWindowMap) { 4595 WindowToken basewtoken = mTokenMap.remove(token); 4596 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) { 4597 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken); 4598 delayed = setTokenVisibilityLocked(wtoken, null, false, 4599 AppTransition.TRANSIT_UNSET, true, wtoken.voiceInteraction); 4600 wtoken.inPendingTransaction = false; 4601 mOpeningApps.remove(wtoken); 4602 wtoken.waitingToShow = false; 4603 if (mClosingApps.contains(wtoken)) { 4604 delayed = true; 4605 } else if (mAppTransition.isTransitionSet()) { 4606 mClosingApps.add(wtoken); 4607 wtoken.waitingToHide = true; 4608 delayed = true; 4609 } 4610 if (DEBUG_APP_TRANSITIONS) Slog.v( 4611 TAG, "Removing app " + wtoken + " delayed=" + delayed 4612 + " animation=" + wtoken.mAppAnimator.animation 4613 + " animating=" + wtoken.mAppAnimator.animating); 4614 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: " 4615 + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4)); 4616 final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack; 4617 if (delayed) { 4618 // set the token aside because it has an active animation to be finished 4619 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4620 "removeAppToken make exiting: " + wtoken); 4621 stack.mExitingAppTokens.add(wtoken); 4622 wtoken.mDeferRemoval = true; 4623 } else { 4624 // Make sure there is no animation running on this token, 4625 // so any windows associated with it will be removed as 4626 // soon as their animations are complete 4627 wtoken.mAppAnimator.clearAnimation(); 4628 wtoken.mAppAnimator.animating = false; 4629 removeAppFromTaskLocked(wtoken); 4630 } 4631 4632 wtoken.removed = true; 4633 if (wtoken.startingData != null) { 4634 startingToken = wtoken; 4635 } 4636 unsetAppFreezingScreenLocked(wtoken, true, true); 4637 if (mFocusedApp == wtoken) { 4638 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Removing focused app token:" + wtoken); 4639 mFocusedApp = null; 4640 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 4641 mInputMonitor.setFocusedAppLw(null); 4642 } 4643 } else { 4644 Slog.w(TAG, "Attempted to remove non-existing app token: " + token); 4645 } 4646 4647 if (!delayed && wtoken != null) { 4648 wtoken.updateReportedVisibilityLocked(); 4649 } 4650 } 4651 Binder.restoreCallingIdentity(origId); 4652 4653 // Will only remove if startingToken non null. 4654 scheduleRemoveStartingWindow(startingToken); 4655 } 4656 4657 void scheduleRemoveStartingWindow(AppWindowToken wtoken) { 4658 if (wtoken != null && wtoken.startingWindow != null) { 4659 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) + 4660 ": Schedule remove starting " + wtoken + (wtoken != null ? 4661 " startingWindow=" + wtoken.startingWindow : "")); 4662 Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken); 4663 mH.sendMessage(m); 4664 } 4665 } 4666 4667 private boolean tmpRemoveAppWindowsLocked(WindowToken token) { 4668 WindowList windows = token.windows; 4669 final int NW = windows.size(); 4670 if (NW > 0) { 4671 mWindowsChanged = true; 4672 } 4673 for (int i = 0; i < NW; i++) { 4674 WindowState win = windows.get(i); 4675 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win); 4676 win.getWindowList().remove(win); 4677 int j = win.mChildWindows.size(); 4678 while (j > 0) { 4679 j--; 4680 WindowState cwin = win.mChildWindows.get(j); 4681 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 4682 "Tmp removing child window " + cwin); 4683 cwin.getWindowList().remove(cwin); 4684 } 4685 } 4686 return NW > 0; 4687 } 4688 4689 void dumpAppTokensLocked() { 4690 final int numStacks = mStackIdToStack.size(); 4691 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 4692 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 4693 Slog.v(TAG, " Stack #" + stack.mStackId + " tasks from bottom to top:"); 4694 final ArrayList<Task> tasks = stack.getTasks(); 4695 final int numTasks = tasks.size(); 4696 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4697 final Task task = tasks.get(taskNdx); 4698 Slog.v(TAG, " Task #" + task.taskId + " activities from bottom to top:"); 4699 AppTokenList tokens = task.mAppTokens; 4700 final int numTokens = tokens.size(); 4701 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 4702 Slog.v(TAG, " activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token); 4703 } 4704 } 4705 } 4706 } 4707 4708 void dumpWindowsLocked() { 4709 final int numDisplays = mDisplayContents.size(); 4710 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 4711 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 4712 Slog.v(TAG, " Display #" + displayContent.getDisplayId()); 4713 final WindowList windows = displayContent.getWindowList(); 4714 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 4715 Slog.v(TAG, " #" + winNdx + ": " + windows.get(winNdx)); 4716 } 4717 } 4718 } 4719 4720 private int findAppWindowInsertionPointLocked(AppWindowToken target) { 4721 final int taskId = target.groupId; 4722 Task targetTask = mTaskIdToTask.get(taskId); 4723 if (targetTask == null) { 4724 Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId=" 4725 + taskId); 4726 return 0; 4727 } 4728 DisplayContent displayContent = targetTask.getDisplayContent(); 4729 if (displayContent == null) { 4730 Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target); 4731 return 0; 4732 } 4733 final WindowList windows = displayContent.getWindowList(); 4734 final int NW = windows.size(); 4735 4736 boolean found = false; 4737 final ArrayList<Task> tasks = displayContent.getTasks(); 4738 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 4739 final Task task = tasks.get(taskNdx); 4740 if (!found && task.taskId != taskId) { 4741 continue; 4742 } 4743 AppTokenList tokens = task.mAppTokens; 4744 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 4745 final AppWindowToken wtoken = tokens.get(tokenNdx); 4746 if (!found && wtoken == target) { 4747 found = true; 4748 } 4749 if (found) { 4750 // Find the first app token below the new position that has 4751 // a window displayed. 4752 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token); 4753 if (wtoken.sendingToBottom) { 4754 if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom"); 4755 continue; 4756 } 4757 for (int i = wtoken.windows.size() - 1; i >= 0; --i) { 4758 WindowState win = wtoken.windows.get(i); 4759 for (int j = win.mChildWindows.size() - 1; j >= 0; --j) { 4760 WindowState cwin = win.mChildWindows.get(j); 4761 if (cwin.mSubLayer >= 0) { 4762 for (int pos = NW - 1; pos >= 0; pos--) { 4763 if (windows.get(pos) == cwin) { 4764 if (DEBUG_REORDER) Slog.v(TAG, 4765 "Found child win @" + (pos + 1)); 4766 return pos + 1; 4767 } 4768 } 4769 } 4770 } 4771 for (int pos = NW - 1; pos >= 0; pos--) { 4772 if (windows.get(pos) == win) { 4773 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1)); 4774 return pos + 1; 4775 } 4776 } 4777 } 4778 } 4779 } 4780 } 4781 // Never put an app window underneath wallpaper. 4782 for (int pos = NW - 1; pos >= 0; pos--) { 4783 if (windows.get(pos).mIsWallpaper) { 4784 if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos); 4785 return pos + 1; 4786 } 4787 } 4788 return 0; 4789 } 4790 4791 private final int reAddWindowLocked(int index, WindowState win) { 4792 final WindowList windows = win.getWindowList(); 4793 final int NCW = win.mChildWindows.size(); 4794 boolean added = false; 4795 for (int j=0; j<NCW; j++) { 4796 WindowState cwin = win.mChildWindows.get(j); 4797 if (!added && cwin.mSubLayer >= 0) { 4798 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at " 4799 + index + ": " + cwin); 4800 win.mRebuilding = false; 4801 windows.add(index, win); 4802 index++; 4803 added = true; 4804 } 4805 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4806 + index + ": " + cwin); 4807 cwin.mRebuilding = false; 4808 windows.add(index, cwin); 4809 index++; 4810 } 4811 if (!added) { 4812 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4813 + index + ": " + win); 4814 win.mRebuilding = false; 4815 windows.add(index, win); 4816 index++; 4817 } 4818 mWindowsChanged = true; 4819 return index; 4820 } 4821 4822 private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index, 4823 WindowToken token) { 4824 final int NW = token.windows.size(); 4825 for (int i=0; i<NW; i++) { 4826 final WindowState win = token.windows.get(i); 4827 final DisplayContent winDisplayContent = win.getDisplayContent(); 4828 if (winDisplayContent == displayContent || winDisplayContent == null) { 4829 win.mDisplayContent = displayContent; 4830 index = reAddWindowLocked(index, win); 4831 } 4832 } 4833 return index; 4834 } 4835 4836 void tmpRemoveTaskWindowsLocked(Task task) { 4837 AppTokenList tokens = task.mAppTokens; 4838 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 4839 tmpRemoveAppWindowsLocked(tokens.get(tokenNdx)); 4840 } 4841 } 4842 4843 void moveStackWindowsLocked(DisplayContent displayContent) { 4844 // First remove all of the windows from the list. 4845 final ArrayList<Task> tasks = displayContent.getTasks(); 4846 final int numTasks = tasks.size(); 4847 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4848 tmpRemoveTaskWindowsLocked(tasks.get(taskNdx)); 4849 } 4850 4851 // And now add them back at the correct place. 4852 // Where to start adding? 4853 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4854 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 4855 final int numTokens = tokens.size(); 4856 if (numTokens == 0) { 4857 continue; 4858 } 4859 int pos = findAppWindowInsertionPointLocked(tokens.get(0)); 4860 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 4861 final AppWindowToken wtoken = tokens.get(tokenNdx); 4862 if (wtoken != null) { 4863 final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken); 4864 if (newPos != pos) { 4865 displayContent.layoutNeeded = true; 4866 } 4867 pos = newPos; 4868 } 4869 } 4870 } 4871 4872 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4873 false /*updateInputWindows*/)) { 4874 assignLayersLocked(displayContent.getWindowList()); 4875 } 4876 4877 mInputMonitor.setUpdateInputWindowsNeededLw(); 4878 performLayoutAndPlaceSurfacesLocked(); 4879 mInputMonitor.updateInputWindowsLw(false /*force*/); 4880 4881 //dump(); 4882 } 4883 4884 public void moveTaskToTop(int taskId) { 4885 final long origId = Binder.clearCallingIdentity(); 4886 try { 4887 synchronized(mWindowMap) { 4888 Task task = mTaskIdToTask.get(taskId); 4889 if (task == null) { 4890 // Normal behavior, addAppToken will be called next and task will be created. 4891 return; 4892 } 4893 final TaskStack stack = task.mStack; 4894 final DisplayContent displayContent = task.getDisplayContent(); 4895 displayContent.moveStack(stack, true); 4896 if (displayContent.isDefaultDisplay) { 4897 final TaskStack homeStack = displayContent.getHomeStack(); 4898 if (homeStack != stack) { 4899 // When a non-home stack moves to the top, the home stack moves to the 4900 // bottom. 4901 displayContent.moveStack(homeStack, false); 4902 } 4903 } 4904 stack.moveTaskToTop(task); 4905 } 4906 } finally { 4907 Binder.restoreCallingIdentity(origId); 4908 } 4909 } 4910 4911 public void moveTaskToBottom(int taskId) { 4912 final long origId = Binder.clearCallingIdentity(); 4913 try { 4914 synchronized(mWindowMap) { 4915 Task task = mTaskIdToTask.get(taskId); 4916 if (task == null) { 4917 Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId 4918 + " not found in mTaskIdToTask"); 4919 return; 4920 } 4921 final TaskStack stack = task.mStack; 4922 stack.moveTaskToBottom(task); 4923 moveStackWindowsLocked(stack.getDisplayContent()); 4924 } 4925 } finally { 4926 Binder.restoreCallingIdentity(origId); 4927 } 4928 } 4929 4930 /** 4931 * Create a new TaskStack and place it on a DisplayContent. 4932 * @param stackId The unique identifier of the new stack. 4933 * @param displayId The unique identifier of the DisplayContent. 4934 */ 4935 public void attachStack(int stackId, int displayId) { 4936 final long origId = Binder.clearCallingIdentity(); 4937 try { 4938 synchronized (mWindowMap) { 4939 final DisplayContent displayContent = mDisplayContents.get(displayId); 4940 if (displayContent != null) { 4941 TaskStack stack = mStackIdToStack.get(stackId); 4942 if (stack == null) { 4943 if (DEBUG_STACK) Slog.d(TAG, "attachStack: stackId=" + stackId); 4944 stack = new TaskStack(this, stackId); 4945 mStackIdToStack.put(stackId, stack); 4946 } 4947 stack.attachDisplayContent(displayContent); 4948 displayContent.attachStack(stack); 4949 moveStackWindowsLocked(displayContent); 4950 final WindowList windows = displayContent.getWindowList(); 4951 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 4952 windows.get(winNdx).reportResized(); 4953 } 4954 } 4955 } 4956 } finally { 4957 Binder.restoreCallingIdentity(origId); 4958 } 4959 } 4960 4961 void detachStackLocked(DisplayContent displayContent, TaskStack stack) { 4962 displayContent.detachStack(stack); 4963 stack.detachDisplay(); 4964 } 4965 4966 public void detachStack(int stackId) { 4967 synchronized (mWindowMap) { 4968 TaskStack stack = mStackIdToStack.get(stackId); 4969 if (stack != null) { 4970 final DisplayContent displayContent = stack.getDisplayContent(); 4971 if (displayContent != null) { 4972 if (stack.isAnimating()) { 4973 stack.mDeferDetach = true; 4974 return; 4975 } 4976 detachStackLocked(displayContent, stack); 4977 } 4978 } 4979 } 4980 } 4981 4982 public void removeStack(int stackId) { 4983 mStackIdToStack.remove(stackId); 4984 } 4985 4986 void removeTaskLocked(Task task) { 4987 final int taskId = task.taskId; 4988 final TaskStack stack = task.mStack; 4989 if (stack.isAnimating()) { 4990 if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId); 4991 task.mDeferRemoval = true; 4992 return; 4993 } 4994 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId); 4995 EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask"); 4996 task.mDeferRemoval = false; 4997 task.mStack.removeTask(task); 4998 mTaskIdToTask.delete(task.taskId); 4999 } 5000 5001 public void removeTask(int taskId) { 5002 synchronized (mWindowMap) { 5003 Task task = mTaskIdToTask.get(taskId); 5004 if (task == null) { 5005 if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId); 5006 return; 5007 } 5008 removeTaskLocked(task); 5009 } 5010 } 5011 5012 public void addTask(int taskId, int stackId, boolean toTop) { 5013 synchronized (mWindowMap) { 5014 if (DEBUG_STACK) Slog.i(TAG, "addTask: adding taskId=" + taskId 5015 + " to " + (toTop ? "top" : "bottom")); 5016 Task task = mTaskIdToTask.get(taskId); 5017 if (task == null) { 5018 return; 5019 } 5020 TaskStack stack = mStackIdToStack.get(stackId); 5021 stack.addTask(task, toTop); 5022 final DisplayContent displayContent = stack.getDisplayContent(); 5023 displayContent.layoutNeeded = true; 5024 performLayoutAndPlaceSurfacesLocked(); 5025 } 5026 } 5027 5028 public void resizeStack(int stackId, Rect bounds) { 5029 synchronized (mWindowMap) { 5030 final TaskStack stack = mStackIdToStack.get(stackId); 5031 if (stack == null) { 5032 throw new IllegalArgumentException("resizeStack: stackId " + stackId 5033 + " not found."); 5034 } 5035 if (stack.setBounds(bounds)) { 5036 stack.resizeWindows(); 5037 stack.getDisplayContent().layoutNeeded = true; 5038 performLayoutAndPlaceSurfacesLocked(); 5039 } 5040 } 5041 } 5042 5043 public void getStackBounds(int stackId, Rect bounds) { 5044 final TaskStack stack = mStackIdToStack.get(stackId); 5045 if (stack != null) { 5046 stack.getBounds(bounds); 5047 return; 5048 } 5049 bounds.setEmpty(); 5050 } 5051 5052 // ------------------------------------------------------------- 5053 // Misc IWindowSession methods 5054 // ------------------------------------------------------------- 5055 5056 @Override 5057 public void startFreezingScreen(int exitAnim, int enterAnim) { 5058 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5059 "startFreezingScreen()")) { 5060 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5061 } 5062 5063 synchronized(mWindowMap) { 5064 if (!mClientFreezingScreen) { 5065 mClientFreezingScreen = true; 5066 final long origId = Binder.clearCallingIdentity(); 5067 try { 5068 startFreezingDisplayLocked(false, exitAnim, enterAnim); 5069 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 5070 mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000); 5071 } finally { 5072 Binder.restoreCallingIdentity(origId); 5073 } 5074 } 5075 } 5076 } 5077 5078 @Override 5079 public void stopFreezingScreen() { 5080 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5081 "stopFreezingScreen()")) { 5082 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5083 } 5084 5085 synchronized(mWindowMap) { 5086 if (mClientFreezingScreen) { 5087 mClientFreezingScreen = false; 5088 mLastFinishedFreezeSource = "client"; 5089 final long origId = Binder.clearCallingIdentity(); 5090 try { 5091 stopFreezingDisplayLocked(); 5092 } finally { 5093 Binder.restoreCallingIdentity(origId); 5094 } 5095 } 5096 } 5097 } 5098 5099 @Override 5100 public void disableKeyguard(IBinder token, String tag) { 5101 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5102 != PackageManager.PERMISSION_GRANTED) { 5103 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5104 } 5105 5106 if (token == null) { 5107 throw new IllegalArgumentException("token == null"); 5108 } 5109 5110 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5111 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag))); 5112 } 5113 5114 @Override 5115 public void reenableKeyguard(IBinder token) { 5116 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5117 != PackageManager.PERMISSION_GRANTED) { 5118 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5119 } 5120 5121 if (token == null) { 5122 throw new IllegalArgumentException("token == null"); 5123 } 5124 5125 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5126 KeyguardDisableHandler.KEYGUARD_REENABLE, token)); 5127 } 5128 5129 /** 5130 * @see android.app.KeyguardManager#exitKeyguardSecurely 5131 */ 5132 @Override 5133 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) { 5134 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5135 != PackageManager.PERMISSION_GRANTED) { 5136 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5137 } 5138 5139 if (callback == null) { 5140 throw new IllegalArgumentException("callback == null"); 5141 } 5142 5143 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() { 5144 @Override 5145 public void onKeyguardExitResult(boolean success) { 5146 try { 5147 callback.onKeyguardExitResult(success); 5148 } catch (RemoteException e) { 5149 // Client has died, we don't care. 5150 } 5151 } 5152 }); 5153 } 5154 5155 @Override 5156 public boolean inKeyguardRestrictedInputMode() { 5157 return mPolicy.inKeyguardRestrictedKeyInputMode(); 5158 } 5159 5160 @Override 5161 public boolean isKeyguardLocked() { 5162 return mPolicy.isKeyguardLocked(); 5163 } 5164 5165 @Override 5166 public boolean isKeyguardSecure() { 5167 return mPolicy.isKeyguardSecure(); 5168 } 5169 5170 @Override 5171 public void dismissKeyguard() { 5172 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5173 != PackageManager.PERMISSION_GRANTED) { 5174 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5175 } 5176 synchronized(mWindowMap) { 5177 mPolicy.dismissKeyguardLw(); 5178 } 5179 } 5180 5181 @Override 5182 public void keyguardGoingAway() { 5183 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5184 != PackageManager.PERMISSION_GRANTED) { 5185 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5186 } 5187 synchronized (mWindowMap) { 5188 mAnimator.mKeyguardGoingAway = true; 5189 requestTraversalLocked(); 5190 } 5191 } 5192 5193 void showGlobalActions() { 5194 mPolicy.showGlobalActions(); 5195 } 5196 5197 @Override 5198 public void closeSystemDialogs(String reason) { 5199 synchronized(mWindowMap) { 5200 final int numDisplays = mDisplayContents.size(); 5201 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5202 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5203 final int numWindows = windows.size(); 5204 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5205 final WindowState w = windows.get(winNdx); 5206 if (w.mHasSurface) { 5207 try { 5208 w.mClient.closeSystemDialogs(reason); 5209 } catch (RemoteException e) { 5210 } 5211 } 5212 } 5213 } 5214 } 5215 } 5216 5217 static float fixScale(float scale) { 5218 if (scale < 0) scale = 0; 5219 else if (scale > 20) scale = 20; 5220 return Math.abs(scale); 5221 } 5222 5223 @Override 5224 public void setAnimationScale(int which, float scale) { 5225 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5226 "setAnimationScale()")) { 5227 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5228 } 5229 5230 scale = fixScale(scale); 5231 switch (which) { 5232 case 0: mWindowAnimationScaleSetting = scale; break; 5233 case 1: mTransitionAnimationScaleSetting = scale; break; 5234 case 2: mAnimatorDurationScaleSetting = scale; break; 5235 } 5236 5237 // Persist setting 5238 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5239 } 5240 5241 @Override 5242 public void setAnimationScales(float[] scales) { 5243 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5244 "setAnimationScale()")) { 5245 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5246 } 5247 5248 if (scales != null) { 5249 if (scales.length >= 1) { 5250 mWindowAnimationScaleSetting = fixScale(scales[0]); 5251 } 5252 if (scales.length >= 2) { 5253 mTransitionAnimationScaleSetting = fixScale(scales[1]); 5254 } 5255 if (scales.length >= 3) { 5256 mAnimatorDurationScaleSetting = fixScale(scales[2]); 5257 dispatchNewAnimatorScaleLocked(null); 5258 } 5259 } 5260 5261 // Persist setting 5262 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5263 } 5264 5265 private void setAnimatorDurationScale(float scale) { 5266 mAnimatorDurationScaleSetting = scale; 5267 ValueAnimator.setDurationScale(scale); 5268 } 5269 5270 public float getWindowAnimationScaleLocked() { 5271 return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting; 5272 } 5273 5274 public float getTransitionAnimationScaleLocked() { 5275 return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting; 5276 } 5277 5278 @Override 5279 public float getAnimationScale(int which) { 5280 switch (which) { 5281 case 0: return mWindowAnimationScaleSetting; 5282 case 1: return mTransitionAnimationScaleSetting; 5283 case 2: return mAnimatorDurationScaleSetting; 5284 } 5285 return 0; 5286 } 5287 5288 @Override 5289 public float[] getAnimationScales() { 5290 return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting, 5291 mAnimatorDurationScaleSetting }; 5292 } 5293 5294 @Override 5295 public float getCurrentAnimatorScale() { 5296 synchronized(mWindowMap) { 5297 return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting; 5298 } 5299 } 5300 5301 void dispatchNewAnimatorScaleLocked(Session session) { 5302 mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget(); 5303 } 5304 5305 @Override 5306 public void registerPointerEventListener(PointerEventListener listener) { 5307 mPointerEventDispatcher.registerInputEventListener(listener); 5308 } 5309 5310 @Override 5311 public void unregisterPointerEventListener(PointerEventListener listener) { 5312 mPointerEventDispatcher.unregisterInputEventListener(listener); 5313 } 5314 5315 // Called by window manager policy. Not exposed externally. 5316 @Override 5317 public int getLidState() { 5318 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 5319 InputManagerService.SW_LID); 5320 if (sw > 0) { 5321 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 5322 return LID_CLOSED; 5323 } else if (sw == 0) { 5324 // Switch state: AKEY_STATE_UP. 5325 return LID_OPEN; 5326 } else { 5327 // Switch state: AKEY_STATE_UNKNOWN. 5328 return LID_ABSENT; 5329 } 5330 } 5331 5332 // Called by window manager policy. Not exposed externally. 5333 @Override 5334 public void switchKeyboardLayout(int deviceId, int direction) { 5335 mInputManager.switchKeyboardLayout(deviceId, direction); 5336 } 5337 5338 // Called by window manager policy. Not exposed externally. 5339 @Override 5340 public void shutdown(boolean confirm) { 5341 ShutdownThread.shutdown(mContext, confirm); 5342 } 5343 5344 // Called by window manager policy. Not exposed externally. 5345 @Override 5346 public void rebootSafeMode(boolean confirm) { 5347 ShutdownThread.rebootSafeMode(mContext, confirm); 5348 } 5349 5350 public void setCurrentProfileIds(final int[] currentProfileIds) { 5351 synchronized (mWindowMap) { 5352 mCurrentProfileIds = currentProfileIds; 5353 } 5354 } 5355 5356 public void setCurrentUser(final int newUserId, final int[] currentProfileIds) { 5357 synchronized (mWindowMap) { 5358 mCurrentUserId = newUserId; 5359 mCurrentProfileIds = currentProfileIds; 5360 mAppTransition.setCurrentUser(newUserId); 5361 mPolicy.setCurrentUserLw(newUserId); 5362 5363 // Hide windows that should not be seen by the new user. 5364 final int numDisplays = mDisplayContents.size(); 5365 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5366 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 5367 displayContent.switchUserStacks(newUserId); 5368 rebuildAppWindowListLocked(displayContent); 5369 } 5370 performLayoutAndPlaceSurfacesLocked(); 5371 } 5372 } 5373 5374 /* Called by WindowState */ 5375 boolean isCurrentProfileLocked(int userId) { 5376 if (userId == mCurrentUserId) return true; 5377 for (int i = 0; i < mCurrentProfileIds.length; i++) { 5378 if (mCurrentProfileIds[i] == userId) return true; 5379 } 5380 return false; 5381 } 5382 5383 public void enableScreenAfterBoot() { 5384 synchronized(mWindowMap) { 5385 if (DEBUG_BOOT) { 5386 RuntimeException here = new RuntimeException("here"); 5387 here.fillInStackTrace(); 5388 Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled 5389 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5390 + " mShowingBootMessages=" + mShowingBootMessages 5391 + " mSystemBooted=" + mSystemBooted, here); 5392 } 5393 if (mSystemBooted) { 5394 return; 5395 } 5396 mSystemBooted = true; 5397 hideBootMessagesLocked(); 5398 // If the screen still doesn't come up after 30 seconds, give 5399 // up and turn it on. 5400 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000); 5401 } 5402 5403 mPolicy.systemBooted(); 5404 5405 performEnableScreen(); 5406 } 5407 5408 @Override 5409 public void enableScreenIfNeeded() { 5410 synchronized (mWindowMap) { 5411 enableScreenIfNeededLocked(); 5412 } 5413 } 5414 5415 void enableScreenIfNeededLocked() { 5416 if (DEBUG_BOOT) { 5417 RuntimeException here = new RuntimeException("here"); 5418 here.fillInStackTrace(); 5419 Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled 5420 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5421 + " mShowingBootMessages=" + mShowingBootMessages 5422 + " mSystemBooted=" + mSystemBooted, here); 5423 } 5424 if (mDisplayEnabled) { 5425 return; 5426 } 5427 if (!mSystemBooted && !mShowingBootMessages) { 5428 return; 5429 } 5430 mH.sendEmptyMessage(H.ENABLE_SCREEN); 5431 } 5432 5433 public void performBootTimeout() { 5434 synchronized(mWindowMap) { 5435 if (mDisplayEnabled) { 5436 return; 5437 } 5438 Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled"); 5439 mForceDisplayEnabled = true; 5440 } 5441 performEnableScreen(); 5442 } 5443 5444 public void performEnableScreen() { 5445 synchronized(mWindowMap) { 5446 if (DEBUG_BOOT) { 5447 RuntimeException here = new RuntimeException("here"); 5448 here.fillInStackTrace(); 5449 Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled 5450 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5451 + " mShowingBootMessages=" + mShowingBootMessages 5452 + " mSystemBooted=" + mSystemBooted 5453 + " mOnlyCore=" + mOnlyCore, here); 5454 } 5455 if (mDisplayEnabled) { 5456 return; 5457 } 5458 if (!mSystemBooted && !mShowingBootMessages) { 5459 return; 5460 } 5461 5462 if (!mForceDisplayEnabled) { 5463 // Don't enable the screen until all existing windows 5464 // have been drawn. 5465 boolean haveBootMsg = false; 5466 boolean haveApp = false; 5467 // if the wallpaper service is disabled on the device, we're never going to have 5468 // wallpaper, don't bother waiting for it 5469 boolean haveWallpaper = false; 5470 boolean wallpaperEnabled = mContext.getResources().getBoolean( 5471 com.android.internal.R.bool.config_enableWallpaperService) 5472 && !mOnlyCore; 5473 boolean haveKeyguard = true; 5474 // TODO(multidisplay): Expand to all displays? 5475 final WindowList windows = getDefaultWindowListLocked(); 5476 final int N = windows.size(); 5477 for (int i=0; i<N; i++) { 5478 WindowState w = windows.get(i); 5479 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 5480 return; 5481 } 5482 if (w.isDrawnLw()) { 5483 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { 5484 haveBootMsg = true; 5485 } else if (w.mAttrs.type == TYPE_APPLICATION) { 5486 haveApp = true; 5487 } else if (w.mAttrs.type == TYPE_WALLPAPER) { 5488 haveWallpaper = true; 5489 } else if (w.mAttrs.type == TYPE_STATUS_BAR) { 5490 haveKeyguard = mPolicy.isKeyguardDrawnLw(); 5491 } 5492 } 5493 } 5494 5495 if (DEBUG_SCREEN_ON || DEBUG_BOOT) { 5496 Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages 5497 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp 5498 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled 5499 + " haveKeyguard=" + haveKeyguard); 5500 } 5501 5502 // If we are turning on the screen to show the boot message, 5503 // don't do it until the boot message is actually displayed. 5504 if (!mSystemBooted && !haveBootMsg) { 5505 return; 5506 } 5507 5508 // If we are turning on the screen after the boot is completed 5509 // normally, don't do so until we have the application and 5510 // wallpaper. 5511 if (mSystemBooted && ((!haveApp && !haveKeyguard) || 5512 (wallpaperEnabled && !haveWallpaper))) { 5513 return; 5514 } 5515 } 5516 5517 mDisplayEnabled = true; 5518 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!"); 5519 if (false) { 5520 StringWriter sw = new StringWriter(); 5521 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 5522 this.dump(null, pw, null); 5523 pw.flush(); 5524 Slog.i(TAG, sw.toString()); 5525 } 5526 try { 5527 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); 5528 if (surfaceFlinger != null) { 5529 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); 5530 Parcel data = Parcel.obtain(); 5531 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 5532 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED 5533 data, null, 0); 5534 data.recycle(); 5535 } 5536 } catch (RemoteException ex) { 5537 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); 5538 } 5539 5540 // Enable input dispatch. 5541 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled); 5542 } 5543 5544 mPolicy.enableScreenAfterBoot(); 5545 5546 // Make sure the last requested orientation has been applied. 5547 updateRotationUnchecked(false, false); 5548 } 5549 5550 public void showBootMessage(final CharSequence msg, final boolean always) { 5551 boolean first = false; 5552 synchronized(mWindowMap) { 5553 if (DEBUG_BOOT) { 5554 RuntimeException here = new RuntimeException("here"); 5555 here.fillInStackTrace(); 5556 Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always 5557 + " mAllowBootMessages=" + mAllowBootMessages 5558 + " mShowingBootMessages=" + mShowingBootMessages 5559 + " mSystemBooted=" + mSystemBooted, here); 5560 } 5561 if (!mAllowBootMessages) { 5562 return; 5563 } 5564 if (!mShowingBootMessages) { 5565 if (!always) { 5566 return; 5567 } 5568 first = true; 5569 } 5570 if (mSystemBooted) { 5571 return; 5572 } 5573 mShowingBootMessages = true; 5574 mPolicy.showBootMessage(msg, always); 5575 } 5576 if (first) { 5577 performEnableScreen(); 5578 } 5579 } 5580 5581 public void hideBootMessagesLocked() { 5582 if (DEBUG_BOOT) { 5583 RuntimeException here = new RuntimeException("here"); 5584 here.fillInStackTrace(); 5585 Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled 5586 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5587 + " mShowingBootMessages=" + mShowingBootMessages 5588 + " mSystemBooted=" + mSystemBooted, here); 5589 } 5590 if (mShowingBootMessages) { 5591 mShowingBootMessages = false; 5592 mPolicy.hideBootMessages(); 5593 } 5594 } 5595 5596 @Override 5597 public void setInTouchMode(boolean mode) { 5598 synchronized(mWindowMap) { 5599 mInTouchMode = mode; 5600 } 5601 } 5602 5603 // TODO: more accounting of which pid(s) turned it on, keep count, 5604 // only allow disables from pids which have count on, etc. 5605 @Override 5606 public void showStrictModeViolation(boolean on) { 5607 int pid = Binder.getCallingPid(); 5608 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid)); 5609 } 5610 5611 private void showStrictModeViolation(int arg, int pid) { 5612 final boolean on = arg != 0; 5613 synchronized(mWindowMap) { 5614 // Ignoring requests to enable the red border from clients 5615 // which aren't on screen. (e.g. Broadcast Receivers in 5616 // the background..) 5617 if (on) { 5618 boolean isVisible = false; 5619 final int numDisplays = mDisplayContents.size(); 5620 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5621 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5622 final int numWindows = windows.size(); 5623 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5624 final WindowState ws = windows.get(winNdx); 5625 if (ws.mSession.mPid == pid && ws.isVisibleLw()) { 5626 isVisible = true; 5627 break; 5628 } 5629 } 5630 } 5631 if (!isVisible) { 5632 return; 5633 } 5634 } 5635 5636 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5637 ">>> OPEN TRANSACTION showStrictModeViolation"); 5638 SurfaceControl.openTransaction(); 5639 try { 5640 // TODO(multi-display): support multiple displays 5641 if (mStrictModeFlash == null) { 5642 mStrictModeFlash = new StrictModeFlash( 5643 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 5644 } 5645 mStrictModeFlash.setVisibility(on); 5646 } finally { 5647 SurfaceControl.closeTransaction(); 5648 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5649 "<<< CLOSE TRANSACTION showStrictModeViolation"); 5650 } 5651 } 5652 } 5653 5654 @Override 5655 public void setStrictModeVisualIndicatorPreference(String value) { 5656 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 5657 } 5658 5659 /** 5660 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 5661 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 5662 * of the target image. 5663 * 5664 * @param displayId the Display to take a screenshot of. 5665 * @param width the width of the target bitmap 5666 * @param height the height of the target bitmap 5667 * @param force565 if true the returned bitmap will be RGB_565, otherwise it 5668 * will be the same config as the surface 5669 */ 5670 @Override 5671 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, 5672 int height, boolean force565) { 5673 if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, 5674 "screenshotApplications()")) { 5675 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 5676 } 5677 5678 final DisplayContent displayContent = getDisplayContentLocked(displayId); 5679 if (displayContent == null) { 5680 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 5681 + ": returning null. No Display for displayId=" + displayId); 5682 return null; 5683 } 5684 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 5685 int dw = displayInfo.logicalWidth; 5686 int dh = displayInfo.logicalHeight; 5687 if (dw == 0 || dh == 0) { 5688 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 5689 + ": returning null. logical widthxheight=" + dw + "x" + dh); 5690 return null; 5691 } 5692 5693 Bitmap rawss = null; 5694 5695 int maxLayer = 0; 5696 final Rect frame = new Rect(); 5697 final Rect stackBounds = new Rect(); 5698 5699 float scale = 0; 5700 int rot = Surface.ROTATION_0; 5701 5702 boolean screenshotReady; 5703 int minLayer; 5704 if (appToken == null) { 5705 screenshotReady = true; 5706 minLayer = 0; 5707 } else { 5708 screenshotReady = false; 5709 minLayer = Integer.MAX_VALUE; 5710 } 5711 5712 int retryCount = 0; 5713 WindowState appWin = null; 5714 5715 final boolean appIsImTarget = mInputMethodTarget != null 5716 && mInputMethodTarget.mAppToken != null 5717 && mInputMethodTarget.mAppToken.appToken != null 5718 && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken; 5719 5720 final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1) 5721 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 5722 5723 while (true) { 5724 if (retryCount++ > 0) { 5725 try { 5726 Thread.sleep(100); 5727 } catch (InterruptedException e) { 5728 } 5729 } 5730 synchronized(mWindowMap) { 5731 // Figure out the part of the screen that is actually the app. 5732 appWin = null; 5733 final WindowList windows = displayContent.getWindowList(); 5734 for (int i = windows.size() - 1; i >= 0; i--) { 5735 WindowState ws = windows.get(i); 5736 if (!ws.mHasSurface) { 5737 continue; 5738 } 5739 if (ws.mLayer >= aboveAppLayer) { 5740 continue; 5741 } 5742 if (ws.mIsImWindow) { 5743 if (!appIsImTarget) { 5744 continue; 5745 } 5746 } else if (ws.mIsWallpaper) { 5747 // Fall through. 5748 } else if (appToken != null) { 5749 if (ws.mAppToken == null || ws.mAppToken.token != appToken) { 5750 // This app window is of no interest if it is not associated with the 5751 // screenshot app. 5752 continue; 5753 } 5754 appWin = ws; 5755 } 5756 5757 // Include this window. 5758 5759 final WindowStateAnimator winAnim = ws.mWinAnimator; 5760 if (maxLayer < winAnim.mSurfaceLayer) { 5761 maxLayer = winAnim.mSurfaceLayer; 5762 } 5763 if (minLayer > winAnim.mSurfaceLayer) { 5764 minLayer = winAnim.mSurfaceLayer; 5765 } 5766 5767 // Don't include wallpaper in bounds calculation 5768 if (!ws.mIsWallpaper) { 5769 final Rect wf = ws.mFrame; 5770 final Rect cr = ws.mContentInsets; 5771 int left = wf.left + cr.left; 5772 int top = wf.top + cr.top; 5773 int right = wf.right - cr.right; 5774 int bottom = wf.bottom - cr.bottom; 5775 frame.union(left, top, right, bottom); 5776 ws.getStackBounds(stackBounds); 5777 frame.intersect(stackBounds); 5778 } 5779 5780 if (ws.mAppToken != null && ws.mAppToken.token == appToken && 5781 ws.isDisplayedLw()) { 5782 screenshotReady = true; 5783 } 5784 } 5785 5786 if (appToken != null && appWin == null) { 5787 // Can't find a window to snapshot. 5788 if (DEBUG_SCREENSHOT) Slog.i(TAG, 5789 "Screenshot: Couldn't find a surface matching " + appToken); 5790 return null; 5791 } 5792 5793 if (!screenshotReady) { 5794 if (retryCount > MAX_SCREENSHOT_RETRIES) { 5795 Slog.i(TAG, "Screenshot max retries " + retryCount + " of " + appToken + 5796 " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" + 5797 appWin.mWinAnimator.mDrawState))); 5798 return null; 5799 } 5800 5801 // Delay and hope that window gets drawn. 5802 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken 5803 + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState); 5804 continue; 5805 } 5806 5807 // Screenshot is ready to be taken. Everything from here below will continue 5808 // through the bottom of the loop and return a value. We only stay in the loop 5809 // because we don't want to release the mWindowMap lock until the screenshot is 5810 // taken. 5811 5812 if (maxLayer == 0) { 5813 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 5814 + ": returning null maxLayer=" + maxLayer); 5815 return null; 5816 } 5817 5818 // Constrain frame to the screen size. 5819 frame.intersect(0, 0, dw, dh); 5820 // Constrain thumbnail to smaller of screen width or height. Assumes aspect 5821 // of thumbnail is the same as the screen (in landscape) or square. 5822 scale = Math.max(width / (float) frame.width(), height / (float) frame.height()); 5823 dw = (int)(dw * scale); 5824 dh = (int)(dh * scale); 5825 5826 // The screenshot API does not apply the current screen rotation. 5827 rot = getDefaultDisplayContentLocked().getDisplay().getRotation(); 5828 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 5829 final int tmp = dw; 5830 dw = dh; 5831 dh = tmp; 5832 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; 5833 } 5834 5835 if (DEBUG_SCREENSHOT) { 5836 Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 5837 + maxLayer + " appToken=" + appToken); 5838 for (int i = 0; i < windows.size(); i++) { 5839 WindowState win = windows.get(i); 5840 Slog.i(TAG, win + ": " + win.mLayer 5841 + " animLayer=" + win.mWinAnimator.mAnimLayer 5842 + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer); 5843 } 5844 } 5845 5846 ScreenRotationAnimation screenRotationAnimation = 5847 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 5848 final boolean inRotation = screenRotationAnimation != null && 5849 screenRotationAnimation.isAnimating(); 5850 if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG, 5851 "Taking screenshot while rotating"); 5852 5853 rawss = SurfaceControl.screenshot(new Rect(), dw, dh, minLayer, maxLayer, 5854 inRotation); 5855 if (rawss == null) { 5856 Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh 5857 + ") to layer " + maxLayer); 5858 return null; 5859 } 5860 } 5861 5862 break; 5863 } 5864 5865 Bitmap bm = Bitmap.createBitmap(width, height, force565 ? 5866 Config.RGB_565 : rawss.getConfig()); 5867 if (DEBUG_SCREENSHOT) { 5868 bm.eraseColor(0xFF000000); 5869 } 5870 frame.scale(scale); 5871 Matrix matrix = new Matrix(); 5872 ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix); 5873 // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left 5874 matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top)); 5875 Canvas canvas = new Canvas(bm); 5876 canvas.drawBitmap(rawss, matrix, null); 5877 canvas.setBitmap(null); 5878 5879 if (DEBUG_SCREENSHOT) { 5880 // TEST IF IT's ALL BLACK 5881 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 5882 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 5883 boolean allBlack = true; 5884 final int firstColor = buffer[0]; 5885 for (int i = 0; i < buffer.length; i++) { 5886 if (buffer[i] != firstColor) { 5887 allBlack = false; 5888 break; 5889 } 5890 } 5891 if (allBlack) { 5892 Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" + 5893 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 5894 (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") + 5895 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 5896 } 5897 } 5898 5899 rawss.recycle(); 5900 return bm; 5901 } 5902 5903 /** 5904 * Freeze rotation changes. (Enable "rotation lock".) 5905 * Persists across reboots. 5906 * @param rotation The desired rotation to freeze to, or -1 to use the 5907 * current rotation. 5908 */ 5909 @Override 5910 public void freezeRotation(int rotation) { 5911 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5912 "freezeRotation()")) { 5913 throw new SecurityException("Requires SET_ORIENTATION permission"); 5914 } 5915 if (rotation < -1 || rotation > Surface.ROTATION_270) { 5916 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 5917 + "rotation constant."); 5918 } 5919 5920 if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); 5921 5922 long origId = Binder.clearCallingIdentity(); 5923 try { 5924 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, 5925 rotation == -1 ? mRotation : rotation); 5926 } finally { 5927 Binder.restoreCallingIdentity(origId); 5928 } 5929 5930 updateRotationUnchecked(false, false); 5931 } 5932 5933 /** 5934 * Thaw rotation changes. (Disable "rotation lock".) 5935 * Persists across reboots. 5936 */ 5937 @Override 5938 public void thawRotation() { 5939 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5940 "thawRotation()")) { 5941 throw new SecurityException("Requires SET_ORIENTATION permission"); 5942 } 5943 5944 if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); 5945 5946 long origId = Binder.clearCallingIdentity(); 5947 try { 5948 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 5949 777); // rot not used 5950 } finally { 5951 Binder.restoreCallingIdentity(origId); 5952 } 5953 5954 updateRotationUnchecked(false, false); 5955 } 5956 5957 /** 5958 * Recalculate the current rotation. 5959 * 5960 * Called by the window manager policy whenever the state of the system changes 5961 * such that the current rotation might need to be updated, such as when the 5962 * device is docked or rotated into a new posture. 5963 */ 5964 @Override 5965 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 5966 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 5967 } 5968 5969 /** 5970 * Temporarily pauses rotation changes until resumed. 5971 * 5972 * This can be used to prevent rotation changes from occurring while the user is 5973 * performing certain operations, such as drag and drop. 5974 * 5975 * This call nests and must be matched by an equal number of calls to 5976 * {@link #resumeRotationLocked}. 5977 */ 5978 void pauseRotationLocked() { 5979 mDeferredRotationPauseCount += 1; 5980 } 5981 5982 /** 5983 * Resumes normal rotation changes after being paused. 5984 */ 5985 void resumeRotationLocked() { 5986 if (mDeferredRotationPauseCount > 0) { 5987 mDeferredRotationPauseCount -= 1; 5988 if (mDeferredRotationPauseCount == 0) { 5989 boolean changed = updateRotationUncheckedLocked(false); 5990 if (changed) { 5991 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 5992 } 5993 } 5994 } 5995 } 5996 5997 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 5998 if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" 5999 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); 6000 6001 long origId = Binder.clearCallingIdentity(); 6002 boolean changed; 6003 synchronized(mWindowMap) { 6004 changed = updateRotationUncheckedLocked(false); 6005 if (!changed || forceRelayout) { 6006 getDefaultDisplayContentLocked().layoutNeeded = true; 6007 performLayoutAndPlaceSurfacesLocked(); 6008 } 6009 } 6010 6011 if (changed || alwaysSendConfiguration) { 6012 sendNewConfiguration(); 6013 } 6014 6015 Binder.restoreCallingIdentity(origId); 6016 } 6017 6018 // TODO(multidisplay): Rotate any display? 6019 /** 6020 * Updates the current rotation. 6021 * 6022 * Returns true if the rotation has been changed. In this case YOU 6023 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. 6024 */ 6025 public boolean updateRotationUncheckedLocked(boolean inTransaction) { 6026 if (mDeferredRotationPauseCount > 0) { 6027 // Rotation updates have been paused temporarily. Defer the update until 6028 // updates have been resumed. 6029 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused."); 6030 return false; 6031 } 6032 6033 ScreenRotationAnimation screenRotationAnimation = 6034 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6035 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 6036 // Rotation updates cannot be performed while the previous rotation change 6037 // animation is still in progress. Skip this update. We will try updating 6038 // again after the animation is finished and the display is unfrozen. 6039 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress."); 6040 return false; 6041 } 6042 6043 if (!mDisplayEnabled) { 6044 // No point choosing a rotation if the display is not enabled. 6045 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled."); 6046 return false; 6047 } 6048 6049 // TODO: Implement forced rotation changes. 6050 // Set mAltOrientation to indicate that the application is receiving 6051 // an orientation that has different metrics than it expected. 6052 // eg. Portrait instead of Landscape. 6053 6054 int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation); 6055 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 6056 mForcedAppOrientation, rotation); 6057 6058 if (DEBUG_ORIENTATION) { 6059 Slog.v(TAG, "Application requested orientation " 6060 + mForcedAppOrientation + ", got rotation " + rotation 6061 + " which has " + (altOrientation ? "incompatible" : "compatible") 6062 + " metrics"); 6063 } 6064 6065 if (mRotation == rotation && mAltOrientation == altOrientation) { 6066 // No change. 6067 return false; 6068 } 6069 6070 if (DEBUG_ORIENTATION) { 6071 Slog.v(TAG, 6072 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") 6073 + " from " + mRotation + (mAltOrientation ? " (alt)" : "") 6074 + ", forceApp=" + mForcedAppOrientation); 6075 } 6076 6077 mRotation = rotation; 6078 mAltOrientation = altOrientation; 6079 mPolicy.setRotationLw(mRotation); 6080 6081 mWindowsFreezingScreen = true; 6082 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 6083 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION); 6084 mWaitingForConfig = true; 6085 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6086 displayContent.layoutNeeded = true; 6087 final int[] anim = new int[2]; 6088 if (displayContent.isDimming()) { 6089 anim[0] = anim[1] = 0; 6090 } else { 6091 mPolicy.selectRotationAnimationLw(anim); 6092 } 6093 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]); 6094 // startFreezingDisplayLocked can reset the ScreenRotationAnimation. 6095 screenRotationAnimation = 6096 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6097 6098 // We need to update our screen size information to match the new 6099 // rotation. Note that this is redundant with the later call to 6100 // sendNewConfiguration() that must be called after this function 6101 // returns... however we need to do the screen size part of that 6102 // before then so we have the correct size to use when initializing 6103 // the rotation animation for the new rotation. 6104 computeScreenConfigurationLocked(null); 6105 6106 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6107 if (!inTransaction) { 6108 if (SHOW_TRANSACTIONS) { 6109 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked"); 6110 } 6111 SurfaceControl.openTransaction(); 6112 } 6113 try { 6114 // NOTE: We disable the rotation in the emulator because 6115 // it doesn't support hardware OpenGL emulation yet. 6116 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 6117 && screenRotationAnimation.hasScreenshot()) { 6118 if (screenRotationAnimation.setRotationInTransaction( 6119 rotation, mFxSession, 6120 MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(), 6121 displayInfo.logicalWidth, displayInfo.logicalHeight)) { 6122 scheduleAnimationLocked(); 6123 } 6124 } 6125 6126 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 6127 } finally { 6128 if (!inTransaction) { 6129 SurfaceControl.closeTransaction(); 6130 if (SHOW_LIGHT_TRANSACTIONS) { 6131 Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked"); 6132 } 6133 } 6134 } 6135 6136 final WindowList windows = displayContent.getWindowList(); 6137 for (int i = windows.size() - 1; i >= 0; i--) { 6138 WindowState w = windows.get(i); 6139 if (w.mHasSurface) { 6140 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w); 6141 w.mOrientationChanging = true; 6142 mInnerFields.mOrientationChangeComplete = false; 6143 } 6144 w.mLastFreezeDuration = 0; 6145 } 6146 6147 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 6148 try { 6149 mRotationWatchers.get(i).watcher.onRotationChanged(rotation); 6150 } catch (RemoteException e) { 6151 } 6152 } 6153 6154 //TODO (multidisplay): Magnification is supported only for the default display. 6155 if (mAccessibilityController != null 6156 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 6157 mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation); 6158 } 6159 6160 return true; 6161 } 6162 6163 @Override 6164 public int getRotation() { 6165 return mRotation; 6166 } 6167 6168 @Override 6169 public boolean isRotationFrozen() { 6170 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED; 6171 } 6172 6173 @Override 6174 public int watchRotation(IRotationWatcher watcher) { 6175 final IBinder watcherBinder = watcher.asBinder(); 6176 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 6177 @Override 6178 public void binderDied() { 6179 synchronized (mWindowMap) { 6180 for (int i=0; i<mRotationWatchers.size(); i++) { 6181 if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) { 6182 RotationWatcher removed = mRotationWatchers.remove(i); 6183 IBinder binder = removed.watcher.asBinder(); 6184 if (binder != null) { 6185 binder.unlinkToDeath(this, 0); 6186 } 6187 i--; 6188 } 6189 } 6190 } 6191 } 6192 }; 6193 6194 synchronized (mWindowMap) { 6195 try { 6196 watcher.asBinder().linkToDeath(dr, 0); 6197 mRotationWatchers.add(new RotationWatcher(watcher, dr)); 6198 } catch (RemoteException e) { 6199 // Client died, no cleanup needed. 6200 } 6201 6202 return mRotation; 6203 } 6204 } 6205 6206 @Override 6207 public void removeRotationWatcher(IRotationWatcher watcher) { 6208 final IBinder watcherBinder = watcher.asBinder(); 6209 synchronized (mWindowMap) { 6210 for (int i=0; i<mRotationWatchers.size(); i++) { 6211 RotationWatcher rotationWatcher = mRotationWatchers.get(i); 6212 if (watcherBinder == rotationWatcher.watcher.asBinder()) { 6213 RotationWatcher removed = mRotationWatchers.remove(i); 6214 IBinder binder = removed.watcher.asBinder(); 6215 if (binder != null) { 6216 binder.unlinkToDeath(removed.deathRecipient, 0); 6217 } 6218 i--; 6219 } 6220 } 6221 } 6222 } 6223 6224 /** 6225 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 6226 * theme attribute) on devices that feature a physical options menu key attempt to position 6227 * their menu panel window along the edge of the screen nearest the physical menu key. 6228 * This lowers the travel distance between invoking the menu panel and selecting 6229 * a menu option. 6230 * 6231 * This method helps control where that menu is placed. Its current implementation makes 6232 * assumptions about the menu key and its relationship to the screen based on whether 6233 * the device's natural orientation is portrait (width < height) or landscape. 6234 * 6235 * The menu key is assumed to be located along the bottom edge of natural-portrait 6236 * devices and along the right edge of natural-landscape devices. If these assumptions 6237 * do not hold for the target device, this method should be changed to reflect that. 6238 * 6239 * @return A {@link Gravity} value for placing the options menu window 6240 */ 6241 @Override 6242 public int getPreferredOptionsPanelGravity() { 6243 synchronized (mWindowMap) { 6244 final int rotation = getRotation(); 6245 6246 // TODO(multidisplay): Assume that such devices physical keys are on the main screen. 6247 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6248 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) { 6249 // On devices with a natural orientation of portrait 6250 switch (rotation) { 6251 default: 6252 case Surface.ROTATION_0: 6253 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6254 case Surface.ROTATION_90: 6255 return Gravity.RIGHT | Gravity.BOTTOM; 6256 case Surface.ROTATION_180: 6257 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6258 case Surface.ROTATION_270: 6259 return Gravity.START | Gravity.BOTTOM; 6260 } 6261 } 6262 6263 // On devices with a natural orientation of landscape 6264 switch (rotation) { 6265 default: 6266 case Surface.ROTATION_0: 6267 return Gravity.RIGHT | Gravity.BOTTOM; 6268 case Surface.ROTATION_90: 6269 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6270 case Surface.ROTATION_180: 6271 return Gravity.START | Gravity.BOTTOM; 6272 case Surface.ROTATION_270: 6273 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6274 } 6275 } 6276 } 6277 6278 /** 6279 * Starts the view server on the specified port. 6280 * 6281 * @param port The port to listener to. 6282 * 6283 * @return True if the server was successfully started, false otherwise. 6284 * 6285 * @see com.android.server.wm.ViewServer 6286 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 6287 */ 6288 @Override 6289 public boolean startViewServer(int port) { 6290 if (isSystemSecure()) { 6291 return false; 6292 } 6293 6294 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 6295 return false; 6296 } 6297 6298 if (port < 1024) { 6299 return false; 6300 } 6301 6302 if (mViewServer != null) { 6303 if (!mViewServer.isRunning()) { 6304 try { 6305 return mViewServer.start(); 6306 } catch (IOException e) { 6307 Slog.w(TAG, "View server did not start"); 6308 } 6309 } 6310 return false; 6311 } 6312 6313 try { 6314 mViewServer = new ViewServer(this, port); 6315 return mViewServer.start(); 6316 } catch (IOException e) { 6317 Slog.w(TAG, "View server did not start"); 6318 } 6319 return false; 6320 } 6321 6322 private boolean isSystemSecure() { 6323 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 6324 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 6325 } 6326 6327 /** 6328 * Stops the view server if it exists. 6329 * 6330 * @return True if the server stopped, false if it wasn't started or 6331 * couldn't be stopped. 6332 * 6333 * @see com.android.server.wm.ViewServer 6334 */ 6335 @Override 6336 public boolean stopViewServer() { 6337 if (isSystemSecure()) { 6338 return false; 6339 } 6340 6341 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 6342 return false; 6343 } 6344 6345 if (mViewServer != null) { 6346 return mViewServer.stop(); 6347 } 6348 return false; 6349 } 6350 6351 /** 6352 * Indicates whether the view server is running. 6353 * 6354 * @return True if the server is running, false otherwise. 6355 * 6356 * @see com.android.server.wm.ViewServer 6357 */ 6358 @Override 6359 public boolean isViewServerRunning() { 6360 if (isSystemSecure()) { 6361 return false; 6362 } 6363 6364 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 6365 return false; 6366 } 6367 6368 return mViewServer != null && mViewServer.isRunning(); 6369 } 6370 6371 /** 6372 * Lists all availble windows in the system. The listing is written in the 6373 * specified Socket's output stream with the following syntax: 6374 * windowHashCodeInHexadecimal windowName 6375 * Each line of the ouput represents a different window. 6376 * 6377 * @param client The remote client to send the listing to. 6378 * @return False if an error occured, true otherwise. 6379 */ 6380 boolean viewServerListWindows(Socket client) { 6381 if (isSystemSecure()) { 6382 return false; 6383 } 6384 6385 boolean result = true; 6386 6387 WindowList windows = new WindowList(); 6388 synchronized (mWindowMap) { 6389 //noinspection unchecked 6390 final int numDisplays = mDisplayContents.size(); 6391 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6392 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 6393 windows.addAll(displayContent.getWindowList()); 6394 } 6395 } 6396 6397 BufferedWriter out = null; 6398 6399 // Any uncaught exception will crash the system process 6400 try { 6401 OutputStream clientStream = client.getOutputStream(); 6402 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6403 6404 final int count = windows.size(); 6405 for (int i = 0; i < count; i++) { 6406 final WindowState w = windows.get(i); 6407 out.write(Integer.toHexString(System.identityHashCode(w))); 6408 out.write(' '); 6409 out.append(w.mAttrs.getTitle()); 6410 out.write('\n'); 6411 } 6412 6413 out.write("DONE.\n"); 6414 out.flush(); 6415 } catch (Exception e) { 6416 result = false; 6417 } finally { 6418 if (out != null) { 6419 try { 6420 out.close(); 6421 } catch (IOException e) { 6422 result = false; 6423 } 6424 } 6425 } 6426 6427 return result; 6428 } 6429 6430 // TODO(multidisplay): Extend to multiple displays. 6431 /** 6432 * Returns the focused window in the following format: 6433 * windowHashCodeInHexadecimal windowName 6434 * 6435 * @param client The remote client to send the listing to. 6436 * @return False if an error occurred, true otherwise. 6437 */ 6438 boolean viewServerGetFocusedWindow(Socket client) { 6439 if (isSystemSecure()) { 6440 return false; 6441 } 6442 6443 boolean result = true; 6444 6445 WindowState focusedWindow = getFocusedWindow(); 6446 6447 BufferedWriter out = null; 6448 6449 // Any uncaught exception will crash the system process 6450 try { 6451 OutputStream clientStream = client.getOutputStream(); 6452 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6453 6454 if(focusedWindow != null) { 6455 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 6456 out.write(' '); 6457 out.append(focusedWindow.mAttrs.getTitle()); 6458 } 6459 out.write('\n'); 6460 out.flush(); 6461 } catch (Exception e) { 6462 result = false; 6463 } finally { 6464 if (out != null) { 6465 try { 6466 out.close(); 6467 } catch (IOException e) { 6468 result = false; 6469 } 6470 } 6471 } 6472 6473 return result; 6474 } 6475 6476 /** 6477 * Sends a command to a target window. The result of the command, if any, will be 6478 * written in the output stream of the specified socket. 6479 * 6480 * The parameters must follow this syntax: 6481 * windowHashcode extra 6482 * 6483 * Where XX is the length in characeters of the windowTitle. 6484 * 6485 * The first parameter is the target window. The window with the specified hashcode 6486 * will be the target. If no target can be found, nothing happens. The extra parameters 6487 * will be delivered to the target window and as parameters to the command itself. 6488 * 6489 * @param client The remote client to sent the result, if any, to. 6490 * @param command The command to execute. 6491 * @param parameters The command parameters. 6492 * 6493 * @return True if the command was successfully delivered, false otherwise. This does 6494 * not indicate whether the command itself was successful. 6495 */ 6496 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 6497 if (isSystemSecure()) { 6498 return false; 6499 } 6500 6501 boolean success = true; 6502 Parcel data = null; 6503 Parcel reply = null; 6504 6505 BufferedWriter out = null; 6506 6507 // Any uncaught exception will crash the system process 6508 try { 6509 // Find the hashcode of the window 6510 int index = parameters.indexOf(' '); 6511 if (index == -1) { 6512 index = parameters.length(); 6513 } 6514 final String code = parameters.substring(0, index); 6515 int hashCode = (int) Long.parseLong(code, 16); 6516 6517 // Extract the command's parameter after the window description 6518 if (index < parameters.length()) { 6519 parameters = parameters.substring(index + 1); 6520 } else { 6521 parameters = ""; 6522 } 6523 6524 final WindowState window = findWindow(hashCode); 6525 if (window == null) { 6526 return false; 6527 } 6528 6529 data = Parcel.obtain(); 6530 data.writeInterfaceToken("android.view.IWindow"); 6531 data.writeString(command); 6532 data.writeString(parameters); 6533 data.writeInt(1); 6534 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 6535 6536 reply = Parcel.obtain(); 6537 6538 final IBinder binder = window.mClient.asBinder(); 6539 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 6540 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 6541 6542 reply.readException(); 6543 6544 if (!client.isOutputShutdown()) { 6545 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 6546 out.write("DONE\n"); 6547 out.flush(); 6548 } 6549 6550 } catch (Exception e) { 6551 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); 6552 success = false; 6553 } finally { 6554 if (data != null) { 6555 data.recycle(); 6556 } 6557 if (reply != null) { 6558 reply.recycle(); 6559 } 6560 if (out != null) { 6561 try { 6562 out.close(); 6563 } catch (IOException e) { 6564 6565 } 6566 } 6567 } 6568 6569 return success; 6570 } 6571 6572 public void addWindowChangeListener(WindowChangeListener listener) { 6573 synchronized(mWindowMap) { 6574 mWindowChangeListeners.add(listener); 6575 } 6576 } 6577 6578 public void removeWindowChangeListener(WindowChangeListener listener) { 6579 synchronized(mWindowMap) { 6580 mWindowChangeListeners.remove(listener); 6581 } 6582 } 6583 6584 private void notifyWindowsChanged() { 6585 WindowChangeListener[] windowChangeListeners; 6586 synchronized(mWindowMap) { 6587 if(mWindowChangeListeners.isEmpty()) { 6588 return; 6589 } 6590 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6591 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6592 } 6593 int N = windowChangeListeners.length; 6594 for(int i = 0; i < N; i++) { 6595 windowChangeListeners[i].windowsChanged(); 6596 } 6597 } 6598 6599 private void notifyFocusChanged() { 6600 WindowChangeListener[] windowChangeListeners; 6601 synchronized(mWindowMap) { 6602 if(mWindowChangeListeners.isEmpty()) { 6603 return; 6604 } 6605 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6606 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6607 } 6608 int N = windowChangeListeners.length; 6609 for(int i = 0; i < N; i++) { 6610 windowChangeListeners[i].focusChanged(); 6611 } 6612 } 6613 6614 private WindowState findWindow(int hashCode) { 6615 if (hashCode == -1) { 6616 // TODO(multidisplay): Extend to multiple displays. 6617 return getFocusedWindow(); 6618 } 6619 6620 synchronized (mWindowMap) { 6621 final int numDisplays = mDisplayContents.size(); 6622 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6623 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 6624 final int numWindows = windows.size(); 6625 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 6626 final WindowState w = windows.get(winNdx); 6627 if (System.identityHashCode(w) == hashCode) { 6628 return w; 6629 } 6630 } 6631 } 6632 } 6633 6634 return null; 6635 } 6636 6637 /* 6638 * Instruct the Activity Manager to fetch the current configuration and broadcast 6639 * that to config-changed listeners if appropriate. 6640 */ 6641 void sendNewConfiguration() { 6642 try { 6643 mActivityManager.updateConfiguration(null); 6644 } catch (RemoteException e) { 6645 } 6646 } 6647 6648 public Configuration computeNewConfiguration() { 6649 synchronized (mWindowMap) { 6650 Configuration config = computeNewConfigurationLocked(); 6651 if (config == null && mWaitingForConfig) { 6652 // Nothing changed but we are waiting for something... stop that! 6653 mWaitingForConfig = false; 6654 mLastFinishedFreezeSource = "new-config"; 6655 performLayoutAndPlaceSurfacesLocked(); 6656 } 6657 return config; 6658 } 6659 } 6660 6661 Configuration computeNewConfigurationLocked() { 6662 Configuration config = new Configuration(); 6663 config.fontScale = 0; 6664 if (!computeScreenConfigurationLocked(config)) { 6665 return null; 6666 } 6667 return config; 6668 } 6669 6670 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) { 6671 // TODO: Multidisplay: for now only use with default display. 6672 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation); 6673 if (width < displayInfo.smallestNominalAppWidth) { 6674 displayInfo.smallestNominalAppWidth = width; 6675 } 6676 if (width > displayInfo.largestNominalAppWidth) { 6677 displayInfo.largestNominalAppWidth = width; 6678 } 6679 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation); 6680 if (height < displayInfo.smallestNominalAppHeight) { 6681 displayInfo.smallestNominalAppHeight = height; 6682 } 6683 if (height > displayInfo.largestNominalAppHeight) { 6684 displayInfo.largestNominalAppHeight = height; 6685 } 6686 } 6687 6688 private int reduceConfigLayout(int curLayout, int rotation, float density, 6689 int dw, int dh) { 6690 // TODO: Multidisplay: for now only use with default display. 6691 // Get the app screen size at this rotation. 6692 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6693 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6694 6695 // Compute the screen layout size class for this rotation. 6696 int longSize = w; 6697 int shortSize = h; 6698 if (longSize < shortSize) { 6699 int tmp = longSize; 6700 longSize = shortSize; 6701 shortSize = tmp; 6702 } 6703 longSize = (int)(longSize/density); 6704 shortSize = (int)(shortSize/density); 6705 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 6706 } 6707 6708 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 6709 int dw, int dh, float density, Configuration outConfig) { 6710 // TODO: Multidisplay: for now only use with default display. 6711 6712 // We need to determine the smallest width that will occur under normal 6713 // operation. To this, start with the base screen size and compute the 6714 // width under the different possible rotations. We need to un-rotate 6715 // the current screen dimensions before doing this. 6716 int unrotDw, unrotDh; 6717 if (rotated) { 6718 unrotDw = dh; 6719 unrotDh = dw; 6720 } else { 6721 unrotDw = dw; 6722 unrotDh = dh; 6723 } 6724 displayInfo.smallestNominalAppWidth = 1<<30; 6725 displayInfo.smallestNominalAppHeight = 1<<30; 6726 displayInfo.largestNominalAppWidth = 0; 6727 displayInfo.largestNominalAppHeight = 0; 6728 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh); 6729 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw); 6730 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh); 6731 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw); 6732 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 6733 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh); 6734 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw); 6735 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); 6736 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); 6737 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 6738 outConfig.screenLayout = sl; 6739 } 6740 6741 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, 6742 int dw, int dh) { 6743 // TODO: Multidisplay: for now only use with default display. 6744 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6745 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6746 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 6747 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 6748 if (curSize == 0 || size < curSize) { 6749 curSize = size; 6750 } 6751 return curSize; 6752 } 6753 6754 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) { 6755 // TODO: Multidisplay: for now only use with default display. 6756 mTmpDisplayMetrics.setTo(dm); 6757 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 6758 final int unrotDw, unrotDh; 6759 if (rotated) { 6760 unrotDw = dh; 6761 unrotDh = dw; 6762 } else { 6763 unrotDw = dw; 6764 unrotDh = dh; 6765 } 6766 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh); 6767 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw); 6768 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh); 6769 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw); 6770 return sw; 6771 } 6772 6773 boolean computeScreenConfigurationLocked(Configuration config) { 6774 if (!mDisplayReady) { 6775 return false; 6776 } 6777 6778 // TODO(multidisplay): For now, apply Configuration to main screen only. 6779 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6780 6781 // Use the effective "visual" dimensions based on current rotation 6782 final boolean rotated = (mRotation == Surface.ROTATION_90 6783 || mRotation == Surface.ROTATION_270); 6784 final int realdw = rotated ? 6785 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; 6786 final int realdh = rotated ? 6787 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; 6788 int dw = realdw; 6789 int dh = realdh; 6790 6791 if (mAltOrientation) { 6792 if (realdw > realdh) { 6793 // Turn landscape into portrait. 6794 int maxw = (int)(realdh/1.3f); 6795 if (maxw < realdw) { 6796 dw = maxw; 6797 } 6798 } else { 6799 // Turn portrait into landscape. 6800 int maxh = (int)(realdw/1.3f); 6801 if (maxh < realdh) { 6802 dh = maxh; 6803 } 6804 } 6805 } 6806 6807 if (config != null) { 6808 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : 6809 Configuration.ORIENTATION_LANDSCAPE; 6810 } 6811 6812 // Update application display metrics. 6813 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); 6814 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); 6815 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6816 synchronized(displayContent.mDisplaySizeLock) { 6817 displayInfo.rotation = mRotation; 6818 displayInfo.logicalWidth = dw; 6819 displayInfo.logicalHeight = dh; 6820 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; 6821 displayInfo.appWidth = appWidth; 6822 displayInfo.appHeight = appHeight; 6823 displayInfo.getLogicalMetrics(mRealDisplayMetrics, 6824 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 6825 displayInfo.getAppMetrics(mDisplayMetrics); 6826 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 6827 displayContent.getDisplayId(), displayInfo); 6828 } 6829 if (false) { 6830 Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); 6831 } 6832 6833 final DisplayMetrics dm = mDisplayMetrics; 6834 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, 6835 mCompatDisplayMetrics); 6836 6837 if (config != null) { 6838 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) 6839 / dm.density); 6840 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) 6841 / dm.density); 6842 computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config); 6843 6844 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 6845 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 6846 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); 6847 config.densityDpi = displayContent.mBaseDisplayDensity; 6848 6849 // Update the configuration based on available input devices, lid switch, 6850 // and platform configuration. 6851 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6852 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6853 config.navigation = Configuration.NAVIGATION_NONAV; 6854 6855 int keyboardPresence = 0; 6856 int navigationPresence = 0; 6857 final InputDevice[] devices = mInputManager.getInputDevices(); 6858 final int len = devices.length; 6859 for (int i = 0; i < len; i++) { 6860 InputDevice device = devices[i]; 6861 if (!device.isVirtual()) { 6862 final int sources = device.getSources(); 6863 final int presenceFlag = device.isExternal() ? 6864 WindowManagerPolicy.PRESENCE_EXTERNAL : 6865 WindowManagerPolicy.PRESENCE_INTERNAL; 6866 6867 if (mIsTouchDevice) { 6868 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 6869 InputDevice.SOURCE_TOUCHSCREEN) { 6870 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 6871 } 6872 } else { 6873 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6874 } 6875 6876 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 6877 config.navigation = Configuration.NAVIGATION_TRACKBALL; 6878 navigationPresence |= presenceFlag; 6879 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 6880 && config.navigation == Configuration.NAVIGATION_NONAV) { 6881 config.navigation = Configuration.NAVIGATION_DPAD; 6882 navigationPresence |= presenceFlag; 6883 } 6884 6885 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 6886 config.keyboard = Configuration.KEYBOARD_QWERTY; 6887 keyboardPresence |= presenceFlag; 6888 } 6889 } 6890 } 6891 6892 // Determine whether a hard keyboard is available and enabled. 6893 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 6894 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 6895 mHardKeyboardAvailable = hardKeyboardAvailable; 6896 mHardKeyboardEnabled = hardKeyboardAvailable; 6897 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6898 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6899 } 6900 if (!mHardKeyboardEnabled) { 6901 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6902 } 6903 6904 // Let the policy update hidden states. 6905 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 6906 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 6907 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 6908 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 6909 } 6910 6911 return true; 6912 } 6913 6914 public boolean isHardKeyboardAvailable() { 6915 synchronized (mWindowMap) { 6916 return mHardKeyboardAvailable; 6917 } 6918 } 6919 6920 public boolean isHardKeyboardEnabled() { 6921 synchronized (mWindowMap) { 6922 return mHardKeyboardEnabled; 6923 } 6924 } 6925 6926 public void setHardKeyboardEnabled(boolean enabled) { 6927 synchronized (mWindowMap) { 6928 if (mHardKeyboardEnabled != enabled) { 6929 mHardKeyboardEnabled = enabled; 6930 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6931 } 6932 } 6933 } 6934 6935 public void setOnHardKeyboardStatusChangeListener( 6936 OnHardKeyboardStatusChangeListener listener) { 6937 synchronized (mWindowMap) { 6938 mHardKeyboardStatusChangeListener = listener; 6939 } 6940 } 6941 6942 void notifyHardKeyboardStatusChange() { 6943 final boolean available, enabled; 6944 final OnHardKeyboardStatusChangeListener listener; 6945 synchronized (mWindowMap) { 6946 listener = mHardKeyboardStatusChangeListener; 6947 available = mHardKeyboardAvailable; 6948 enabled = mHardKeyboardEnabled; 6949 } 6950 if (listener != null) { 6951 listener.onHardKeyboardStatusChange(available, enabled); 6952 } 6953 } 6954 6955 // ------------------------------------------------------------- 6956 // Drag and drop 6957 // ------------------------------------------------------------- 6958 6959 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 6960 int flags, int width, int height, Surface outSurface) { 6961 if (DEBUG_DRAG) { 6962 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 6963 + " flags=" + Integer.toHexString(flags) + " win=" + window 6964 + " asbinder=" + window.asBinder()); 6965 } 6966 6967 final int callerPid = Binder.getCallingPid(); 6968 final long origId = Binder.clearCallingIdentity(); 6969 IBinder token = null; 6970 6971 try { 6972 synchronized (mWindowMap) { 6973 try { 6974 if (mDragState == null) { 6975 // TODO(multi-display): support other displays 6976 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6977 final Display display = displayContent.getDisplay(); 6978 SurfaceControl surface = new SurfaceControl(session, "drag surface", 6979 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 6980 surface.setLayerStack(display.getLayerStack()); 6981 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 6982 + surface + ": CREATE"); 6983 outSurface.copyFrom(surface); 6984 final IBinder winBinder = window.asBinder(); 6985 token = new Binder(); 6986 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 6987 token = mDragState.mToken = new Binder(); 6988 6989 // 5 second timeout for this window to actually begin the drag 6990 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 6991 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 6992 mH.sendMessageDelayed(msg, 5000); 6993 } else { 6994 Slog.w(TAG, "Drag already in progress"); 6995 } 6996 } catch (OutOfResourcesException e) { 6997 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 6998 if (mDragState != null) { 6999 mDragState.reset(); 7000 mDragState = null; 7001 } 7002 } 7003 } 7004 } finally { 7005 Binder.restoreCallingIdentity(origId); 7006 } 7007 7008 return token; 7009 } 7010 7011 // ------------------------------------------------------------- 7012 // Input Events and Focus Management 7013 // ------------------------------------------------------------- 7014 7015 final InputMonitor mInputMonitor = new InputMonitor(this); 7016 private boolean mEventDispatchingEnabled; 7017 7018 @Override 7019 public void pauseKeyDispatching(IBinder _token) { 7020 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7021 "pauseKeyDispatching()")) { 7022 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7023 } 7024 7025 synchronized (mWindowMap) { 7026 WindowToken token = mTokenMap.get(_token); 7027 if (token != null) { 7028 mInputMonitor.pauseDispatchingLw(token); 7029 } 7030 } 7031 } 7032 7033 @Override 7034 public void resumeKeyDispatching(IBinder _token) { 7035 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7036 "resumeKeyDispatching()")) { 7037 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7038 } 7039 7040 synchronized (mWindowMap) { 7041 WindowToken token = mTokenMap.get(_token); 7042 if (token != null) { 7043 mInputMonitor.resumeDispatchingLw(token); 7044 } 7045 } 7046 } 7047 7048 @Override 7049 public void setEventDispatching(boolean enabled) { 7050 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7051 "setEventDispatching()")) { 7052 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7053 } 7054 7055 synchronized (mWindowMap) { 7056 mEventDispatchingEnabled = enabled; 7057 if (mDisplayEnabled) { 7058 mInputMonitor.setEventDispatchingLw(enabled); 7059 } 7060 } 7061 } 7062 7063 private WindowState getFocusedWindow() { 7064 synchronized (mWindowMap) { 7065 return getFocusedWindowLocked(); 7066 } 7067 } 7068 7069 private WindowState getFocusedWindowLocked() { 7070 return mCurrentFocus; 7071 } 7072 7073 public boolean detectSafeMode() { 7074 if (!mInputMonitor.waitForInputDevicesReady( 7075 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 7076 Slog.w(TAG, "Devices still not ready after waiting " 7077 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 7078 + " milliseconds before attempting to detect safe mode."); 7079 } 7080 7081 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7082 KeyEvent.KEYCODE_MENU); 7083 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 7084 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 7085 KeyEvent.KEYCODE_DPAD_CENTER); 7086 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 7087 InputManagerService.BTN_MOUSE); 7088 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7089 KeyEvent.KEYCODE_VOLUME_DOWN); 7090 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 7091 || volumeDownState > 0; 7092 try { 7093 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 7094 mSafeMode = true; 7095 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 7096 } 7097 } catch (IllegalArgumentException e) { 7098 } 7099 if (mSafeMode) { 7100 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 7101 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 7102 } else { 7103 Log.i(TAG, "SAFE MODE not enabled"); 7104 } 7105 mPolicy.setSafeMode(mSafeMode); 7106 return mSafeMode; 7107 } 7108 7109 public void displayReady() { 7110 displayReady(Display.DEFAULT_DISPLAY); 7111 7112 synchronized(mWindowMap) { 7113 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7114 readForcedDisplaySizeAndDensityLocked(displayContent); 7115 mDisplayReady = true; 7116 } 7117 7118 try { 7119 mActivityManager.updateConfiguration(null); 7120 } catch (RemoteException e) { 7121 } 7122 7123 synchronized(mWindowMap) { 7124 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 7125 PackageManager.FEATURE_TOUCHSCREEN); 7126 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 7127 } 7128 7129 try { 7130 mActivityManager.updateConfiguration(null); 7131 } catch (RemoteException e) { 7132 } 7133 } 7134 7135 private void displayReady(int displayId) { 7136 synchronized(mWindowMap) { 7137 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7138 if (displayContent != null) { 7139 mAnimator.addDisplayLocked(displayId); 7140 synchronized(displayContent.mDisplaySizeLock) { 7141 // Bootstrap the default logical display from the display manager. 7142 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7143 DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId); 7144 if (newDisplayInfo != null) { 7145 displayInfo.copyFrom(newDisplayInfo); 7146 } 7147 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; 7148 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; 7149 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; 7150 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; 7151 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; 7152 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; 7153 displayContent.mBaseDisplayRect.set(0, 0, 7154 displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight); 7155 } 7156 } 7157 } 7158 } 7159 7160 public void systemReady() { 7161 mPolicy.systemReady(); 7162 } 7163 7164 // ------------------------------------------------------------- 7165 // Async Handler 7166 // ------------------------------------------------------------- 7167 7168 final class H extends Handler { 7169 public static final int REPORT_FOCUS_CHANGE = 2; 7170 public static final int REPORT_LOSING_FOCUS = 3; 7171 public static final int DO_TRAVERSAL = 4; 7172 public static final int ADD_STARTING = 5; 7173 public static final int REMOVE_STARTING = 6; 7174 public static final int FINISHED_STARTING = 7; 7175 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 7176 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 7177 public static final int WINDOW_FREEZE_TIMEOUT = 11; 7178 7179 public static final int APP_TRANSITION_TIMEOUT = 13; 7180 public static final int PERSIST_ANIMATION_SCALE = 14; 7181 public static final int FORCE_GC = 15; 7182 public static final int ENABLE_SCREEN = 16; 7183 public static final int APP_FREEZE_TIMEOUT = 17; 7184 public static final int SEND_NEW_CONFIGURATION = 18; 7185 public static final int REPORT_WINDOWS_CHANGE = 19; 7186 public static final int DRAG_START_TIMEOUT = 20; 7187 public static final int DRAG_END_TIMEOUT = 21; 7188 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 7189 public static final int BOOT_TIMEOUT = 23; 7190 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 7191 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 7192 public static final int DO_ANIMATION_CALLBACK = 26; 7193 7194 public static final int DO_DISPLAY_ADDED = 27; 7195 public static final int DO_DISPLAY_REMOVED = 28; 7196 public static final int DO_DISPLAY_CHANGED = 29; 7197 7198 public static final int CLIENT_FREEZE_TIMEOUT = 30; 7199 public static final int TAP_OUTSIDE_STACK = 31; 7200 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 7201 7202 public static final int ALL_WINDOWS_DRAWN = 33; 7203 7204 public static final int NEW_ANIMATOR_SCALE = 34; 7205 7206 @Override 7207 public void handleMessage(Message msg) { 7208 if (DEBUG_WINDOW_TRACE) { 7209 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 7210 } 7211 switch (msg.what) { 7212 case REPORT_FOCUS_CHANGE: { 7213 WindowState lastFocus; 7214 WindowState newFocus; 7215 7216 synchronized(mWindowMap) { 7217 lastFocus = mLastFocus; 7218 newFocus = mCurrentFocus; 7219 if (lastFocus == newFocus) { 7220 // Focus is not changing, so nothing to do. 7221 return; 7222 } 7223 mLastFocus = newFocus; 7224 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus + 7225 " to " + newFocus); 7226 if (newFocus != null && lastFocus != null 7227 && !newFocus.isDisplayedLw()) { 7228 //Slog.i(TAG, "Delaying loss of focus..."); 7229 mLosingFocus.add(lastFocus); 7230 lastFocus = null; 7231 } 7232 } 7233 7234 //System.out.println("Changing focus from " + lastFocus 7235 // + " to " + newFocus); 7236 if (newFocus != null) { 7237 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus); 7238 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 7239 notifyFocusChanged(); 7240 } 7241 7242 if (lastFocus != null) { 7243 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus); 7244 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 7245 } 7246 } break; 7247 7248 case REPORT_LOSING_FOCUS: { 7249 ArrayList<WindowState> losers; 7250 7251 synchronized(mWindowMap) { 7252 losers = mLosingFocus; 7253 mLosingFocus = new ArrayList<WindowState>(); 7254 } 7255 7256 final int N = losers.size(); 7257 for (int i=0; i<N; i++) { 7258 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " + 7259 losers.get(i)); 7260 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 7261 } 7262 } break; 7263 7264 case DO_TRAVERSAL: { 7265 synchronized(mWindowMap) { 7266 mTraversalScheduled = false; 7267 performLayoutAndPlaceSurfacesLocked(); 7268 } 7269 } break; 7270 7271 case ADD_STARTING: { 7272 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7273 final StartingData sd = wtoken.startingData; 7274 7275 if (sd == null) { 7276 // Animation has been canceled... do nothing. 7277 return; 7278 } 7279 7280 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 7281 + wtoken + ": pkg=" + sd.pkg); 7282 7283 View view = null; 7284 try { 7285 view = mPolicy.addStartingWindow( 7286 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 7287 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags); 7288 } catch (Exception e) { 7289 Slog.w(TAG, "Exception when adding starting window", e); 7290 } 7291 7292 if (view != null) { 7293 boolean abort = false; 7294 7295 synchronized(mWindowMap) { 7296 if (wtoken.removed || wtoken.startingData == null) { 7297 // If the window was successfully added, then 7298 // we need to remove it. 7299 if (wtoken.startingWindow != null) { 7300 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7301 "Aborted starting " + wtoken 7302 + ": removed=" + wtoken.removed 7303 + " startingData=" + wtoken.startingData); 7304 wtoken.startingWindow = null; 7305 wtoken.startingData = null; 7306 abort = true; 7307 } 7308 } else { 7309 wtoken.startingView = view; 7310 } 7311 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7312 "Added starting " + wtoken 7313 + ": startingWindow=" 7314 + wtoken.startingWindow + " startingView=" 7315 + wtoken.startingView); 7316 } 7317 7318 if (abort) { 7319 try { 7320 mPolicy.removeStartingWindow(wtoken.token, view); 7321 } catch (Exception e) { 7322 Slog.w(TAG, "Exception when removing starting window", e); 7323 } 7324 } 7325 } 7326 } break; 7327 7328 case REMOVE_STARTING: { 7329 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7330 IBinder token = null; 7331 View view = null; 7332 synchronized (mWindowMap) { 7333 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7334 + wtoken + ": startingWindow=" 7335 + wtoken.startingWindow + " startingView=" 7336 + wtoken.startingView); 7337 if (wtoken.startingWindow != null) { 7338 view = wtoken.startingView; 7339 token = wtoken.token; 7340 wtoken.startingData = null; 7341 wtoken.startingView = null; 7342 wtoken.startingWindow = null; 7343 wtoken.startingDisplayed = false; 7344 } 7345 } 7346 if (view != null) { 7347 try { 7348 mPolicy.removeStartingWindow(token, view); 7349 } catch (Exception e) { 7350 Slog.w(TAG, "Exception when removing starting window", e); 7351 } 7352 } 7353 } break; 7354 7355 case FINISHED_STARTING: { 7356 IBinder token = null; 7357 View view = null; 7358 while (true) { 7359 synchronized (mWindowMap) { 7360 final int N = mFinishedStarting.size(); 7361 if (N <= 0) { 7362 break; 7363 } 7364 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7365 7366 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7367 "Finished starting " + wtoken 7368 + ": startingWindow=" + wtoken.startingWindow 7369 + " startingView=" + wtoken.startingView); 7370 7371 if (wtoken.startingWindow == null) { 7372 continue; 7373 } 7374 7375 view = wtoken.startingView; 7376 token = wtoken.token; 7377 wtoken.startingData = null; 7378 wtoken.startingView = null; 7379 wtoken.startingWindow = null; 7380 wtoken.startingDisplayed = false; 7381 } 7382 7383 try { 7384 mPolicy.removeStartingWindow(token, view); 7385 } catch (Exception e) { 7386 Slog.w(TAG, "Exception when removing starting window", e); 7387 } 7388 } 7389 } break; 7390 7391 case REPORT_APPLICATION_TOKEN_DRAWN: { 7392 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7393 7394 try { 7395 if (DEBUG_VISIBILITY) Slog.v( 7396 TAG, "Reporting drawn in " + wtoken); 7397 wtoken.appToken.windowsDrawn(); 7398 } catch (RemoteException ex) { 7399 } 7400 } break; 7401 7402 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7403 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7404 7405 boolean nowVisible = msg.arg1 != 0; 7406 boolean nowGone = msg.arg2 != 0; 7407 7408 try { 7409 if (DEBUG_VISIBILITY) Slog.v( 7410 TAG, "Reporting visible in " + wtoken 7411 + " visible=" + nowVisible 7412 + " gone=" + nowGone); 7413 if (nowVisible) { 7414 wtoken.appToken.windowsVisible(); 7415 } else { 7416 wtoken.appToken.windowsGone(); 7417 } 7418 } catch (RemoteException ex) { 7419 } 7420 } break; 7421 7422 case WINDOW_FREEZE_TIMEOUT: { 7423 // TODO(multidisplay): Can non-default displays rotate? 7424 synchronized (mWindowMap) { 7425 Slog.w(TAG, "Window freeze timeout expired."); 7426 final WindowList windows = getDefaultWindowListLocked(); 7427 int i = windows.size(); 7428 while (i > 0) { 7429 i--; 7430 WindowState w = windows.get(i); 7431 if (w.mOrientationChanging) { 7432 w.mOrientationChanging = false; 7433 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 7434 - mDisplayFreezeTime); 7435 Slog.w(TAG, "Force clearing orientation change: " + w); 7436 } 7437 } 7438 performLayoutAndPlaceSurfacesLocked(); 7439 } 7440 break; 7441 } 7442 7443 case APP_TRANSITION_TIMEOUT: { 7444 synchronized (mWindowMap) { 7445 if (mAppTransition.isTransitionSet()) { 7446 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT"); 7447 mAppTransition.setTimeout(); 7448 performLayoutAndPlaceSurfacesLocked(); 7449 } 7450 } 7451 break; 7452 } 7453 7454 case PERSIST_ANIMATION_SCALE: { 7455 Settings.Global.putFloat(mContext.getContentResolver(), 7456 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 7457 Settings.Global.putFloat(mContext.getContentResolver(), 7458 Settings.Global.TRANSITION_ANIMATION_SCALE, 7459 mTransitionAnimationScaleSetting); 7460 Settings.Global.putFloat(mContext.getContentResolver(), 7461 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting); 7462 break; 7463 } 7464 7465 case FORCE_GC: { 7466 synchronized (mWindowMap) { 7467 // Since we're holding both mWindowMap and mAnimator we don't need to 7468 // hold mAnimator.mLayoutToAnim. 7469 if (mAnimator.mAnimating || mAnimationScheduled) { 7470 // If we are animating, don't do the gc now but 7471 // delay a bit so we don't interrupt the animation. 7472 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 7473 return; 7474 } 7475 // If we are currently rotating the display, it will 7476 // schedule a new message when done. 7477 if (mDisplayFrozen) { 7478 return; 7479 } 7480 } 7481 Runtime.getRuntime().gc(); 7482 break; 7483 } 7484 7485 case ENABLE_SCREEN: { 7486 performEnableScreen(); 7487 break; 7488 } 7489 7490 case APP_FREEZE_TIMEOUT: { 7491 synchronized (mWindowMap) { 7492 Slog.w(TAG, "App freeze timeout expired."); 7493 final int numStacks = mStackIdToStack.size(); 7494 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 7495 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 7496 final ArrayList<Task> tasks = stack.getTasks(); 7497 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 7498 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 7499 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 7500 AppWindowToken tok = tokens.get(tokenNdx); 7501 if (tok.mAppAnimator.freezingScreen) { 7502 Slog.w(TAG, "Force clearing freeze: " + tok); 7503 unsetAppFreezingScreenLocked(tok, true, true); 7504 } 7505 } 7506 } 7507 } 7508 } 7509 break; 7510 } 7511 7512 case CLIENT_FREEZE_TIMEOUT: { 7513 synchronized (mWindowMap) { 7514 if (mClientFreezingScreen) { 7515 mClientFreezingScreen = false; 7516 mLastFinishedFreezeSource = "client-timeout"; 7517 stopFreezingDisplayLocked(); 7518 } 7519 } 7520 break; 7521 } 7522 7523 case SEND_NEW_CONFIGURATION: { 7524 removeMessages(SEND_NEW_CONFIGURATION); 7525 sendNewConfiguration(); 7526 break; 7527 } 7528 7529 case REPORT_WINDOWS_CHANGE: { 7530 if (mWindowsChanged) { 7531 synchronized (mWindowMap) { 7532 mWindowsChanged = false; 7533 } 7534 notifyWindowsChanged(); 7535 } 7536 break; 7537 } 7538 7539 case DRAG_START_TIMEOUT: { 7540 IBinder win = (IBinder)msg.obj; 7541 if (DEBUG_DRAG) { 7542 Slog.w(TAG, "Timeout starting drag by win " + win); 7543 } 7544 synchronized (mWindowMap) { 7545 // !!! TODO: ANR the app that has failed to start the drag in time 7546 if (mDragState != null) { 7547 mDragState.unregister(); 7548 mInputMonitor.updateInputWindowsLw(true /*force*/); 7549 mDragState.reset(); 7550 mDragState = null; 7551 } 7552 } 7553 break; 7554 } 7555 7556 case DRAG_END_TIMEOUT: { 7557 IBinder win = (IBinder)msg.obj; 7558 if (DEBUG_DRAG) { 7559 Slog.w(TAG, "Timeout ending drag to win " + win); 7560 } 7561 synchronized (mWindowMap) { 7562 // !!! TODO: ANR the drag-receiving app 7563 if (mDragState != null) { 7564 mDragState.mDragResult = false; 7565 mDragState.endDragLw(); 7566 } 7567 } 7568 break; 7569 } 7570 7571 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7572 notifyHardKeyboardStatusChange(); 7573 break; 7574 } 7575 7576 case BOOT_TIMEOUT: { 7577 performBootTimeout(); 7578 break; 7579 } 7580 7581 case WAITING_FOR_DRAWN_TIMEOUT: { 7582 Runnable callback = null; 7583 synchronized (mWindowMap) { 7584 Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn); 7585 mWaitingForDrawn.clear(); 7586 callback = mWaitingForDrawnCallback; 7587 mWaitingForDrawnCallback = null; 7588 } 7589 if (callback != null) { 7590 callback.run(); 7591 } 7592 break; 7593 } 7594 7595 case SHOW_STRICT_MODE_VIOLATION: { 7596 showStrictModeViolation(msg.arg1, msg.arg2); 7597 break; 7598 } 7599 7600 case DO_ANIMATION_CALLBACK: { 7601 try { 7602 ((IRemoteCallback)msg.obj).sendResult(null); 7603 } catch (RemoteException e) { 7604 } 7605 break; 7606 } 7607 7608 case DO_DISPLAY_ADDED: 7609 handleDisplayAdded(msg.arg1); 7610 break; 7611 7612 case DO_DISPLAY_REMOVED: 7613 synchronized (mWindowMap) { 7614 handleDisplayRemovedLocked(msg.arg1); 7615 } 7616 break; 7617 7618 case DO_DISPLAY_CHANGED: 7619 synchronized (mWindowMap) { 7620 handleDisplayChangedLocked(msg.arg1); 7621 } 7622 break; 7623 7624 case TAP_OUTSIDE_STACK: { 7625 int stackId; 7626 synchronized (mWindowMap) { 7627 stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2); 7628 } 7629 if (stackId >= 0) { 7630 try { 7631 mActivityManager.setFocusedStack(stackId); 7632 } catch (RemoteException e) { 7633 } 7634 } 7635 } 7636 break; 7637 case NOTIFY_ACTIVITY_DRAWN: 7638 try { 7639 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 7640 } catch (RemoteException e) { 7641 } 7642 break; 7643 case ALL_WINDOWS_DRAWN: { 7644 Runnable callback; 7645 synchronized (mWindowMap) { 7646 callback = mWaitingForDrawnCallback; 7647 mWaitingForDrawnCallback = null; 7648 } 7649 if (callback != null) { 7650 callback.run(); 7651 } 7652 } 7653 case NEW_ANIMATOR_SCALE: { 7654 float scale = getCurrentAnimatorScale(); 7655 ValueAnimator.setDurationScale(scale); 7656 Session session = (Session)msg.obj; 7657 if (session != null) { 7658 try { 7659 session.mCallback.onAnimatorScaleChanged(scale); 7660 } catch (RemoteException e) { 7661 } 7662 } else { 7663 ArrayList<IWindowSessionCallback> callbacks 7664 = new ArrayList<IWindowSessionCallback>(); 7665 synchronized (mWindowMap) { 7666 for (int i=0; i<mSessions.size(); i++) { 7667 callbacks.add(mSessions.valueAt(i).mCallback); 7668 } 7669 7670 } 7671 for (int i=0; i<callbacks.size(); i++) { 7672 try { 7673 callbacks.get(i).onAnimatorScaleChanged(scale); 7674 } catch (RemoteException e) { 7675 } 7676 } 7677 } 7678 } 7679 break; 7680 } 7681 if (DEBUG_WINDOW_TRACE) { 7682 Slog.v(TAG, "handleMessage: exit"); 7683 } 7684 } 7685 } 7686 7687 // ------------------------------------------------------------- 7688 // IWindowManager API 7689 // ------------------------------------------------------------- 7690 7691 @Override 7692 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, 7693 IInputContext inputContext) { 7694 if (client == null) throw new IllegalArgumentException("null client"); 7695 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7696 Session session = new Session(this, callback, client, inputContext); 7697 return session; 7698 } 7699 7700 @Override 7701 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7702 synchronized (mWindowMap) { 7703 // The focus for the client is the window immediately below 7704 // where we would place the input method window. 7705 int idx = findDesiredInputMethodWindowIndexLocked(false); 7706 if (idx > 0) { 7707 // TODO(multidisplay): IMEs are only supported on the default display. 7708 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 7709 if (DEBUG_INPUT_METHOD) { 7710 Slog.i(TAG, "Desired input method target: " + imFocus); 7711 Slog.i(TAG, "Current focus: " + mCurrentFocus); 7712 Slog.i(TAG, "Last focus: " + mLastFocus); 7713 } 7714 if (imFocus != null) { 7715 // This may be a starting window, in which case we still want 7716 // to count it as okay. 7717 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7718 && imFocus.mAppToken != null) { 7719 // The client has definitely started, so it really should 7720 // have a window in this app token. Let's look for it. 7721 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7722 WindowState w = imFocus.mAppToken.windows.get(i); 7723 if (w != imFocus) { 7724 Log.i(TAG, "Switching to real app window: " + w); 7725 imFocus = w; 7726 break; 7727 } 7728 } 7729 } 7730 if (DEBUG_INPUT_METHOD) { 7731 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7732 if (imFocus.mSession.mClient != null) { 7733 Slog.i(TAG, "IM target client binder: " 7734 + imFocus.mSession.mClient.asBinder()); 7735 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 7736 } 7737 } 7738 if (imFocus.mSession.mClient != null && 7739 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7740 return true; 7741 } 7742 } 7743 } 7744 7745 // Okay, how about this... what is the current focus? 7746 // It seems in some cases we may not have moved the IM 7747 // target window, such as when it was in a pop-up window, 7748 // so let's also look at the current focus. (An example: 7749 // go to Gmail, start searching so the keyboard goes up, 7750 // press home. Sometimes the IME won't go down.) 7751 // Would be nice to fix this more correctly, but it's 7752 // way at the end of a release, and this should be good enough. 7753 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 7754 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7755 return true; 7756 } 7757 } 7758 return false; 7759 } 7760 7761 @Override 7762 public void getInitialDisplaySize(int displayId, Point size) { 7763 synchronized (mWindowMap) { 7764 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7765 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7766 synchronized(displayContent.mDisplaySizeLock) { 7767 size.x = displayContent.mInitialDisplayWidth; 7768 size.y = displayContent.mInitialDisplayHeight; 7769 } 7770 } 7771 } 7772 } 7773 7774 @Override 7775 public void getBaseDisplaySize(int displayId, Point size) { 7776 synchronized (mWindowMap) { 7777 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7778 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7779 synchronized(displayContent.mDisplaySizeLock) { 7780 size.x = displayContent.mBaseDisplayWidth; 7781 size.y = displayContent.mBaseDisplayHeight; 7782 } 7783 } 7784 } 7785 } 7786 7787 @Override 7788 public void setForcedDisplaySize(int displayId, int width, int height) { 7789 if (mContext.checkCallingOrSelfPermission( 7790 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7791 PackageManager.PERMISSION_GRANTED) { 7792 throw new SecurityException("Must hold permission " + 7793 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7794 } 7795 if (displayId != Display.DEFAULT_DISPLAY) { 7796 throw new IllegalArgumentException("Can only set the default display"); 7797 } 7798 final long ident = Binder.clearCallingIdentity(); 7799 try { 7800 synchronized(mWindowMap) { 7801 // Set some sort of reasonable bounds on the size of the display that we 7802 // will try to emulate. 7803 final int MIN_WIDTH = 200; 7804 final int MIN_HEIGHT = 200; 7805 final int MAX_SCALE = 2; 7806 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7807 if (displayContent != null) { 7808 width = Math.min(Math.max(width, MIN_WIDTH), 7809 displayContent.mInitialDisplayWidth * MAX_SCALE); 7810 height = Math.min(Math.max(height, MIN_HEIGHT), 7811 displayContent.mInitialDisplayHeight * MAX_SCALE); 7812 setForcedDisplaySizeLocked(displayContent, width, height); 7813 Settings.Global.putString(mContext.getContentResolver(), 7814 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 7815 } 7816 } 7817 } finally { 7818 Binder.restoreCallingIdentity(ident); 7819 } 7820 } 7821 7822 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 7823 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 7824 Settings.Global.DISPLAY_SIZE_FORCED); 7825 if (sizeStr == null || sizeStr.length() == 0) { 7826 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 7827 } 7828 if (sizeStr != null && sizeStr.length() > 0) { 7829 final int pos = sizeStr.indexOf(','); 7830 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 7831 int width, height; 7832 try { 7833 width = Integer.parseInt(sizeStr.substring(0, pos)); 7834 height = Integer.parseInt(sizeStr.substring(pos+1)); 7835 synchronized(displayContent.mDisplaySizeLock) { 7836 if (displayContent.mBaseDisplayWidth != width 7837 || displayContent.mBaseDisplayHeight != height) { 7838 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 7839 displayContent.mBaseDisplayWidth = width; 7840 displayContent.mBaseDisplayHeight = height; 7841 } 7842 } 7843 } catch (NumberFormatException ex) { 7844 } 7845 } 7846 } 7847 String densityStr = Settings.Global.getString(mContext.getContentResolver(), 7848 Settings.Global.DISPLAY_DENSITY_FORCED); 7849 if (densityStr == null || densityStr.length() == 0) { 7850 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 7851 } 7852 if (densityStr != null && densityStr.length() > 0) { 7853 int density; 7854 try { 7855 density = Integer.parseInt(densityStr); 7856 synchronized(displayContent.mDisplaySizeLock) { 7857 if (displayContent.mBaseDisplayDensity != density) { 7858 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 7859 displayContent.mBaseDisplayDensity = density; 7860 } 7861 } 7862 } catch (NumberFormatException ex) { 7863 } 7864 } 7865 } 7866 7867 // displayContent must not be null 7868 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 7869 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7870 7871 synchronized(displayContent.mDisplaySizeLock) { 7872 displayContent.mBaseDisplayWidth = width; 7873 displayContent.mBaseDisplayHeight = height; 7874 } 7875 reconfigureDisplayLocked(displayContent); 7876 } 7877 7878 @Override 7879 public void clearForcedDisplaySize(int displayId) { 7880 if (mContext.checkCallingOrSelfPermission( 7881 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7882 PackageManager.PERMISSION_GRANTED) { 7883 throw new SecurityException("Must hold permission " + 7884 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7885 } 7886 if (displayId != Display.DEFAULT_DISPLAY) { 7887 throw new IllegalArgumentException("Can only set the default display"); 7888 } 7889 final long ident = Binder.clearCallingIdentity(); 7890 try { 7891 synchronized(mWindowMap) { 7892 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7893 if (displayContent != null) { 7894 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 7895 displayContent.mInitialDisplayHeight); 7896 Settings.Global.putString(mContext.getContentResolver(), 7897 Settings.Global.DISPLAY_SIZE_FORCED, ""); 7898 } 7899 } 7900 } finally { 7901 Binder.restoreCallingIdentity(ident); 7902 } 7903 } 7904 7905 @Override 7906 public int getInitialDisplayDensity(int displayId) { 7907 synchronized (mWindowMap) { 7908 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7909 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7910 synchronized(displayContent.mDisplaySizeLock) { 7911 return displayContent.mInitialDisplayDensity; 7912 } 7913 } 7914 } 7915 return -1; 7916 } 7917 7918 @Override 7919 public int getBaseDisplayDensity(int displayId) { 7920 synchronized (mWindowMap) { 7921 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7922 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7923 synchronized(displayContent.mDisplaySizeLock) { 7924 return displayContent.mBaseDisplayDensity; 7925 } 7926 } 7927 } 7928 return -1; 7929 } 7930 7931 @Override 7932 public void setForcedDisplayDensity(int displayId, int density) { 7933 if (mContext.checkCallingOrSelfPermission( 7934 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7935 PackageManager.PERMISSION_GRANTED) { 7936 throw new SecurityException("Must hold permission " + 7937 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7938 } 7939 if (displayId != Display.DEFAULT_DISPLAY) { 7940 throw new IllegalArgumentException("Can only set the default display"); 7941 } 7942 final long ident = Binder.clearCallingIdentity(); 7943 try { 7944 synchronized(mWindowMap) { 7945 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7946 if (displayContent != null) { 7947 setForcedDisplayDensityLocked(displayContent, density); 7948 Settings.Global.putString(mContext.getContentResolver(), 7949 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 7950 } 7951 } 7952 } finally { 7953 Binder.restoreCallingIdentity(ident); 7954 } 7955 } 7956 7957 // displayContent must not be null 7958 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 7959 Slog.i(TAG, "Using new display density: " + density); 7960 7961 synchronized(displayContent.mDisplaySizeLock) { 7962 displayContent.mBaseDisplayDensity = density; 7963 } 7964 reconfigureDisplayLocked(displayContent); 7965 } 7966 7967 @Override 7968 public void clearForcedDisplayDensity(int displayId) { 7969 if (mContext.checkCallingOrSelfPermission( 7970 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7971 PackageManager.PERMISSION_GRANTED) { 7972 throw new SecurityException("Must hold permission " + 7973 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7974 } 7975 if (displayId != Display.DEFAULT_DISPLAY) { 7976 throw new IllegalArgumentException("Can only set the default display"); 7977 } 7978 final long ident = Binder.clearCallingIdentity(); 7979 try { 7980 synchronized(mWindowMap) { 7981 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7982 if (displayContent != null) { 7983 setForcedDisplayDensityLocked(displayContent, 7984 displayContent.mInitialDisplayDensity); 7985 Settings.Global.putString(mContext.getContentResolver(), 7986 Settings.Global.DISPLAY_DENSITY_FORCED, ""); 7987 } 7988 } 7989 } finally { 7990 Binder.restoreCallingIdentity(ident); 7991 } 7992 } 7993 7994 // displayContent must not be null 7995 private void reconfigureDisplayLocked(DisplayContent displayContent) { 7996 // TODO: Multidisplay: for now only use with default display. 7997 configureDisplayPolicyLocked(displayContent); 7998 displayContent.layoutNeeded = true; 7999 8000 boolean configChanged = updateOrientationFromAppTokensLocked(false); 8001 mTempConfiguration.setToDefaults(); 8002 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 8003 if (computeScreenConfigurationLocked(mTempConfiguration)) { 8004 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 8005 configChanged = true; 8006 } 8007 } 8008 8009 if (configChanged) { 8010 mWaitingForConfig = true; 8011 startFreezingDisplayLocked(false, 0, 0); 8012 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8013 } 8014 8015 performLayoutAndPlaceSurfacesLocked(); 8016 } 8017 8018 private void configureDisplayPolicyLocked(DisplayContent displayContent) { 8019 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 8020 displayContent.mBaseDisplayWidth, 8021 displayContent.mBaseDisplayHeight, 8022 displayContent.mBaseDisplayDensity); 8023 8024 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8025 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 8026 displayInfo.overscanLeft, displayInfo.overscanTop, 8027 displayInfo.overscanRight, displayInfo.overscanBottom); 8028 } 8029 8030 @Override 8031 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 8032 if (mContext.checkCallingOrSelfPermission( 8033 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8034 PackageManager.PERMISSION_GRANTED) { 8035 throw new SecurityException("Must hold permission " + 8036 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8037 } 8038 final long ident = Binder.clearCallingIdentity(); 8039 try { 8040 synchronized(mWindowMap) { 8041 DisplayContent displayContent = getDisplayContentLocked(displayId); 8042 if (displayContent != null) { 8043 setOverscanLocked(displayContent, left, top, right, bottom); 8044 } 8045 } 8046 } finally { 8047 Binder.restoreCallingIdentity(ident); 8048 } 8049 } 8050 8051 private void setOverscanLocked(DisplayContent displayContent, 8052 int left, int top, int right, int bottom) { 8053 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8054 synchronized (displayContent.mDisplaySizeLock) { 8055 displayInfo.overscanLeft = left; 8056 displayInfo.overscanTop = top; 8057 displayInfo.overscanRight = right; 8058 displayInfo.overscanBottom = bottom; 8059 } 8060 8061 mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom); 8062 mDisplaySettings.writeSettingsLocked(); 8063 8064 reconfigureDisplayLocked(displayContent); 8065 } 8066 8067 // ------------------------------------------------------------- 8068 // Internals 8069 // ------------------------------------------------------------- 8070 8071 final WindowState windowForClientLocked(Session session, IWindow client, 8072 boolean throwOnError) { 8073 return windowForClientLocked(session, client.asBinder(), throwOnError); 8074 } 8075 8076 final WindowState windowForClientLocked(Session session, IBinder client, 8077 boolean throwOnError) { 8078 WindowState win = mWindowMap.get(client); 8079 if (localLOGV) Slog.v( 8080 TAG, "Looking up client " + client + ": " + win); 8081 if (win == null) { 8082 RuntimeException ex = new IllegalArgumentException( 8083 "Requested window " + client + " does not exist"); 8084 if (throwOnError) { 8085 throw ex; 8086 } 8087 Slog.w(TAG, "Failed looking up window", ex); 8088 return null; 8089 } 8090 if (session != null && win.mSession != session) { 8091 RuntimeException ex = new IllegalArgumentException( 8092 "Requested window " + client + " is in session " + 8093 win.mSession + ", not " + session); 8094 if (throwOnError) { 8095 throw ex; 8096 } 8097 Slog.w(TAG, "Failed looking up window", ex); 8098 return null; 8099 } 8100 8101 return win; 8102 } 8103 8104 final void rebuildAppWindowListLocked() { 8105 rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); 8106 } 8107 8108 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 8109 final WindowList windows = displayContent.getWindowList(); 8110 int NW = windows.size(); 8111 int i; 8112 int lastBelow = -1; 8113 int numRemoved = 0; 8114 8115 if (mRebuildTmp.length < NW) { 8116 mRebuildTmp = new WindowState[NW+10]; 8117 } 8118 8119 // First remove all existing app windows. 8120 i=0; 8121 while (i < NW) { 8122 WindowState w = windows.get(i); 8123 if (w.mAppToken != null) { 8124 WindowState win = windows.remove(i); 8125 win.mRebuilding = true; 8126 mRebuildTmp[numRemoved] = win; 8127 mWindowsChanged = true; 8128 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win); 8129 NW--; 8130 numRemoved++; 8131 continue; 8132 } else if (lastBelow == i-1) { 8133 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8134 lastBelow = i; 8135 } 8136 } 8137 i++; 8138 } 8139 8140 // Keep whatever windows were below the app windows still below, 8141 // by skipping them. 8142 lastBelow++; 8143 i = lastBelow; 8144 8145 // First add all of the exiting app tokens... these are no longer 8146 // in the main app list, but still have windows shown. We put them 8147 // in the back because now that the animation is over we no longer 8148 // will care about them. 8149 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 8150 final int numStacks = stacks.size(); 8151 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8152 AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens; 8153 int NT = exitingAppTokens.size(); 8154 for (int j = 0; j < NT; j++) { 8155 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 8156 } 8157 } 8158 8159 // And add in the still active app tokens in Z order. 8160 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8161 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8162 final int numTasks = tasks.size(); 8163 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 8164 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8165 final int numTokens = tokens.size(); 8166 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 8167 final AppWindowToken wtoken = tokens.get(tokenNdx); 8168 if (wtoken.mDeferRemoval) { 8169 continue; 8170 } 8171 i = reAddAppWindowsLocked(displayContent, i, wtoken); 8172 } 8173 } 8174 } 8175 8176 i -= lastBelow; 8177 if (i != numRemoved) { 8178 Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " + 8179 numRemoved + " windows but added " + i, 8180 new RuntimeException("here").fillInStackTrace()); 8181 for (i=0; i<numRemoved; i++) { 8182 WindowState ws = mRebuildTmp[i]; 8183 if (ws.mRebuilding) { 8184 StringWriter sw = new StringWriter(); 8185 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 8186 ws.dump(pw, "", true); 8187 pw.flush(); 8188 Slog.w(TAG, "This window was lost: " + ws); 8189 Slog.w(TAG, sw.toString()); 8190 ws.mWinAnimator.destroySurfaceLocked(); 8191 } 8192 } 8193 Slog.w(TAG, "Current app token list:"); 8194 dumpAppTokensLocked(); 8195 Slog.w(TAG, "Final window list:"); 8196 dumpWindowsLocked(); 8197 } 8198 } 8199 8200 private final void assignLayersLocked(WindowList windows) { 8201 int N = windows.size(); 8202 int curBaseLayer = 0; 8203 int curLayer = 0; 8204 int i; 8205 8206 if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows, 8207 new RuntimeException("here").fillInStackTrace()); 8208 8209 boolean anyLayerChanged = false; 8210 8211 for (i=0; i<N; i++) { 8212 final WindowState w = windows.get(i); 8213 final WindowStateAnimator winAnimator = w.mWinAnimator; 8214 boolean layerChanged = false; 8215 int oldLayer = w.mLayer; 8216 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 8217 || (i > 0 && w.mIsWallpaper)) { 8218 curLayer += WINDOW_LAYER_MULTIPLIER; 8219 w.mLayer = curLayer; 8220 } else { 8221 curBaseLayer = curLayer = w.mBaseLayer; 8222 w.mLayer = curLayer; 8223 } 8224 if (w.mLayer != oldLayer) { 8225 layerChanged = true; 8226 anyLayerChanged = true; 8227 } 8228 final AppWindowToken wtoken = w.mAppToken; 8229 oldLayer = winAnimator.mAnimLayer; 8230 if (w.mTargetAppToken != null) { 8231 winAnimator.mAnimLayer = 8232 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 8233 } else if (wtoken != null) { 8234 winAnimator.mAnimLayer = 8235 w.mLayer + wtoken.mAppAnimator.animLayerAdjustment; 8236 } else { 8237 winAnimator.mAnimLayer = w.mLayer; 8238 } 8239 if (w.mIsImWindow) { 8240 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 8241 } else if (w.mIsWallpaper) { 8242 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 8243 } 8244 if (winAnimator.mAnimLayer != oldLayer) { 8245 layerChanged = true; 8246 anyLayerChanged = true; 8247 } 8248 if (layerChanged && w.getStack().isDimming(winAnimator)) { 8249 // Force an animation pass just to update the mDimLayer layer. 8250 scheduleAnimationLocked(); 8251 } 8252 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 8253 + "mBase=" + w.mBaseLayer 8254 + " mLayer=" + w.mLayer 8255 + (wtoken == null ? 8256 "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment) 8257 + " =mAnimLayer=" + winAnimator.mAnimLayer); 8258 //System.out.println( 8259 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 8260 } 8261 8262 //TODO (multidisplay): Magnification is supported only for the default display. 8263 if (mAccessibilityController != null && anyLayerChanged 8264 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) { 8265 mAccessibilityController.onWindowLayersChangedLocked(); 8266 } 8267 } 8268 8269 private final void performLayoutAndPlaceSurfacesLocked() { 8270 int loopCount = 6; 8271 do { 8272 mTraversalScheduled = false; 8273 performLayoutAndPlaceSurfacesLockedLoop(); 8274 mH.removeMessages(H.DO_TRAVERSAL); 8275 loopCount--; 8276 } while (mTraversalScheduled && loopCount > 0); 8277 mInnerFields.mWallpaperActionPending = false; 8278 } 8279 8280 private boolean mInLayout = false; 8281 private final void performLayoutAndPlaceSurfacesLockedLoop() { 8282 if (mInLayout) { 8283 if (DEBUG) { 8284 throw new RuntimeException("Recursive call!"); 8285 } 8286 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 8287 + Debug.getCallers(3)); 8288 return; 8289 } 8290 8291 if (mWaitingForConfig) { 8292 // Our configuration has changed (most likely rotation), but we 8293 // don't yet have the complete configuration to report to 8294 // applications. Don't do any window layout until we have it. 8295 return; 8296 } 8297 8298 if (!mDisplayReady) { 8299 // Not yet initialized, nothing to do. 8300 return; 8301 } 8302 8303 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 8304 mInLayout = true; 8305 boolean recoveringMemory = false; 8306 8307 try { 8308 if (mForceRemoves != null) { 8309 recoveringMemory = true; 8310 // Wait a little bit for things to settle down, and off we go. 8311 for (int i=0; i<mForceRemoves.size(); i++) { 8312 WindowState ws = mForceRemoves.get(i); 8313 Slog.i(TAG, "Force removing: " + ws); 8314 removeWindowInnerLocked(ws.mSession, ws); 8315 } 8316 mForceRemoves = null; 8317 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 8318 Object tmp = new Object(); 8319 synchronized (tmp) { 8320 try { 8321 tmp.wait(250); 8322 } catch (InterruptedException e) { 8323 } 8324 } 8325 } 8326 } catch (RuntimeException e) { 8327 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 8328 } 8329 8330 try { 8331 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 8332 8333 mInLayout = false; 8334 8335 if (needsLayout()) { 8336 if (++mLayoutRepeatCount < 6) { 8337 requestTraversalLocked(); 8338 } else { 8339 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 8340 mLayoutRepeatCount = 0; 8341 } 8342 } else { 8343 mLayoutRepeatCount = 0; 8344 } 8345 8346 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 8347 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 8348 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE); 8349 } 8350 } catch (RuntimeException e) { 8351 mInLayout = false; 8352 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 8353 } 8354 8355 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 8356 } 8357 8358 private final void performLayoutLockedInner(final DisplayContent displayContent, 8359 boolean initial, boolean updateInputWindows) { 8360 if (!displayContent.layoutNeeded) { 8361 return; 8362 } 8363 displayContent.layoutNeeded = false; 8364 WindowList windows = displayContent.getWindowList(); 8365 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 8366 8367 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8368 final int dw = displayInfo.logicalWidth; 8369 final int dh = displayInfo.logicalHeight; 8370 8371 final int NFW = mFakeWindows.size(); 8372 for (int i=0; i<NFW; i++) { 8373 mFakeWindows.get(i).layout(dw, dh); 8374 } 8375 8376 final int N = windows.size(); 8377 int i; 8378 8379 if (DEBUG_LAYOUT) { 8380 Slog.v(TAG, "-------------------------------------"); 8381 Slog.v(TAG, "performLayout: needed=" 8382 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 8383 } 8384 8385 WindowStateAnimator universeBackground = null; 8386 8387 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); 8388 if (isDefaultDisplay) { 8389 // Not needed on non-default displays. 8390 mSystemDecorLayer = mPolicy.getSystemDecorLayerLw(); 8391 mScreenRect.set(0, 0, dw, dh); 8392 } 8393 8394 mPolicy.getContentRectLw(mTmpContentRect); 8395 displayContent.resize(mTmpContentRect); 8396 8397 int seq = mLayoutSeq+1; 8398 if (seq < 0) seq = 0; 8399 mLayoutSeq = seq; 8400 8401 boolean behindDream = false; 8402 8403 // First perform layout of any root windows (not attached 8404 // to another window). 8405 int topAttached = -1; 8406 for (i = N-1; i >= 0; i--) { 8407 final WindowState win = windows.get(i); 8408 8409 // Don't do layout of a window if it is not visible, or 8410 // soon won't be visible, to avoid wasting time and funky 8411 // changes while a window is animating away. 8412 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) 8413 || win.isGoneForLayoutLw(); 8414 8415 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 8416 Slog.v(TAG, "1ST PASS " + win 8417 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 8418 + " mLayoutAttached=" + win.mLayoutAttached 8419 + " screen changed=" + win.isConfigChanged()); 8420 final AppWindowToken atoken = win.mAppToken; 8421 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 8422 + win.mViewVisibility + " mRelayoutCalled=" 8423 + win.mRelayoutCalled + " hidden=" 8424 + win.mRootToken.hidden + " hiddenRequested=" 8425 + (atoken != null && atoken.hiddenRequested) 8426 + " mAttachedHidden=" + win.mAttachedHidden); 8427 else Slog.v(TAG, " VIS: mViewVisibility=" 8428 + win.mViewVisibility + " mRelayoutCalled=" 8429 + win.mRelayoutCalled + " hidden=" 8430 + win.mRootToken.hidden + " hiddenRequested=" 8431 + (atoken != null && atoken.hiddenRequested) 8432 + " mAttachedHidden=" + win.mAttachedHidden); 8433 } 8434 8435 // If this view is GONE, then skip it -- keep the current 8436 // frame, and let the caller know so they can ignore it 8437 // if they want. (We do the normal layout for INVISIBLE 8438 // windows, since that means "perform layout as normal, 8439 // just don't display"). 8440 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 8441 || ((win.isConfigChanged() || win.setInsetsChanged()) && 8442 ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || 8443 win.mAppToken != null && win.mAppToken.layoutConfigChanges)) 8444 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8445 if (!win.mLayoutAttached) { 8446 if (initial) { 8447 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8448 win.mContentChanged = false; 8449 } 8450 if (win.mAttrs.type == TYPE_DREAM) { 8451 // Don't layout windows behind a dream, so that if it 8452 // does stuff like hide the status bar we won't get a 8453 // bad transition when it goes away. 8454 behindDream = true; 8455 } 8456 win.mLayoutNeeded = false; 8457 win.prelayout(); 8458 mPolicy.layoutWindowLw(win, null); 8459 win.mLayoutSeq = seq; 8460 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8461 + win.mFrame + " mContainingFrame=" 8462 + win.mContainingFrame + " mDisplayFrame=" 8463 + win.mDisplayFrame); 8464 } else { 8465 if (topAttached < 0) topAttached = i; 8466 } 8467 } 8468 if (win.mViewVisibility == View.VISIBLE 8469 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 8470 && universeBackground == null) { 8471 universeBackground = win.mWinAnimator; 8472 } 8473 } 8474 8475 if (mAnimator.mUniverseBackground != universeBackground) { 8476 mFocusMayChange = true; 8477 mAnimator.mUniverseBackground = universeBackground; 8478 } 8479 8480 boolean attachedBehindDream = false; 8481 8482 // Now perform layout of attached windows, which usually 8483 // depend on the position of the window they are attached to. 8484 // XXX does not deal with windows that are attached to windows 8485 // that are themselves attached. 8486 for (i = topAttached; i >= 0; i--) { 8487 final WindowState win = windows.get(i); 8488 8489 if (win.mLayoutAttached) { 8490 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 8491 + " mHaveFrame=" + win.mHaveFrame 8492 + " mViewVisibility=" + win.mViewVisibility 8493 + " mRelayoutCalled=" + win.mRelayoutCalled); 8494 // If this view is GONE, then skip it -- keep the current 8495 // frame, and let the caller know so they can ignore it 8496 // if they want. (We do the normal layout for INVISIBLE 8497 // windows, since that means "perform layout as normal, 8498 // just don't display"). 8499 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) { 8500 continue; 8501 } 8502 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8503 || !win.mHaveFrame || win.mLayoutNeeded) { 8504 if (initial) { 8505 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8506 win.mContentChanged = false; 8507 } 8508 win.mLayoutNeeded = false; 8509 win.prelayout(); 8510 mPolicy.layoutWindowLw(win, win.mAttachedWindow); 8511 win.mLayoutSeq = seq; 8512 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8513 + win.mFrame + " mContainingFrame=" 8514 + win.mContainingFrame + " mDisplayFrame=" 8515 + win.mDisplayFrame); 8516 } 8517 } else if (win.mAttrs.type == TYPE_DREAM) { 8518 // Don't layout windows behind a dream, so that if it 8519 // does stuff like hide the status bar we won't get a 8520 // bad transition when it goes away. 8521 attachedBehindDream = behindDream; 8522 } 8523 } 8524 8525 // Window frames may have changed. Tell the input dispatcher about it. 8526 mInputMonitor.setUpdateInputWindowsNeededLw(); 8527 if (updateInputWindows) { 8528 mInputMonitor.updateInputWindowsLw(false /*force*/); 8529 } 8530 8531 mPolicy.finishLayoutLw(); 8532 } 8533 8534 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8535 // If the screen is currently frozen or off, then keep 8536 // it frozen/off until this window draws at its new 8537 // orientation. 8538 if (!okToDisplay()) { 8539 if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w); 8540 w.mOrientationChanging = true; 8541 w.mLastFreezeDuration = 0; 8542 mInnerFields.mOrientationChangeComplete = false; 8543 if (!mWindowsFreezingScreen) { 8544 mWindowsFreezingScreen = true; 8545 // XXX should probably keep timeout from 8546 // when we first froze the display. 8547 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8548 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 8549 WINDOW_FREEZE_TIMEOUT_DURATION); 8550 } 8551 } 8552 } 8553 8554 /** 8555 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8556 * @param windows List of windows on default display. 8557 * @return bitmap indicating if another pass through layout must be made. 8558 */ 8559 public int handleAppTransitionReadyLocked(WindowList windows) { 8560 int changes = 0; 8561 int i; 8562 int NN = mOpeningApps.size(); 8563 boolean goodToGo = true; 8564 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8565 "Checking " + NN + " opening apps (frozen=" 8566 + mDisplayFrozen + " timeout=" 8567 + mAppTransition.isTimeout() + ")..."); 8568 if (!mDisplayFrozen && !mAppTransition.isTimeout()) { 8569 // If the display isn't frozen, wait to do anything until 8570 // all of the apps are ready. Otherwise just go because 8571 // we'll unfreeze the display when everyone is ready. 8572 for (i=0; i<NN && goodToGo; i++) { 8573 AppWindowToken wtoken = mOpeningApps.valueAt(i); 8574 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8575 "Check opening app=" + wtoken + ": allDrawn=" 8576 + wtoken.allDrawn + " startingDisplayed=" 8577 + wtoken.startingDisplayed + " startingMoved=" 8578 + wtoken.startingMoved); 8579 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8580 && !wtoken.startingMoved) { 8581 goodToGo = false; 8582 } 8583 } 8584 } 8585 if (goodToGo) { 8586 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8587 int transit = mAppTransition.getAppTransition(); 8588 if (mSkipAppTransitionAnimation) { 8589 transit = AppTransition.TRANSIT_UNSET; 8590 } 8591 mAppTransition.goodToGo(); 8592 mStartingIconInTransition = false; 8593 mSkipAppTransitionAnimation = false; 8594 8595 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8596 8597 rebuildAppWindowListLocked(); 8598 8599 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8600 WindowState oldWallpaper = 8601 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8602 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8603 ? null : mWallpaperTarget; 8604 8605 mInnerFields.mWallpaperMayChange = false; 8606 8607 // The top-most window will supply the layout params, 8608 // and we will determine it below. 8609 LayoutParams animLp = null; 8610 int bestAnimLayer = -1; 8611 boolean fullscreenAnim = false; 8612 boolean voiceInteraction = false; 8613 8614 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8615 "New wallpaper target=" + mWallpaperTarget 8616 + ", oldWallpaper=" + oldWallpaper 8617 + ", lower target=" + mLowerWallpaperTarget 8618 + ", upper target=" + mUpperWallpaperTarget); 8619 8620 boolean openingAppHasWallpaper = false; 8621 boolean closingAppHasWallpaper = false; 8622 final AppWindowToken lowerWallpaperAppToken; 8623 final AppWindowToken upperWallpaperAppToken; 8624 if (mLowerWallpaperTarget == null) { 8625 lowerWallpaperAppToken = upperWallpaperAppToken = null; 8626 } else { 8627 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken; 8628 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken; 8629 } 8630 8631 // Do a first pass through the tokens for two 8632 // things: 8633 // (1) Determine if both the closing and opening 8634 // app token sets are wallpaper targets, in which 8635 // case special animations are needed 8636 // (since the wallpaper needs to stay static 8637 // behind them). 8638 // (2) Find the layout params of the top-most 8639 // application window in the tokens, which is 8640 // what will control the animation theme. 8641 final int NC = mClosingApps.size(); 8642 NN = NC + mOpeningApps.size(); 8643 for (i=0; i<NN; i++) { 8644 final AppWindowToken wtoken; 8645 if (i < NC) { 8646 wtoken = mClosingApps.valueAt(i); 8647 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8648 closingAppHasWallpaper = true; 8649 } 8650 } else { 8651 wtoken = mOpeningApps.valueAt(i - NC); 8652 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8653 openingAppHasWallpaper = true; 8654 } 8655 } 8656 8657 voiceInteraction |= wtoken.voiceInteraction; 8658 8659 if (wtoken.appFullscreen) { 8660 WindowState ws = wtoken.findMainWindow(); 8661 if (ws != null) { 8662 animLp = ws.mAttrs; 8663 bestAnimLayer = ws.mLayer; 8664 fullscreenAnim = true; 8665 } 8666 } else if (!fullscreenAnim) { 8667 WindowState ws = wtoken.findMainWindow(); 8668 if (ws != null) { 8669 if (ws.mLayer > bestAnimLayer) { 8670 animLp = ws.mAttrs; 8671 bestAnimLayer = ws.mLayer; 8672 } 8673 } 8674 } 8675 } 8676 8677 mAnimateWallpaperWithTarget = false; 8678 if (closingAppHasWallpaper && openingAppHasWallpaper) { 8679 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!"); 8680 switch (transit) { 8681 case AppTransition.TRANSIT_ACTIVITY_OPEN: 8682 case AppTransition.TRANSIT_TASK_OPEN: 8683 case AppTransition.TRANSIT_TASK_TO_FRONT: 8684 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN; 8685 break; 8686 case AppTransition.TRANSIT_ACTIVITY_CLOSE: 8687 case AppTransition.TRANSIT_TASK_CLOSE: 8688 case AppTransition.TRANSIT_TASK_TO_BACK: 8689 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; 8690 break; 8691 } 8692 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); 8693 } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty() 8694 && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 8695 // We are transitioning from an activity with 8696 // a wallpaper to one without. 8697 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; 8698 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8699 "New transit away from wallpaper: " + transit); 8700 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) { 8701 // We are transitioning from an activity without 8702 // a wallpaper to now showing the wallpaper 8703 transit = AppTransition.TRANSIT_WALLPAPER_OPEN; 8704 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8705 "New transit into wallpaper: " + transit); 8706 } else { 8707 mAnimateWallpaperWithTarget = true; 8708 } 8709 8710 // If all closing windows are obscured, then there is 8711 // no need to do an animation. This is the case, for 8712 // example, when this transition is being done behind 8713 // the lock screen. 8714 if (!mPolicy.allowAppAnimationsLw()) { 8715 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8716 "Animations disallowed by keyguard or dream."); 8717 animLp = null; 8718 } 8719 8720 AppWindowToken topOpeningApp = null; 8721 int topOpeningLayer = 0; 8722 8723 NN = mOpeningApps.size(); 8724 for (i=0; i<NN; i++) { 8725 AppWindowToken wtoken = mOpeningApps.valueAt(i); 8726 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 8727 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 8728 appAnimator.clearThumbnail(); 8729 wtoken.inPendingTransaction = false; 8730 appAnimator.animation = null; 8731 setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction); 8732 wtoken.updateReportedVisibilityLocked(); 8733 wtoken.waitingToShow = false; 8734 8735 appAnimator.mAllAppWinAnimators.clear(); 8736 final int N = wtoken.allAppWindows.size(); 8737 for (int j = 0; j < N; j++) { 8738 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 8739 } 8740 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 8741 8742 if (animLp != null) { 8743 int layer = -1; 8744 for (int j=0; j<wtoken.windows.size(); j++) { 8745 WindowState win = wtoken.windows.get(j); 8746 if (win.mWinAnimator.mAnimLayer > layer) { 8747 layer = win.mWinAnimator.mAnimLayer; 8748 } 8749 } 8750 if (topOpeningApp == null || layer > topOpeningLayer) { 8751 topOpeningApp = wtoken; 8752 topOpeningLayer = layer; 8753 } 8754 } 8755 } 8756 NN = mClosingApps.size(); 8757 for (i=0; i<NN; i++) { 8758 AppWindowToken wtoken = mClosingApps.valueAt(i); 8759 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken); 8760 wtoken.mAppAnimator.clearThumbnail(); 8761 wtoken.inPendingTransaction = false; 8762 wtoken.mAppAnimator.animation = null; 8763 setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction); 8764 wtoken.updateReportedVisibilityLocked(); 8765 wtoken.waitingToHide = false; 8766 // Force the allDrawn flag, because we want to start 8767 // this guy's animations regardless of whether it's 8768 // gotten drawn. 8769 wtoken.allDrawn = true; 8770 wtoken.deferClearAllDrawn = false; 8771 } 8772 8773 boolean useAlternateThumbnailAnimation = true; 8774 AppWindowAnimator appAnimator = 8775 topOpeningApp == null ? null : topOpeningApp.mAppAnimator; 8776 Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail(); 8777 if (!useAlternateThumbnailAnimation && nextAppTransitionThumbnail != null 8778 && appAnimator != null && appAnimator.animation != null) { 8779 // This thumbnail animation is very special, we need to have 8780 // an extra surface with the thumbnail included with the animation. 8781 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(), 8782 nextAppTransitionThumbnail.getHeight()); 8783 try { 8784 // TODO(multi-display): support other displays 8785 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8786 final Display display = displayContent.getDisplay(); 8787 SurfaceControl surfaceControl = new SurfaceControl(mFxSession, 8788 "thumbnail anim", 8789 dirty.width(), dirty.height(), 8790 PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 8791 surfaceControl.setLayerStack(display.getLayerStack()); 8792 appAnimator.thumbnail = surfaceControl; 8793 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE"); 8794 Surface drawSurface = new Surface(); 8795 drawSurface.copyFrom(surfaceControl); 8796 Canvas c = drawSurface.lockCanvas(dirty); 8797 c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null); 8798 drawSurface.unlockCanvasAndPost(c); 8799 drawSurface.release(); 8800 appAnimator.thumbnailLayer = topOpeningLayer; 8801 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 8802 Animation anim = mAppTransition.createThumbnailScaleAnimationLocked( 8803 displayInfo.appWidth, displayInfo.appHeight, transit); 8804 appAnimator.thumbnailAnimation = anim; 8805 anim.restrictDuration(MAX_ANIMATION_DURATION); 8806 anim.scaleCurrentDuration(getTransitionAnimationScaleLocked()); 8807 Point p = new Point(); 8808 mAppTransition.getStartingPoint(p); 8809 appAnimator.thumbnailX = p.x; 8810 appAnimator.thumbnailY = p.y; 8811 } catch (OutOfResourcesException e) { 8812 Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width() 8813 + " h=" + dirty.height(), e); 8814 appAnimator.clearThumbnail(); 8815 } 8816 } 8817 8818 mAppTransition.postAnimationCallback(); 8819 mAppTransition.clear(); 8820 8821 mOpeningApps.clear(); 8822 mClosingApps.clear(); 8823 8824 // This has changed the visibility of windows, so perform 8825 // a new layout to get them all up-to-date. 8826 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT 8827 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 8828 getDefaultDisplayContentLocked().layoutNeeded = true; 8829 8830 // TODO(multidisplay): IMEs are only supported on the default display. 8831 if (windows == getDefaultWindowListLocked() 8832 && !moveInputMethodWindowsIfNeededLocked(true)) { 8833 assignLayersLocked(windows); 8834 } 8835 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/); 8836 mFocusMayChange = false; 8837 } 8838 8839 return changes; 8840 } 8841 8842 /** 8843 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8844 * @return bitmap indicating if another pass through layout must be made. 8845 */ 8846 private int handleAnimatingStoppedAndTransitionLocked() { 8847 int changes = 0; 8848 8849 mAppTransition.setIdle(); 8850 // Restore window app tokens to the ActivityManager views 8851 ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks(); 8852 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 8853 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8854 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 8855 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8856 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 8857 tokens.get(tokenNdx).sendingToBottom = false; 8858 } 8859 } 8860 } 8861 rebuildAppWindowListLocked(); 8862 8863 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8864 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 8865 "Wallpaper layer changed: assigning layers + relayout"); 8866 moveInputMethodWindowsIfNeededLocked(true); 8867 mInnerFields.mWallpaperMayChange = true; 8868 // Since the window list has been rebuilt, focus might 8869 // have to be recomputed since the actual order of windows 8870 // might have changed again. 8871 mFocusMayChange = true; 8872 8873 return changes; 8874 } 8875 8876 private void updateResizingWindows(final WindowState w) { 8877 final WindowStateAnimator winAnimator = w.mWinAnimator; 8878 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { 8879 w.setInsetsChanged(); 8880 boolean configChanged = w.isConfigChanged(); 8881 if (DEBUG_CONFIGURATION && configChanged) { 8882 Slog.v(TAG, "Win " + w + " config changed: " 8883 + mCurConfiguration); 8884 } 8885 if (localLOGV) Slog.v(TAG, "Resizing " + w 8886 + ": configChanged=" + configChanged 8887 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8888 w.mLastFrame.set(w.mFrame); 8889 if (w.mContentInsetsChanged 8890 || w.mVisibleInsetsChanged 8891 || winAnimator.mSurfaceResized 8892 || configChanged) { 8893 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8894 Slog.v(TAG, "Resize reasons for w=" + w + ": " 8895 + " contentInsetsChanged=" + w.mContentInsetsChanged 8896 + " " + w.mContentInsets.toShortString() 8897 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8898 + " " + w.mVisibleInsets.toShortString() 8899 + " stableInsetsChanged=" + w.mStableInsetsChanged 8900 + " " + w.mStableInsets.toShortString() 8901 + " surfaceResized=" + winAnimator.mSurfaceResized 8902 + " configChanged=" + configChanged); 8903 } 8904 8905 w.mLastOverscanInsets.set(w.mOverscanInsets); 8906 w.mLastContentInsets.set(w.mContentInsets); 8907 w.mLastVisibleInsets.set(w.mVisibleInsets); 8908 w.mLastStableInsets.set(w.mStableInsets); 8909 makeWindowFreezingScreenIfNeededLocked(w); 8910 // If the orientation is changing, then we need to 8911 // hold off on unfreezing the display until this 8912 // window has been redrawn; to do that, we need 8913 // to go through the process of getting informed 8914 // by the application when it has finished drawing. 8915 if (w.mOrientationChanging) { 8916 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 8917 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 8918 + w + ", surface " + winAnimator.mSurfaceControl); 8919 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 8920 if (w.mAppToken != null) { 8921 w.mAppToken.allDrawn = false; 8922 w.mAppToken.deferClearAllDrawn = false; 8923 } 8924 } 8925 if (!mResizingWindows.contains(w)) { 8926 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8927 "Resizing window " + w + " to " + winAnimator.mSurfaceW 8928 + "x" + winAnimator.mSurfaceH); 8929 mResizingWindows.add(w); 8930 } 8931 } else if (w.mOrientationChanging) { 8932 if (w.isDrawnLw()) { 8933 if (DEBUG_ORIENTATION) Slog.v(TAG, 8934 "Orientation not waiting for draw in " 8935 + w + ", surface " + winAnimator.mSurfaceControl); 8936 w.mOrientationChanging = false; 8937 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 8938 - mDisplayFreezeTime); 8939 } 8940 } 8941 } 8942 } 8943 8944 /** 8945 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8946 * 8947 * @param w WindowState this method is applied to. 8948 * @param currentTime The time which animations use for calculating transitions. 8949 * @param innerDw Width of app window. 8950 * @param innerDh Height of app window. 8951 */ 8952 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 8953 final int innerDw, final int innerDh) { 8954 final WindowManager.LayoutParams attrs = w.mAttrs; 8955 final int attrFlags = attrs.flags; 8956 final boolean canBeSeen = w.isDisplayedLw(); 8957 final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8958 8959 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8960 // This window completely covers everything behind it, 8961 // so we want to leave all of them as undimmed (for 8962 // performance reasons). 8963 mInnerFields.mObscured = true; 8964 } 8965 8966 if (w.mHasSurface) { 8967 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8968 mInnerFields.mHoldScreen = w.mSession; 8969 } 8970 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 8971 && mInnerFields.mScreenBrightness < 0) { 8972 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 8973 } 8974 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 8975 && mInnerFields.mButtonBrightness < 0) { 8976 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 8977 } 8978 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0 8979 && mInnerFields.mUserActivityTimeout < 0) { 8980 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout; 8981 } 8982 8983 final int type = attrs.type; 8984 if (canBeSeen 8985 && (type == TYPE_SYSTEM_DIALOG 8986 || type == TYPE_RECENTS_OVERLAY 8987 || type == TYPE_SYSTEM_ERROR 8988 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) { 8989 mInnerFields.mSyswin = true; 8990 } 8991 8992 if (canBeSeen) { 8993 // This function assumes that the contents of the default display are 8994 // processed first before secondary displays. 8995 final DisplayContent displayContent = w.getDisplayContent(); 8996 if (displayContent != null && displayContent.isDefaultDisplay) { 8997 // While a dream or keyguard is showing, obscure ordinary application 8998 // content on secondary displays (by forcibly enabling mirroring unless 8999 // there is other content we want to show) but still allow opaque 9000 // keyguard dialogs to be shown. 9001 if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 9002 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true; 9003 } 9004 mInnerFields.mDisplayHasContent = true; 9005 } else if (displayContent != null && 9006 (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays 9007 || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) { 9008 // Allow full screen keyguard presentation dialogs to be seen. 9009 mInnerFields.mDisplayHasContent = true; 9010 } 9011 } 9012 } 9013 } 9014 9015 private void handleFlagDimBehind(WindowState w) { 9016 final WindowManager.LayoutParams attrs = w.mAttrs; 9017 if ((attrs.flags & FLAG_DIM_BEHIND) != 0 9018 && w.isDisplayedLw() 9019 && !w.mExiting) { 9020 final WindowStateAnimator winAnimator = w.mWinAnimator; 9021 final TaskStack stack = w.getStack(); 9022 stack.setDimmingTag(); 9023 if (!stack.isDimming(winAnimator)) { 9024 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming."); 9025 stack.startDimmingIfNeeded(winAnimator); 9026 } 9027 } 9028 } 9029 9030 private void updateAllDrawnLocked(DisplayContent displayContent) { 9031 // See if any windows have been drawn, so they (and others 9032 // associated with them) can now be shown. 9033 ArrayList<TaskStack> stacks = displayContent.getStacks(); 9034 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 9035 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9036 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9037 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9038 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9039 final AppWindowToken wtoken = tokens.get(tokenNdx); 9040 if (!wtoken.allDrawn) { 9041 int numInteresting = wtoken.numInterestingWindows; 9042 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 9043 if (DEBUG_VISIBILITY) Slog.v(TAG, 9044 "allDrawn: " + wtoken 9045 + " interesting=" + numInteresting 9046 + " drawn=" + wtoken.numDrawnWindows); 9047 wtoken.allDrawn = true; 9048 mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget(); 9049 } 9050 } 9051 } 9052 } 9053 } 9054 } 9055 9056 // "Something has changed! Let's make it correct now." 9057 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 9058 if (DEBUG_WINDOW_TRACE) { 9059 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 9060 + Debug.getCallers(3)); 9061 } 9062 9063 final long currentTime = SystemClock.uptimeMillis(); 9064 9065 int i; 9066 9067 if (mFocusMayChange) { 9068 mFocusMayChange = false; 9069 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 9070 false /*updateInputWindows*/); 9071 } 9072 9073 // Initialize state of exiting tokens. 9074 final int numDisplays = mDisplayContents.size(); 9075 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9076 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9077 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) { 9078 displayContent.mExitingTokens.get(i).hasVisible = false; 9079 } 9080 } 9081 9082 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9083 // Initialize state of exiting applications. 9084 final AppTokenList exitingAppTokens = 9085 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9086 for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9087 exitingAppTokens.get(tokenNdx).hasVisible = false; 9088 } 9089 } 9090 9091 mInnerFields.mHoldScreen = null; 9092 mInnerFields.mScreenBrightness = -1; 9093 mInnerFields.mButtonBrightness = -1; 9094 mInnerFields.mUserActivityTimeout = -1; 9095 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false; 9096 9097 mTransactionSequence++; 9098 9099 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked(); 9100 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 9101 final int defaultDw = defaultInfo.logicalWidth; 9102 final int defaultDh = defaultInfo.logicalHeight; 9103 9104 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9105 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 9106 SurfaceControl.openTransaction(); 9107 try { 9108 9109 if (mWatermark != null) { 9110 mWatermark.positionSurface(defaultDw, defaultDh); 9111 } 9112 if (mStrictModeFlash != null) { 9113 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 9114 } 9115 9116 boolean focusDisplayed = false; 9117 9118 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9119 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9120 boolean updateAllDrawn = false; 9121 WindowList windows = displayContent.getWindowList(); 9122 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9123 final int displayId = displayContent.getDisplayId(); 9124 final int dw = displayInfo.logicalWidth; 9125 final int dh = displayInfo.logicalHeight; 9126 final int innerDw = displayInfo.appWidth; 9127 final int innerDh = displayInfo.appHeight; 9128 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 9129 9130 // Reset for each display. 9131 mInnerFields.mDisplayHasContent = false; 9132 9133 int repeats = 0; 9134 do { 9135 repeats++; 9136 if (repeats > 6) { 9137 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 9138 displayContent.layoutNeeded = false; 9139 break; 9140 } 9141 9142 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 9143 displayContent.pendingLayoutChanges); 9144 9145 if ((displayContent.pendingLayoutChanges & 9146 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 && 9147 (adjustWallpaperWindowsLocked() & 9148 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 9149 assignLayersLocked(windows); 9150 displayContent.layoutNeeded = true; 9151 } 9152 9153 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 9154 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 9155 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 9156 if (updateOrientationFromAppTokensLocked(true)) { 9157 displayContent.layoutNeeded = true; 9158 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9159 } 9160 } 9161 9162 if ((displayContent.pendingLayoutChanges 9163 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9164 displayContent.layoutNeeded = true; 9165 } 9166 9167 // FIRST LOOP: Perform a layout, if needed. 9168 if (repeats < 4) { 9169 performLayoutLockedInner(displayContent, repeats == 1, 9170 false /*updateInputWindows*/); 9171 } else { 9172 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 9173 } 9174 9175 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 9176 // it is animating. 9177 displayContent.pendingLayoutChanges = 0; 9178 9179 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 9180 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 9181 9182 if (isDefaultDisplay) { 9183 mPolicy.beginPostLayoutPolicyLw(dw, dh); 9184 for (i = windows.size() - 1; i >= 0; i--) { 9185 WindowState w = windows.get(i); 9186 if (w.mHasSurface) { 9187 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); 9188 } 9189 } 9190 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 9191 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 9192 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges); 9193 } 9194 } while (displayContent.pendingLayoutChanges != 0); 9195 9196 mInnerFields.mObscured = false; 9197 mInnerFields.mSyswin = false; 9198 displayContent.resetDimming(); 9199 9200 // Only used if default window 9201 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 9202 9203 final int N = windows.size(); 9204 for (i=N-1; i>=0; i--) { 9205 WindowState w = windows.get(i); 9206 final TaskStack stack = w.getStack(); 9207 if (stack == null) { 9208 continue; 9209 } 9210 9211 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 9212 9213 // Update effect. 9214 w.mObscured = mInnerFields.mObscured; 9215 if (!mInnerFields.mObscured) { 9216 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 9217 } 9218 9219 if (!stack.testDimmingTag()) { 9220 handleFlagDimBehind(w); 9221 } 9222 9223 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 9224 && w.isVisibleLw()) { 9225 // This is the wallpaper target and its obscured state 9226 // changed... make sure the current wallaper's visibility 9227 // has been updated accordingly. 9228 updateWallpaperVisibilityLocked(); 9229 } 9230 9231 final WindowStateAnimator winAnimator = w.mWinAnimator; 9232 9233 // If the window has moved due to its containing 9234 // content frame changing, then we'd like to animate 9235 // it. 9236 if (w.mHasSurface && w.shouldAnimateMove()) { 9237 // Frame has moved, containing content frame 9238 // has also moved, and we're not currently animating... 9239 // let's do something. 9240 Animation a = AnimationUtils.loadAnimation(mContext, 9241 com.android.internal.R.anim.window_move_from_decor); 9242 winAnimator.setAnimation(a); 9243 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 9244 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 9245 9246 //TODO (multidisplay): Accessibility supported only for the default display. 9247 if (mAccessibilityController != null 9248 && displayId == Display.DEFAULT_DISPLAY) { 9249 mAccessibilityController.onSomeWindowResizedOrMovedLocked(); 9250 } 9251 9252 try { 9253 w.mClient.moved(w.mFrame.left, w.mFrame.top); 9254 } catch (RemoteException e) { 9255 } 9256 } 9257 9258 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 9259 w.mContentChanged = false; 9260 9261 // Moved from updateWindowsAndWallpaperLocked(). 9262 if (w.mHasSurface) { 9263 // Take care of the window being ready to display. 9264 final boolean committed = 9265 winAnimator.commitFinishDrawingLocked(currentTime); 9266 if (isDefaultDisplay && committed) { 9267 if (w.mAttrs.type == TYPE_DREAM) { 9268 // HACK: When a dream is shown, it may at that 9269 // point hide the lock screen. So we need to 9270 // redo the layout to let the phone window manager 9271 // make this happen. 9272 displayContent.pendingLayoutChanges |= 9273 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9274 if (DEBUG_LAYOUT_REPEATS) { 9275 debugLayoutRepeats( 9276 "dream and commitFinishDrawingLocked true", 9277 displayContent.pendingLayoutChanges); 9278 } 9279 } 9280 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 9281 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 9282 "First draw done in potential wallpaper target " + w); 9283 mInnerFields.mWallpaperMayChange = true; 9284 displayContent.pendingLayoutChanges |= 9285 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9286 if (DEBUG_LAYOUT_REPEATS) { 9287 debugLayoutRepeats( 9288 "wallpaper and commitFinishDrawingLocked true", 9289 displayContent.pendingLayoutChanges); 9290 } 9291 } 9292 } 9293 9294 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 9295 9296 final AppWindowToken atoken = w.mAppToken; 9297 if (DEBUG_STARTING_WINDOW && atoken != null 9298 && w == atoken.startingWindow) { 9299 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 9300 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 9301 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 9302 } 9303 if (atoken != null 9304 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 9305 if (atoken.lastTransactionSequence != mTransactionSequence) { 9306 atoken.lastTransactionSequence = mTransactionSequence; 9307 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 9308 atoken.startingDisplayed = false; 9309 } 9310 if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 9311 && !w.mExiting && !w.mDestroying) { 9312 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 9313 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 9314 + ", isAnimating=" + winAnimator.isAnimating()); 9315 if (!w.isDrawnLw()) { 9316 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl 9317 + " pv=" + w.mPolicyVisibility 9318 + " mDrawState=" + winAnimator.mDrawState 9319 + " ah=" + w.mAttachedHidden 9320 + " th=" + atoken.hiddenRequested 9321 + " a=" + winAnimator.mAnimating); 9322 } 9323 } 9324 if (w != atoken.startingWindow) { 9325 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 9326 atoken.numInterestingWindows++; 9327 if (w.isDrawnLw()) { 9328 atoken.numDrawnWindows++; 9329 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 9330 "tokenMayBeDrawn: " + atoken 9331 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 9332 + " mAppFreezing=" + w.mAppFreezing); 9333 updateAllDrawn = true; 9334 } 9335 } 9336 } else if (w.isDrawnLw()) { 9337 atoken.startingDisplayed = true; 9338 } 9339 } 9340 } 9341 } 9342 9343 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 9344 && w.isDisplayedLw()) { 9345 focusDisplayed = true; 9346 } 9347 9348 updateResizingWindows(w); 9349 } 9350 9351 mDisplayManagerInternal.setDisplayHasContent(displayId, 9352 mInnerFields.mDisplayHasContent, 9353 true /* inTraversal, must call performTraversalInTrans... below */); 9354 9355 getDisplayContentLocked(displayId).stopDimmingIfNeeded(); 9356 9357 if (updateAllDrawn) { 9358 updateAllDrawnLocked(displayContent); 9359 } 9360 } 9361 9362 if (focusDisplayed) { 9363 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 9364 } 9365 9366 // Give the display manager a chance to adjust properties 9367 // like display rotation if it needs to. 9368 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 9369 9370 } catch (RuntimeException e) { 9371 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 9372 } finally { 9373 SurfaceControl.closeTransaction(); 9374 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9375 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 9376 } 9377 9378 final WindowList defaultWindows = defaultDisplay.getWindowList(); 9379 9380 // If we are ready to perform an app transition, check through 9381 // all of the app tokens to be shown and see if they are ready 9382 // to go. 9383 if (mAppTransition.isReady()) { 9384 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 9385 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 9386 defaultDisplay.pendingLayoutChanges); 9387 } 9388 9389 if (!mAnimator.mAnimating && mAppTransition.isRunning()) { 9390 // We have finished the animation of an app transition. To do 9391 // this, we have delayed a lot of operations like showing and 9392 // hiding apps, moving apps in Z-order, etc. The app token list 9393 // reflects the correct Z-order, but the window list may now 9394 // be out of sync with it. So here we will just rebuild the 9395 // entire app window list. Fun! 9396 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 9397 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 9398 defaultDisplay.pendingLayoutChanges); 9399 } 9400 9401 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 9402 && !mAppTransition.isReady()) { 9403 // At this point, there was a window with a wallpaper that 9404 // was force hiding other windows behind it, but now it 9405 // is going away. This may be simple -- just animate 9406 // away the wallpaper and its window -- or it may be 9407 // hard -- the wallpaper now needs to be shown behind 9408 // something that was hidden. 9409 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9410 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 9411 defaultDisplay.pendingLayoutChanges); 9412 } 9413 mInnerFields.mWallpaperForceHidingChanged = false; 9414 9415 if (mInnerFields.mWallpaperMayChange) { 9416 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting"); 9417 defaultDisplay.pendingLayoutChanges |= 9418 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9419 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange", 9420 defaultDisplay.pendingLayoutChanges); 9421 } 9422 9423 if (mFocusMayChange) { 9424 mFocusMayChange = false; 9425 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 9426 false /*updateInputWindows*/)) { 9427 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 9428 } 9429 } 9430 9431 if (needsLayout()) { 9432 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9433 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 9434 defaultDisplay.pendingLayoutChanges); 9435 } 9436 9437 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 9438 WindowState win = mResizingWindows.get(i); 9439 if (win.mAppFreezing) { 9440 // Don't remove this window until rotation has completed. 9441 continue; 9442 } 9443 win.reportResized(); 9444 mResizingWindows.remove(i); 9445 } 9446 9447 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 9448 "With display frozen, orientationChangeComplete=" 9449 + mInnerFields.mOrientationChangeComplete); 9450 if (mInnerFields.mOrientationChangeComplete) { 9451 if (mWindowsFreezingScreen) { 9452 mWindowsFreezingScreen = false; 9453 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource; 9454 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9455 } 9456 stopFreezingDisplayLocked(); 9457 } 9458 9459 // Destroy the surface of any windows that are no longer visible. 9460 boolean wallpaperDestroyed = false; 9461 i = mDestroySurface.size(); 9462 if (i > 0) { 9463 do { 9464 i--; 9465 WindowState win = mDestroySurface.get(i); 9466 win.mDestroying = false; 9467 if (mInputMethodWindow == win) { 9468 mInputMethodWindow = null; 9469 } 9470 if (win == mWallpaperTarget) { 9471 wallpaperDestroyed = true; 9472 } 9473 win.mWinAnimator.destroySurfaceLocked(); 9474 } while (i > 0); 9475 mDestroySurface.clear(); 9476 } 9477 9478 // Time to remove any exiting tokens? 9479 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9480 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9481 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens; 9482 for (i = exitingTokens.size() - 1; i >= 0; i--) { 9483 WindowToken token = exitingTokens.get(i); 9484 if (!token.hasVisible) { 9485 exitingTokens.remove(i); 9486 if (token.windowType == TYPE_WALLPAPER) { 9487 mWallpaperTokens.remove(token); 9488 } 9489 } 9490 } 9491 } 9492 9493 // Time to remove any exiting applications? 9494 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9495 // Initialize state of exiting applications. 9496 final AppTokenList exitingAppTokens = 9497 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9498 for (i = exitingAppTokens.size() - 1; i >= 0; i--) { 9499 AppWindowToken token = exitingAppTokens.get(i); 9500 if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) { 9501 // Make sure there is no animation running on this token, 9502 // so any windows associated with it will be removed as 9503 // soon as their animations are complete 9504 token.mAppAnimator.clearAnimation(); 9505 token.mAppAnimator.animating = false; 9506 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 9507 "performLayout: App token exiting now removed" + token); 9508 removeAppFromTaskLocked(token); 9509 exitingAppTokens.remove(i); 9510 } 9511 } 9512 } 9513 9514 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 9515 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 9516 try { 9517 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 9518 } catch (RemoteException e) { 9519 } 9520 } 9521 mRelayoutWhileAnimating.clear(); 9522 } 9523 9524 if (wallpaperDestroyed) { 9525 defaultDisplay.pendingLayoutChanges |= 9526 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9527 defaultDisplay.layoutNeeded = true; 9528 } 9529 9530 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9531 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9532 if (displayContent.pendingLayoutChanges != 0) { 9533 displayContent.layoutNeeded = true; 9534 } 9535 } 9536 9537 // Finally update all input windows now that the window changes have stabilized. 9538 mInputMonitor.updateInputWindowsLw(true /*force*/); 9539 9540 setHoldScreenLocked(mInnerFields.mHoldScreen); 9541 if (!mDisplayFrozen) { 9542 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 9543 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1); 9544 } else { 9545 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager( 9546 toBrightnessOverride(mInnerFields.mScreenBrightness)); 9547 } 9548 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 9549 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1); 9550 } else { 9551 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager( 9552 toBrightnessOverride(mInnerFields.mButtonBrightness)); 9553 } 9554 mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager( 9555 mInnerFields.mUserActivityTimeout); 9556 } 9557 9558 if (mTurnOnScreen) { 9559 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 9560 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 9561 mTurnOnScreen = false; 9562 } 9563 9564 if (mInnerFields.mUpdateRotation) { 9565 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9566 if (updateRotationUncheckedLocked(false)) { 9567 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9568 } else { 9569 mInnerFields.mUpdateRotation = false; 9570 } 9571 } 9572 9573 if (mWaitingForDrawnCallback != null || 9574 (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded && 9575 !mInnerFields.mUpdateRotation)) { 9576 checkDrawnWindowsLocked(); 9577 } 9578 9579 final int N = mPendingRemove.size(); 9580 if (N > 0) { 9581 if (mPendingRemoveTmp.length < N) { 9582 mPendingRemoveTmp = new WindowState[N+10]; 9583 } 9584 mPendingRemove.toArray(mPendingRemoveTmp); 9585 mPendingRemove.clear(); 9586 DisplayContentList displayList = new DisplayContentList(); 9587 for (i = 0; i < N; i++) { 9588 WindowState w = mPendingRemoveTmp[i]; 9589 removeWindowInnerLocked(w.mSession, w); 9590 final DisplayContent displayContent = w.getDisplayContent(); 9591 if (displayContent != null && !displayList.contains(displayContent)) { 9592 displayList.add(displayContent); 9593 } 9594 } 9595 9596 for (DisplayContent displayContent : displayList) { 9597 assignLayersLocked(displayContent.getWindowList()); 9598 displayContent.layoutNeeded = true; 9599 } 9600 } 9601 9602 // Remove all deferred displays stacks, tasks, and activities. 9603 for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) { 9604 mDisplayContents.valueAt(displayNdx).checkForDeferredActions(); 9605 } 9606 9607 setFocusedStackFrame(); 9608 9609 // Check to see if we are now in a state where the screen should 9610 // be enabled, because the window obscured flags have changed. 9611 enableScreenIfNeededLocked(); 9612 9613 scheduleAnimationLocked(); 9614 9615 if (DEBUG_WINDOW_TRACE) { 9616 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" 9617 + mAnimator.mAnimating); 9618 } 9619 } 9620 9621 private int toBrightnessOverride(float value) { 9622 return (int)(value * PowerManager.BRIGHTNESS_ON); 9623 } 9624 9625 void checkDrawnWindowsLocked() { 9626 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { 9627 return; 9628 } 9629 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { 9630 WindowState win = mWaitingForDrawn.get(j); 9631 if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win + 9632 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() + 9633 " mHasSurface=" + win.mHasSurface + 9634 " drawState=" + win.mWinAnimator.mDrawState); 9635 if (win.mRemoved || !win.mHasSurface) { 9636 // Window has been removed; no draw will now happen, so stop waiting. 9637 if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win); 9638 mWaitingForDrawn.remove(win); 9639 } else if (win.hasDrawnLw()) { 9640 // Window is now drawn (and shown). 9641 if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win); 9642 mWaitingForDrawn.remove(win); 9643 } 9644 } 9645 if (mWaitingForDrawn.isEmpty()) { 9646 if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!"); 9647 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 9648 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); 9649 } 9650 } 9651 9652 void setHoldScreenLocked(final Session newHoldScreen) { 9653 final boolean hold = newHoldScreen != null; 9654 9655 if (hold && mHoldingScreenOn != newHoldScreen) { 9656 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 9657 } 9658 mHoldingScreenOn = newHoldScreen; 9659 9660 final boolean state = mHoldingScreenWakeLock.isHeld(); 9661 if (hold != state) { 9662 if (hold) { 9663 mHoldingScreenWakeLock.acquire(); 9664 mPolicy.keepScreenOnStartedLw(); 9665 } else { 9666 mPolicy.keepScreenOnStoppedLw(); 9667 mHoldingScreenWakeLock.release(); 9668 } 9669 } 9670 } 9671 9672 void requestTraversal() { 9673 synchronized (mWindowMap) { 9674 requestTraversalLocked(); 9675 } 9676 } 9677 9678 void requestTraversalLocked() { 9679 if (!mTraversalScheduled) { 9680 mTraversalScheduled = true; 9681 mH.sendEmptyMessage(H.DO_TRAVERSAL); 9682 } 9683 } 9684 9685 /** Note that Locked in this case is on mLayoutToAnim */ 9686 void scheduleAnimationLocked() { 9687 if (!mAnimationScheduled) { 9688 mAnimationScheduled = true; 9689 mChoreographer.postCallback( 9690 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 9691 } 9692 } 9693 9694 private boolean needsLayout() { 9695 final int numDisplays = mDisplayContents.size(); 9696 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9697 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9698 if (displayContent.layoutNeeded) { 9699 return true; 9700 } 9701 } 9702 return false; 9703 } 9704 9705 boolean copyAnimToLayoutParamsLocked() { 9706 boolean doRequest = false; 9707 9708 final int bulkUpdateParams = mAnimator.mBulkUpdateParams; 9709 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 9710 mInnerFields.mUpdateRotation = true; 9711 doRequest = true; 9712 } 9713 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 9714 mInnerFields.mWallpaperMayChange = true; 9715 doRequest = true; 9716 } 9717 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 9718 mInnerFields.mWallpaperForceHidingChanged = true; 9719 doRequest = true; 9720 } 9721 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 9722 mInnerFields.mOrientationChangeComplete = false; 9723 } else { 9724 mInnerFields.mOrientationChangeComplete = true; 9725 mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource; 9726 if (mWindowsFreezingScreen) { 9727 doRequest = true; 9728 } 9729 } 9730 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 9731 mTurnOnScreen = true; 9732 } 9733 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) { 9734 mInnerFields.mWallpaperActionPending = true; 9735 } 9736 9737 return doRequest; 9738 } 9739 9740 /** If a window that has an animation specifying a colored background and the current wallpaper 9741 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 9742 * suddenly disappear. */ 9743 int adjustAnimationBackground(WindowStateAnimator winAnimator) { 9744 WindowList windows = winAnimator.mWin.getWindowList(); 9745 for (int i = windows.size() - 1; i >= 0; --i) { 9746 WindowState testWin = windows.get(i); 9747 if (testWin.mIsWallpaper && testWin.isVisibleNow()) { 9748 return testWin.mWinAnimator.mAnimLayer; 9749 } 9750 } 9751 return winAnimator.mAnimLayer; 9752 } 9753 9754 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9755 boolean secure) { 9756 final SurfaceControl surface = winAnimator.mSurfaceControl; 9757 boolean leakedSurface = false; 9758 boolean killedApps = false; 9759 9760 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9761 winAnimator.mSession.mPid, operation); 9762 9763 if (mForceRemoves == null) { 9764 mForceRemoves = new ArrayList<WindowState>(); 9765 } 9766 9767 long callingIdentity = Binder.clearCallingIdentity(); 9768 try { 9769 // There was some problem... first, do a sanity check of the 9770 // window list to make sure we haven't left any dangling surfaces 9771 // around. 9772 9773 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 9774 final int numDisplays = mDisplayContents.size(); 9775 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9776 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9777 final int numWindows = windows.size(); 9778 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9779 final WindowState ws = windows.get(winNdx); 9780 WindowStateAnimator wsa = ws.mWinAnimator; 9781 if (wsa.mSurfaceControl != null) { 9782 if (!mSessions.contains(wsa.mSession)) { 9783 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 9784 + ws + " surface=" + wsa.mSurfaceControl 9785 + " token=" + ws.mToken 9786 + " pid=" + ws.mSession.mPid 9787 + " uid=" + ws.mSession.mUid); 9788 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9789 wsa.mSurfaceControl.destroy(); 9790 wsa.mSurfaceShown = false; 9791 wsa.mSurfaceControl = null; 9792 ws.mHasSurface = false; 9793 mForceRemoves.add(ws); 9794 leakedSurface = true; 9795 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9796 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 9797 + ws + " surface=" + wsa.mSurfaceControl 9798 + " token=" + ws.mAppToken); 9799 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9800 wsa.mSurfaceControl.destroy(); 9801 wsa.mSurfaceShown = false; 9802 wsa.mSurfaceControl = null; 9803 ws.mHasSurface = false; 9804 leakedSurface = true; 9805 } 9806 } 9807 } 9808 } 9809 9810 if (!leakedSurface) { 9811 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 9812 SparseIntArray pidCandidates = new SparseIntArray(); 9813 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9814 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9815 final int numWindows = windows.size(); 9816 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9817 final WindowState ws = windows.get(winNdx); 9818 if (mForceRemoves.contains(ws)) { 9819 continue; 9820 } 9821 WindowStateAnimator wsa = ws.mWinAnimator; 9822 if (wsa.mSurfaceControl != null) { 9823 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9824 } 9825 } 9826 if (pidCandidates.size() > 0) { 9827 int[] pids = new int[pidCandidates.size()]; 9828 for (int i=0; i<pids.length; i++) { 9829 pids[i] = pidCandidates.keyAt(i); 9830 } 9831 try { 9832 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9833 killedApps = true; 9834 } 9835 } catch (RemoteException e) { 9836 } 9837 } 9838 } 9839 } 9840 9841 if (leakedSurface || killedApps) { 9842 // We managed to reclaim some memory, so get rid of the trouble 9843 // surface and ask the app to request another one. 9844 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 9845 if (surface != null) { 9846 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9847 "RECOVER DESTROY", null); 9848 surface.destroy(); 9849 winAnimator.mSurfaceShown = false; 9850 winAnimator.mSurfaceControl = null; 9851 winAnimator.mWin.mHasSurface = false; 9852 scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken); 9853 } 9854 9855 try { 9856 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9857 } catch (RemoteException e) { 9858 } 9859 } 9860 } finally { 9861 Binder.restoreCallingIdentity(callingIdentity); 9862 } 9863 9864 return leakedSurface || killedApps; 9865 } 9866 9867 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9868 WindowState newFocus = computeFocusedWindowLocked(); 9869 if (mCurrentFocus != newFocus) { 9870 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9871 // This check makes sure that we don't already have the focus 9872 // change message pending. 9873 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9874 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9875 // TODO(multidisplay): Focused windows on default display only. 9876 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9877 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked( 9878 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 9879 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES); 9880 if (imWindowChanged) { 9881 displayContent.layoutNeeded = true; 9882 newFocus = computeFocusedWindowLocked(); 9883 } 9884 9885 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " + 9886 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 9887 final WindowState oldFocus = mCurrentFocus; 9888 mCurrentFocus = newFocus; 9889 mLosingFocus.remove(newFocus); 9890 9891 // TODO(multidisplay): Accessibilty supported only of default desiplay. 9892 if (mAccessibilityController != null 9893 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 9894 mAccessibilityController.onWindowFocusChangedLocked(); 9895 } 9896 9897 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9898 9899 if (imWindowChanged && oldFocus != mInputMethodWindow) { 9900 // Focus of the input method window changed. Perform layout if needed. 9901 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9902 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9903 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9904 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9905 // Client will do the layout, but we need to assign layers 9906 // for handleNewWindowLocked() below. 9907 assignLayersLocked(displayContent.getWindowList()); 9908 } 9909 } 9910 9911 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9912 // The change in focus caused us to need to do a layout. Okay. 9913 displayContent.layoutNeeded = true; 9914 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9915 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9916 } 9917 } 9918 9919 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9920 // If we defer assigning layers, then the caller is responsible for 9921 // doing this part. 9922 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 9923 } 9924 9925 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9926 return true; 9927 } 9928 return false; 9929 } 9930 9931 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 9932 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9933 } 9934 9935 private WindowState computeFocusedWindowLocked() { 9936 if (mAnimator.mUniverseBackground != null 9937 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 9938 return mAnimator.mUniverseBackground.mWin; 9939 } 9940 9941 final int displayCount = mDisplayContents.size(); 9942 for (int i = 0; i < displayCount; i++) { 9943 final DisplayContent displayContent = mDisplayContents.valueAt(i); 9944 WindowState win = findFocusedWindowLocked(displayContent); 9945 if (win != null) { 9946 return win; 9947 } 9948 } 9949 return null; 9950 } 9951 9952 private WindowState findFocusedWindowLocked(DisplayContent displayContent) { 9953 final WindowList windows = displayContent.getWindowList(); 9954 for (int i = windows.size() - 1; i >= 0; i--) { 9955 final WindowState win = windows.get(i); 9956 9957 if (localLOGV || DEBUG_FOCUS) Slog.v( 9958 TAG, "Looking for focus: " + i 9959 + " = " + win 9960 + ", flags=" + win.mAttrs.flags 9961 + ", canReceive=" + win.canReceiveKeys()); 9962 9963 AppWindowToken wtoken = win.mAppToken; 9964 9965 // If this window's application has been removed, just skip it. 9966 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 9967 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because " 9968 + (wtoken.removed ? "removed" : "sendingToBottom")); 9969 continue; 9970 } 9971 9972 if (!win.canReceiveKeys()) { 9973 continue; 9974 } 9975 9976 // Descend through all of the app tokens and find the first that either matches 9977 // win.mAppToken (return win) or mFocusedApp (return null). 9978 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && 9979 mFocusedApp != null) { 9980 ArrayList<Task> tasks = displayContent.getTasks(); 9981 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9982 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9983 int tokenNdx = tokens.size() - 1; 9984 for ( ; tokenNdx >= 0; --tokenNdx) { 9985 final AppWindowToken token = tokens.get(tokenNdx); 9986 if (wtoken == token) { 9987 break; 9988 } 9989 if (mFocusedApp == token) { 9990 // Whoops, we are below the focused app... no focus for you! 9991 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG, 9992 "findFocusedWindow: Reached focused app=" + mFocusedApp); 9993 return null; 9994 } 9995 } 9996 if (tokenNdx >= 0) { 9997 // Early exit from loop, must have found the matching token. 9998 break; 9999 } 10000 } 10001 } 10002 10003 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i + 10004 " = " + win); 10005 return win; 10006 } 10007 10008 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows."); 10009 return null; 10010 } 10011 10012 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 10013 if (mDisplayFrozen) { 10014 return; 10015 } 10016 10017 if (!mDisplayReady || !mPolicy.isScreenOnFully()) { 10018 // No need to freeze the screen before the system is ready or if 10019 // the screen is off. 10020 return; 10021 } 10022 10023 mScreenFrozenLock.acquire(); 10024 10025 mDisplayFrozen = true; 10026 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 10027 mLastFinishedFreezeSource = null; 10028 10029 mInputMonitor.freezeInputDispatchingLw(); 10030 10031 // Clear the last input window -- that is just used for 10032 // clean transitions between IMEs, and if we are freezing 10033 // the screen then the whole world is changing behind the scenes. 10034 mPolicy.setLastInputMethodWindowLw(null, null); 10035 10036 if (mAppTransition.isTransitionSet()) { 10037 mAppTransition.freeze(); 10038 } 10039 10040 if (PROFILE_ORIENTATION) { 10041 File file = new File("/data/system/frozen"); 10042 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 10043 } 10044 10045 if (CUSTOM_SCREEN_ROTATION) { 10046 mExitAnimId = exitAnim; 10047 mEnterAnimId = enterAnim; 10048 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10049 final int displayId = displayContent.getDisplayId(); 10050 ScreenRotationAnimation screenRotationAnimation = 10051 mAnimator.getScreenRotationAnimationLocked(displayId); 10052 if (screenRotationAnimation != null) { 10053 screenRotationAnimation.kill(); 10054 } 10055 10056 // Check whether the current screen contains any secure content. 10057 boolean isSecure = false; 10058 final WindowList windows = getDefaultWindowListLocked(); 10059 final int N = windows.size(); 10060 for (int i = 0; i < N; i++) { 10061 WindowState ws = windows.get(i); 10062 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) { 10063 isSecure = true; 10064 break; 10065 } 10066 } 10067 10068 // TODO(multidisplay): rotation on main screen only. 10069 displayContent.updateDisplayInfo(); 10070 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 10071 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure); 10072 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10073 } 10074 } 10075 10076 private void stopFreezingDisplayLocked() { 10077 if (!mDisplayFrozen) { 10078 return; 10079 } 10080 10081 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen 10082 || mClientFreezingScreen) { 10083 if (DEBUG_ORIENTATION) Slog.d(TAG, 10084 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 10085 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 10086 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 10087 + ", mClientFreezingScreen=" + mClientFreezingScreen); 10088 return; 10089 } 10090 10091 mDisplayFrozen = false; 10092 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 10093 StringBuilder sb = new StringBuilder(128); 10094 sb.append("Screen frozen for "); 10095 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 10096 if (mLastFinishedFreezeSource != null) { 10097 sb.append(" due to "); 10098 sb.append(mLastFinishedFreezeSource); 10099 } 10100 Slog.i(TAG, sb.toString()); 10101 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 10102 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 10103 if (PROFILE_ORIENTATION) { 10104 Debug.stopMethodTracing(); 10105 } 10106 10107 boolean updateRotation = false; 10108 10109 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10110 final int displayId = displayContent.getDisplayId(); 10111 ScreenRotationAnimation screenRotationAnimation = 10112 mAnimator.getScreenRotationAnimationLocked(displayId); 10113 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 10114 && screenRotationAnimation.hasScreenshot()) { 10115 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 10116 // TODO(multidisplay): rotation on main screen only. 10117 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10118 // Get rotation animation again, with new top window 10119 boolean isDimming = displayContent.isDimming(); 10120 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 10121 mExitAnimId = mEnterAnimId = 0; 10122 } 10123 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 10124 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, 10125 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 10126 scheduleAnimationLocked(); 10127 } else { 10128 screenRotationAnimation.kill(); 10129 screenRotationAnimation = null; 10130 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10131 updateRotation = true; 10132 } 10133 } else { 10134 if (screenRotationAnimation != null) { 10135 screenRotationAnimation.kill(); 10136 screenRotationAnimation = null; 10137 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10138 } 10139 updateRotation = true; 10140 } 10141 10142 mInputMonitor.thawInputDispatchingLw(); 10143 10144 boolean configChanged; 10145 10146 // While the display is frozen we don't re-compute the orientation 10147 // to avoid inconsistent states. However, something interesting 10148 // could have actually changed during that time so re-evaluate it 10149 // now to catch that. 10150 configChanged = updateOrientationFromAppTokensLocked(false); 10151 10152 // A little kludge: a lot could have happened while the 10153 // display was frozen, so now that we are coming back we 10154 // do a gc so that any remote references the system 10155 // processes holds on others can be released if they are 10156 // no longer needed. 10157 mH.removeMessages(H.FORCE_GC); 10158 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 10159 10160 mScreenFrozenLock.release(); 10161 10162 if (updateRotation) { 10163 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 10164 configChanged |= updateRotationUncheckedLocked(false); 10165 } 10166 10167 if (configChanged) { 10168 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10169 } 10170 } 10171 10172 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 10173 DisplayMetrics dm) { 10174 if (index < tokens.length) { 10175 String str = tokens[index]; 10176 if (str != null && str.length() > 0) { 10177 try { 10178 int val = Integer.parseInt(str); 10179 return val; 10180 } catch (Exception e) { 10181 } 10182 } 10183 } 10184 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 10185 return defDps; 10186 } 10187 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 10188 return val; 10189 } 10190 10191 void createWatermarkInTransaction() { 10192 if (mWatermark != null) { 10193 return; 10194 } 10195 10196 File file = new File("/system/etc/setup.conf"); 10197 FileInputStream in = null; 10198 DataInputStream ind = null; 10199 try { 10200 in = new FileInputStream(file); 10201 ind = new DataInputStream(in); 10202 String line = ind.readLine(); 10203 if (line != null) { 10204 String[] toks = line.split("%"); 10205 if (toks != null && toks.length > 0) { 10206 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 10207 mRealDisplayMetrics, mFxSession, toks); 10208 } 10209 } 10210 } catch (FileNotFoundException e) { 10211 } catch (IOException e) { 10212 } finally { 10213 if (ind != null) { 10214 try { 10215 ind.close(); 10216 } catch (IOException e) { 10217 } 10218 } else if (in != null) { 10219 try { 10220 in.close(); 10221 } catch (IOException e) { 10222 } 10223 } 10224 } 10225 } 10226 10227 @Override 10228 public void statusBarVisibilityChanged(int visibility) { 10229 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10230 != PackageManager.PERMISSION_GRANTED) { 10231 throw new SecurityException("Caller does not hold permission " 10232 + android.Manifest.permission.STATUS_BAR); 10233 } 10234 10235 synchronized (mWindowMap) { 10236 mLastStatusBarVisibility = visibility; 10237 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 10238 updateStatusBarVisibilityLocked(visibility); 10239 } 10240 } 10241 10242 // TOOD(multidisplay): StatusBar on multiple screens? 10243 void updateStatusBarVisibilityLocked(int visibility) { 10244 mInputManager.setSystemUiVisibility(visibility); 10245 final WindowList windows = getDefaultWindowListLocked(); 10246 final int N = windows.size(); 10247 for (int i = 0; i < N; i++) { 10248 WindowState ws = windows.get(i); 10249 try { 10250 int curValue = ws.mSystemUiVisibility; 10251 int diff = curValue ^ visibility; 10252 // We are only interested in differences of one of the 10253 // clearable flags... 10254 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 10255 // ...if it has actually been cleared. 10256 diff &= ~visibility; 10257 int newValue = (curValue&~diff) | (visibility&diff); 10258 if (newValue != curValue) { 10259 ws.mSeq++; 10260 ws.mSystemUiVisibility = newValue; 10261 } 10262 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 10263 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 10264 visibility, newValue, diff); 10265 } 10266 } catch (RemoteException e) { 10267 // so sorry 10268 } 10269 } 10270 } 10271 10272 @Override 10273 public void reevaluateStatusBarVisibility() { 10274 synchronized (mWindowMap) { 10275 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 10276 updateStatusBarVisibilityLocked(visibility); 10277 performLayoutAndPlaceSurfacesLocked(); 10278 } 10279 } 10280 10281 @Override 10282 public FakeWindow addFakeWindow(Looper looper, 10283 InputEventReceiver.Factory inputEventReceiverFactory, 10284 String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags, 10285 boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) { 10286 synchronized (mWindowMap) { 10287 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 10288 name, windowType, 10289 layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys, 10290 hasFocus, touchFullscreen); 10291 int i=0; 10292 while (i<mFakeWindows.size()) { 10293 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 10294 break; 10295 } 10296 } 10297 mFakeWindows.add(i, fw); 10298 mInputMonitor.updateInputWindowsLw(true); 10299 return fw; 10300 } 10301 } 10302 10303 boolean removeFakeWindowLocked(FakeWindow window) { 10304 synchronized (mWindowMap) { 10305 if (mFakeWindows.remove(window)) { 10306 mInputMonitor.updateInputWindowsLw(true); 10307 return true; 10308 } 10309 return false; 10310 } 10311 } 10312 10313 // It is assumed that this method is called only by InputMethodManagerService. 10314 public void saveLastInputMethodWindowForTransition() { 10315 synchronized (mWindowMap) { 10316 // TODO(multidisplay): Pass in the displayID. 10317 DisplayContent displayContent = getDefaultDisplayContentLocked(); 10318 if (mInputMethodWindow != null) { 10319 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 10320 } 10321 } 10322 } 10323 10324 public int getInputMethodWindowVisibleHeight() { 10325 synchronized (mWindowMap) { 10326 return mPolicy.getInputMethodWindowVisibleHeightLw(); 10327 } 10328 } 10329 10330 @Override 10331 public boolean hasNavigationBar() { 10332 return mPolicy.hasNavigationBar(); 10333 } 10334 10335 @Override 10336 public void lockNow(Bundle options) { 10337 mPolicy.lockNow(options); 10338 } 10339 10340 public void showRecentApps() { 10341 mPolicy.showRecentApps(); 10342 } 10343 10344 @Override 10345 public boolean isSafeModeEnabled() { 10346 return mSafeMode; 10347 } 10348 10349 @Override 10350 public boolean clearWindowContentFrameStats(IBinder token) { 10351 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10352 "clearWindowContentFrameStats()")) { 10353 throw new SecurityException("Requires FRAME_STATS permission"); 10354 } 10355 synchronized (mWindowMap) { 10356 WindowState windowState = mWindowMap.get(token); 10357 if (windowState == null) { 10358 return false; 10359 } 10360 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10361 if (surfaceControl == null) { 10362 return false; 10363 } 10364 return surfaceControl.clearContentFrameStats(); 10365 } 10366 } 10367 10368 @Override 10369 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) { 10370 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10371 "getWindowContentFrameStats()")) { 10372 throw new SecurityException("Requires FRAME_STATS permission"); 10373 } 10374 synchronized (mWindowMap) { 10375 WindowState windowState = mWindowMap.get(token); 10376 if (windowState == null) { 10377 return null; 10378 } 10379 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10380 if (surfaceControl == null) { 10381 return null; 10382 } 10383 if (mTempWindowRenderStats == null) { 10384 mTempWindowRenderStats = new WindowContentFrameStats(); 10385 } 10386 WindowContentFrameStats stats = mTempWindowRenderStats; 10387 if (!surfaceControl.getContentFrameStats(stats)) { 10388 return null; 10389 } 10390 return stats; 10391 } 10392 } 10393 10394 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10395 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 10396 mPolicy.dump(" ", pw, args); 10397 } 10398 10399 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10400 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 10401 mAnimator.dumpLocked(pw, " ", dumpAll); 10402 } 10403 10404 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 10405 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 10406 if (mTokenMap.size() > 0) { 10407 pw.println(" All tokens:"); 10408 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10409 while (it.hasNext()) { 10410 WindowToken token = it.next(); 10411 pw.print(" "); pw.print(token); 10412 if (dumpAll) { 10413 pw.println(':'); 10414 token.dump(pw, " "); 10415 } else { 10416 pw.println(); 10417 } 10418 } 10419 } 10420 if (mWallpaperTokens.size() > 0) { 10421 pw.println(); 10422 pw.println(" Wallpaper tokens:"); 10423 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 10424 WindowToken token = mWallpaperTokens.get(i); 10425 pw.print(" Wallpaper #"); pw.print(i); 10426 pw.print(' '); pw.print(token); 10427 if (dumpAll) { 10428 pw.println(':'); 10429 token.dump(pw, " "); 10430 } else { 10431 pw.println(); 10432 } 10433 } 10434 } 10435 if (mFinishedStarting.size() > 0) { 10436 pw.println(); 10437 pw.println(" Finishing start of application tokens:"); 10438 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10439 WindowToken token = mFinishedStarting.get(i); 10440 pw.print(" Finished Starting #"); pw.print(i); 10441 pw.print(' '); pw.print(token); 10442 if (dumpAll) { 10443 pw.println(':'); 10444 token.dump(pw, " "); 10445 } else { 10446 pw.println(); 10447 } 10448 } 10449 } 10450 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 10451 pw.println(); 10452 if (mOpeningApps.size() > 0) { 10453 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10454 } 10455 if (mClosingApps.size() > 0) { 10456 pw.print(" mClosingApps="); pw.println(mClosingApps); 10457 } 10458 } 10459 } 10460 10461 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 10462 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 10463 for (int i=0; i<mSessions.size(); i++) { 10464 Session s = mSessions.valueAt(i); 10465 pw.print(" Session "); pw.print(s); pw.println(':'); 10466 s.dump(pw, " "); 10467 } 10468 } 10469 10470 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 10471 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 10472 if (mDisplayReady) { 10473 final int numDisplays = mDisplayContents.size(); 10474 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10475 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10476 displayContent.dump(" ", pw); 10477 } 10478 } else { 10479 pw.println(" NO DISPLAY"); 10480 } 10481 } 10482 10483 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 10484 ArrayList<WindowState> windows) { 10485 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 10486 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 10487 } 10488 10489 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 10490 ArrayList<WindowState> windows) { 10491 final int numDisplays = mDisplayContents.size(); 10492 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10493 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); 10494 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10495 final WindowState w = windowList.get(winNdx); 10496 if (windows == null || windows.contains(w)) { 10497 pw.print(" Window #"); pw.print(winNdx); pw.print(' '); 10498 pw.print(w); pw.println(":"); 10499 w.dump(pw, " ", dumpAll || windows != null); 10500 } 10501 } 10502 } 10503 if (mInputMethodDialogs.size() > 0) { 10504 pw.println(); 10505 pw.println(" Input method dialogs:"); 10506 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 10507 WindowState w = mInputMethodDialogs.get(i); 10508 if (windows == null || windows.contains(w)) { 10509 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 10510 } 10511 } 10512 } 10513 if (mPendingRemove.size() > 0) { 10514 pw.println(); 10515 pw.println(" Remove pending for:"); 10516 for (int i=mPendingRemove.size()-1; i>=0; i--) { 10517 WindowState w = mPendingRemove.get(i); 10518 if (windows == null || windows.contains(w)) { 10519 pw.print(" Remove #"); pw.print(i); pw.print(' '); 10520 pw.print(w); 10521 if (dumpAll) { 10522 pw.println(":"); 10523 w.dump(pw, " ", true); 10524 } else { 10525 pw.println(); 10526 } 10527 } 10528 } 10529 } 10530 if (mForceRemoves != null && mForceRemoves.size() > 0) { 10531 pw.println(); 10532 pw.println(" Windows force removing:"); 10533 for (int i=mForceRemoves.size()-1; i>=0; i--) { 10534 WindowState w = mForceRemoves.get(i); 10535 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10536 pw.print(w); 10537 if (dumpAll) { 10538 pw.println(":"); 10539 w.dump(pw, " ", true); 10540 } else { 10541 pw.println(); 10542 } 10543 } 10544 } 10545 if (mDestroySurface.size() > 0) { 10546 pw.println(); 10547 pw.println(" Windows waiting to destroy their surface:"); 10548 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10549 WindowState w = mDestroySurface.get(i); 10550 if (windows == null || windows.contains(w)) { 10551 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10552 pw.print(w); 10553 if (dumpAll) { 10554 pw.println(":"); 10555 w.dump(pw, " ", true); 10556 } else { 10557 pw.println(); 10558 } 10559 } 10560 } 10561 } 10562 if (mLosingFocus.size() > 0) { 10563 pw.println(); 10564 pw.println(" Windows losing focus:"); 10565 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10566 WindowState w = mLosingFocus.get(i); 10567 if (windows == null || windows.contains(w)) { 10568 pw.print(" Losing #"); pw.print(i); pw.print(' '); 10569 pw.print(w); 10570 if (dumpAll) { 10571 pw.println(":"); 10572 w.dump(pw, " ", true); 10573 } else { 10574 pw.println(); 10575 } 10576 } 10577 } 10578 } 10579 if (mResizingWindows.size() > 0) { 10580 pw.println(); 10581 pw.println(" Windows waiting to resize:"); 10582 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10583 WindowState w = mResizingWindows.get(i); 10584 if (windows == null || windows.contains(w)) { 10585 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 10586 pw.print(w); 10587 if (dumpAll) { 10588 pw.println(":"); 10589 w.dump(pw, " ", true); 10590 } else { 10591 pw.println(); 10592 } 10593 } 10594 } 10595 } 10596 if (mWaitingForDrawn.size() > 0) { 10597 pw.println(); 10598 pw.println(" Clients waiting for these windows to be drawn:"); 10599 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10600 WindowState win = mWaitingForDrawn.get(i); 10601 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); 10602 } 10603 } 10604 pw.println(); 10605 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10606 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10607 if (mLastFocus != mCurrentFocus) { 10608 pw.print(" mLastFocus="); pw.println(mLastFocus); 10609 } 10610 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10611 if (mInputMethodTarget != null) { 10612 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10613 } 10614 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10615 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10616 pw.print(" mLastDisplayFreezeDuration="); 10617 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 10618 if ( mLastFinishedFreezeSource != null) { 10619 pw.print(" due to "); 10620 pw.print(mLastFinishedFreezeSource); 10621 } 10622 pw.println(); 10623 if (dumpAll) { 10624 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 10625 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 10626 if (mLastStatusBarVisibility != 0) { 10627 pw.print(" mLastStatusBarVisibility=0x"); 10628 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 10629 } 10630 if (mInputMethodWindow != null) { 10631 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10632 } 10633 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 10634 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) { 10635 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 10636 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 10637 } 10638 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 10639 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 10640 if (mInputMethodAnimLayerAdjustment != 0 || 10641 mWallpaperAnimLayerAdjustment != 0) { 10642 pw.print(" mInputMethodAnimLayerAdjustment="); 10643 pw.print(mInputMethodAnimLayerAdjustment); 10644 pw.print(" mWallpaperAnimLayerAdjustment="); 10645 pw.println(mWallpaperAnimLayerAdjustment); 10646 } 10647 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10648 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10649 if (needsLayout()) { 10650 pw.print(" layoutNeeded on displays="); 10651 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10652 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10653 if (displayContent.layoutNeeded) { 10654 pw.print(displayContent.getDisplayId()); 10655 } 10656 } 10657 pw.println(); 10658 } 10659 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 10660 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10661 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 10662 pw.print(" client="); pw.print(mClientFreezingScreen); 10663 pw.print(" apps="); pw.print(mAppsFreezingScreen); 10664 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 10665 pw.print(" mRotation="); pw.print(mRotation); 10666 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 10667 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 10668 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 10669 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 10670 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled); 10671 pw.print(" window="); pw.print(mWindowAnimationScaleSetting); 10672 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); 10673 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); 10674 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); 10675 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 10676 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 10677 pw.println(" mLayoutToAnim:"); 10678 mAppTransition.dump(pw); 10679 } 10680 } 10681 10682 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10683 int opti, boolean dumpAll) { 10684 WindowList windows = new WindowList(); 10685 if ("visible".equals(name)) { 10686 synchronized(mWindowMap) { 10687 final int numDisplays = mDisplayContents.size(); 10688 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10689 final WindowList windowList = 10690 mDisplayContents.valueAt(displayNdx).getWindowList(); 10691 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10692 final WindowState w = windowList.get(winNdx); 10693 if (w.mWinAnimator.mSurfaceShown) { 10694 windows.add(w); 10695 } 10696 } 10697 } 10698 } 10699 } else { 10700 int objectId = 0; 10701 // See if this is an object ID. 10702 try { 10703 objectId = Integer.parseInt(name, 16); 10704 name = null; 10705 } catch (RuntimeException e) { 10706 } 10707 synchronized(mWindowMap) { 10708 final int numDisplays = mDisplayContents.size(); 10709 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10710 final WindowList windowList = 10711 mDisplayContents.valueAt(displayNdx).getWindowList(); 10712 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10713 final WindowState w = windowList.get(winNdx); 10714 if (name != null) { 10715 if (w.mAttrs.getTitle().toString().contains(name)) { 10716 windows.add(w); 10717 } 10718 } else if (System.identityHashCode(w) == objectId) { 10719 windows.add(w); 10720 } 10721 } 10722 } 10723 } 10724 } 10725 10726 if (windows.size() <= 0) { 10727 return false; 10728 } 10729 10730 synchronized(mWindowMap) { 10731 dumpWindowsLocked(pw, dumpAll, windows); 10732 } 10733 return true; 10734 } 10735 10736 void dumpLastANRLocked(PrintWriter pw) { 10737 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10738 if (mLastANRState == null) { 10739 pw.println(" <no ANR has occurred since boot>"); 10740 } else { 10741 pw.println(mLastANRState); 10742 } 10743 } 10744 10745 /** 10746 * Saves information about the state of the window manager at 10747 * the time an ANR occurred before anything else in the system changes 10748 * in response. 10749 * 10750 * @param appWindowToken The application that ANR'd, may be null. 10751 * @param windowState The window that ANR'd, may be null. 10752 * @param reason The reason for the ANR, may be null. 10753 */ 10754 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, 10755 String reason) { 10756 StringWriter sw = new StringWriter(); 10757 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 10758 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10759 if (appWindowToken != null) { 10760 pw.println(" Application at fault: " + appWindowToken.stringName); 10761 } 10762 if (windowState != null) { 10763 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10764 } 10765 if (reason != null) { 10766 pw.println(" Reason: " + reason); 10767 } 10768 pw.println(); 10769 dumpWindowsNoHeaderLocked(pw, true, null); 10770 pw.close(); 10771 mLastANRState = sw.toString(); 10772 } 10773 10774 @Override 10775 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10776 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10777 != PackageManager.PERMISSION_GRANTED) { 10778 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10779 + Binder.getCallingPid() 10780 + ", uid=" + Binder.getCallingUid()); 10781 return; 10782 } 10783 10784 boolean dumpAll = false; 10785 10786 int opti = 0; 10787 while (opti < args.length) { 10788 String opt = args[opti]; 10789 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10790 break; 10791 } 10792 opti++; 10793 if ("-a".equals(opt)) { 10794 dumpAll = true; 10795 } else if ("-h".equals(opt)) { 10796 pw.println("Window manager dump options:"); 10797 pw.println(" [-a] [-h] [cmd] ..."); 10798 pw.println(" cmd may be one of:"); 10799 pw.println(" l[astanr]: last ANR information"); 10800 pw.println(" p[policy]: policy state"); 10801 pw.println(" a[animator]: animator state"); 10802 pw.println(" s[essions]: active sessions"); 10803 pw.println(" d[isplays]: active display contents"); 10804 pw.println(" t[okens]: token list"); 10805 pw.println(" w[indows]: window list"); 10806 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10807 pw.println(" be a partial substring in a window name, a"); 10808 pw.println(" Window hex object identifier, or"); 10809 pw.println(" \"all\" for all windows, or"); 10810 pw.println(" \"visible\" for the visible windows."); 10811 pw.println(" -a: include all available server state."); 10812 return; 10813 } else { 10814 pw.println("Unknown argument: " + opt + "; use -h for help"); 10815 } 10816 } 10817 10818 // Is the caller requesting to dump a particular piece of data? 10819 if (opti < args.length) { 10820 String cmd = args[opti]; 10821 opti++; 10822 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10823 synchronized(mWindowMap) { 10824 dumpLastANRLocked(pw); 10825 } 10826 return; 10827 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10828 synchronized(mWindowMap) { 10829 dumpPolicyLocked(pw, args, true); 10830 } 10831 return; 10832 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 10833 synchronized(mWindowMap) { 10834 dumpAnimatorLocked(pw, args, true); 10835 } 10836 return; 10837 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10838 synchronized(mWindowMap) { 10839 dumpSessionsLocked(pw, true); 10840 } 10841 return; 10842 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 10843 synchronized(mWindowMap) { 10844 dumpDisplayContentsLocked(pw, true); 10845 } 10846 return; 10847 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10848 synchronized(mWindowMap) { 10849 dumpTokensLocked(pw, true); 10850 } 10851 return; 10852 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10853 synchronized(mWindowMap) { 10854 dumpWindowsLocked(pw, true, null); 10855 } 10856 return; 10857 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10858 synchronized(mWindowMap) { 10859 dumpWindowsLocked(pw, true, null); 10860 } 10861 return; 10862 } else { 10863 // Dumping a single name? 10864 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10865 pw.println("Bad window command, or no windows match: " + cmd); 10866 pw.println("Use -h for help."); 10867 } 10868 return; 10869 } 10870 } 10871 10872 synchronized(mWindowMap) { 10873 pw.println(); 10874 if (dumpAll) { 10875 pw.println("-------------------------------------------------------------------------------"); 10876 } 10877 dumpLastANRLocked(pw); 10878 pw.println(); 10879 if (dumpAll) { 10880 pw.println("-------------------------------------------------------------------------------"); 10881 } 10882 dumpPolicyLocked(pw, args, dumpAll); 10883 pw.println(); 10884 if (dumpAll) { 10885 pw.println("-------------------------------------------------------------------------------"); 10886 } 10887 dumpAnimatorLocked(pw, args, dumpAll); 10888 pw.println(); 10889 if (dumpAll) { 10890 pw.println("-------------------------------------------------------------------------------"); 10891 } 10892 dumpSessionsLocked(pw, dumpAll); 10893 pw.println(); 10894 if (dumpAll) { 10895 pw.println("-------------------------------------------------------------------------------"); 10896 } 10897 dumpDisplayContentsLocked(pw, dumpAll); 10898 pw.println(); 10899 if (dumpAll) { 10900 pw.println("-------------------------------------------------------------------------------"); 10901 } 10902 dumpTokensLocked(pw, dumpAll); 10903 pw.println(); 10904 if (dumpAll) { 10905 pw.println("-------------------------------------------------------------------------------"); 10906 } 10907 dumpWindowsLocked(pw, dumpAll, null); 10908 } 10909 } 10910 10911 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10912 @Override 10913 public void monitor() { 10914 synchronized (mWindowMap) { } 10915 } 10916 10917 public interface OnHardKeyboardStatusChangeListener { 10918 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 10919 } 10920 10921 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 10922 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 10923 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 10924 Integer.toHexString(pendingLayoutChanges)); 10925 } 10926 } 10927 10928 private DisplayContent newDisplayContentLocked(final Display display) { 10929 DisplayContent displayContent = new DisplayContent(display, this); 10930 final int displayId = display.getDisplayId(); 10931 if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display); 10932 mDisplayContents.put(displayId, displayContent); 10933 10934 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10935 final Rect rect = new Rect(); 10936 mDisplaySettings.getOverscanLocked(displayInfo.name, rect); 10937 synchronized (displayContent.mDisplaySizeLock) { 10938 displayInfo.overscanLeft = rect.left; 10939 displayInfo.overscanTop = rect.top; 10940 displayInfo.overscanRight = rect.right; 10941 displayInfo.overscanBottom = rect.bottom; 10942 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 10943 displayId, displayInfo); 10944 } 10945 configureDisplayPolicyLocked(displayContent); 10946 10947 // TODO: Create an input channel for each display with touch capability. 10948 if (displayId == Display.DEFAULT_DISPLAY) { 10949 displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent); 10950 registerPointerEventListener(displayContent.mTapDetector); 10951 } 10952 10953 return displayContent; 10954 } 10955 10956 public void createDisplayContentLocked(final Display display) { 10957 if (display == null) { 10958 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 10959 } 10960 getDisplayContentLocked(display.getDisplayId()); 10961 } 10962 10963 /** 10964 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 10965 * there is a Display for the displayId. 10966 * @param displayId The display the caller is interested in. 10967 * @return The DisplayContent associated with displayId or null if there is no Display for it. 10968 */ 10969 public DisplayContent getDisplayContentLocked(final int displayId) { 10970 DisplayContent displayContent = mDisplayContents.get(displayId); 10971 if (displayContent == null) { 10972 final Display display = mDisplayManager.getDisplay(displayId); 10973 if (display != null) { 10974 displayContent = newDisplayContentLocked(display); 10975 } 10976 } 10977 return displayContent; 10978 } 10979 10980 // There is an inherent assumption that this will never return null. 10981 public DisplayContent getDefaultDisplayContentLocked() { 10982 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 10983 } 10984 10985 public WindowList getDefaultWindowListLocked() { 10986 return getDefaultDisplayContentLocked().getWindowList(); 10987 } 10988 10989 public DisplayInfo getDefaultDisplayInfoLocked() { 10990 return getDefaultDisplayContentLocked().getDisplayInfo(); 10991 } 10992 10993 /** 10994 * Return the list of WindowStates associated on the passed display. 10995 * @param display The screen to return windows from. 10996 * @return The list of WindowStates on the screen, or null if the there is no screen. 10997 */ 10998 public WindowList getWindowListLocked(final Display display) { 10999 return getWindowListLocked(display.getDisplayId()); 11000 } 11001 11002 /** 11003 * Return the list of WindowStates associated on the passed display. 11004 * @param displayId The screen to return windows from. 11005 * @return The list of WindowStates on the screen, or null if the there is no screen. 11006 */ 11007 public WindowList getWindowListLocked(final int displayId) { 11008 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11009 return displayContent != null ? displayContent.getWindowList() : null; 11010 } 11011 11012 public void onDisplayAdded(int displayId) { 11013 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 11014 } 11015 11016 public void handleDisplayAdded(int displayId) { 11017 synchronized (mWindowMap) { 11018 final Display display = mDisplayManager.getDisplay(displayId); 11019 if (display != null) { 11020 createDisplayContentLocked(display); 11021 displayReady(displayId); 11022 } 11023 } 11024 } 11025 11026 public void onDisplayRemoved(int displayId) { 11027 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 11028 } 11029 11030 private void handleDisplayRemovedLocked(int displayId) { 11031 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11032 if (displayContent != null) { 11033 if (displayContent.isAnimating()) { 11034 displayContent.mDeferredRemoval = true; 11035 return; 11036 } 11037 if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent); 11038 mDisplayContents.delete(displayId); 11039 displayContent.close(); 11040 if (displayId == Display.DEFAULT_DISPLAY) { 11041 unregisterPointerEventListener(displayContent.mTapDetector); 11042 } 11043 } 11044 mAnimator.removeDisplayLocked(displayId); 11045 } 11046 11047 public void onDisplayChanged(int displayId) { 11048 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 11049 } 11050 11051 private void handleDisplayChangedLocked(int displayId) { 11052 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11053 if (displayContent != null) { 11054 displayContent.updateDisplayInfo(); 11055 } 11056 } 11057 11058 @Override 11059 public Object getWindowManagerLock() { 11060 return mWindowMap; 11061 } 11062 11063 private final class LocalService extends WindowManagerInternal { 11064 @Override 11065 public void requestTraversalFromDisplayManager() { 11066 requestTraversal(); 11067 } 11068 11069 @Override 11070 public void setMagnificationSpec(MagnificationSpec spec) { 11071 synchronized (mWindowMap) { 11072 if (mAccessibilityController != null) { 11073 mAccessibilityController.setMagnificationSpecLocked(spec); 11074 } else { 11075 throw new IllegalStateException("Magnification callbacks not set!"); 11076 } 11077 } 11078 if (Binder.getCallingPid() != android.os.Process.myPid()) { 11079 spec.recycle(); 11080 } 11081 } 11082 11083 @Override 11084 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { 11085 synchronized (mWindowMap) { 11086 WindowState windowState = mWindowMap.get(windowToken); 11087 if (windowState == null) { 11088 return null; 11089 } 11090 MagnificationSpec spec = null; 11091 if (mAccessibilityController != null) { 11092 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState); 11093 } 11094 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) { 11095 return null; 11096 } 11097 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec); 11098 spec.scale *= windowState.mGlobalScale; 11099 return spec; 11100 } 11101 } 11102 11103 @Override 11104 public void setMagnificationCallbacks(MagnificationCallbacks callbacks) { 11105 synchronized (mWindowMap) { 11106 if (mAccessibilityController == null) { 11107 mAccessibilityController = new AccessibilityController( 11108 WindowManagerService.this); 11109 } 11110 mAccessibilityController.setMagnificationCallbacksLocked(callbacks); 11111 if (!mAccessibilityController.hasCallbacksLocked()) { 11112 mAccessibilityController = null; 11113 } 11114 } 11115 } 11116 11117 @Override 11118 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) { 11119 synchronized (mWindowMap) { 11120 if (mAccessibilityController == null) { 11121 mAccessibilityController = new AccessibilityController( 11122 WindowManagerService.this); 11123 } 11124 mAccessibilityController.setWindowsForAccessibilityCallback(callback); 11125 if (!mAccessibilityController.hasCallbacksLocked()) { 11126 mAccessibilityController = null; 11127 } 11128 } 11129 } 11130 11131 @Override 11132 public void setInputFilter(IInputFilter filter) { 11133 mInputManager.setInputFilter(filter); 11134 } 11135 11136 @Override 11137 public IBinder getFocusedWindowToken() { 11138 synchronized (mWindowMap) { 11139 WindowState windowState = getFocusedWindowLocked(); 11140 if (windowState != null) { 11141 return windowState.mClient.asBinder(); 11142 } 11143 return null; 11144 } 11145 } 11146 11147 @Override 11148 public boolean isKeyguardLocked() { 11149 return WindowManagerService.this.isKeyguardLocked(); 11150 } 11151 11152 @Override 11153 public void showGlobalActions() { 11154 WindowManagerService.this.showGlobalActions(); 11155 } 11156 11157 @Override 11158 public void getWindowFrame(IBinder token, Rect outBounds) { 11159 synchronized (mWindowMap) { 11160 WindowState windowState = mWindowMap.get(token); 11161 if (windowState != null) { 11162 outBounds.set(windowState.mFrame); 11163 } else { 11164 outBounds.setEmpty(); 11165 } 11166 } 11167 } 11168 11169 public void waitForAllWindowsDrawn(Runnable callback, long timeout) { 11170 synchronized (mWindowMap) { 11171 mWaitingForDrawnCallback = callback; 11172 final WindowList windows = getDefaultWindowListLocked(); 11173 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 11174 final WindowState win = windows.get(winNdx); 11175 if (win.mHasSurface) { 11176 win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 11177 // Force add to mResizingWindows. 11178 win.mLastContentInsets.set(-1, -1, -1, -1); 11179 mWaitingForDrawn.add(win); 11180 } 11181 } 11182 requestTraversalLocked(); 11183 } 11184 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 11185 if (mWaitingForDrawn.isEmpty()) { 11186 callback.run(); 11187 } else { 11188 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); 11189 checkDrawnWindowsLocked(); 11190 } 11191 } 11192 } 11193} 11194