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