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