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