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