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