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