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