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