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