WindowManagerService.java revision 4fd791735b21162bc573ece564144fa4f0e2ed29
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 Task task = new Task(atoken, stack, userId); 3401 mTaskIdToTask.put(taskId, task); 3402 stack.addTask(task, true); 3403 stack.getDisplayContent().moveStack(stack, 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 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3411 "addAppToken()")) { 3412 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3413 } 3414 3415 // Get the dispatching timeout here while we are not holding any locks so that it 3416 // can be cached by the AppWindowToken. The timeout value is used later by the 3417 // input dispatcher in code that does hold locks. If we did not cache the value 3418 // here we would run the chance of introducing a deadlock between the window manager 3419 // (which holds locks while updating the input dispatcher state) and the activity manager 3420 // (which holds locks while querying the application token). 3421 long inputDispatchingTimeoutNanos; 3422 try { 3423 inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L; 3424 } catch (RemoteException ex) { 3425 Slog.w(TAG, "Could not get dispatching timeout.", ex); 3426 inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 3427 } 3428 3429 synchronized(mWindowMap) { 3430 AppWindowToken atoken = findAppWindowToken(token.asBinder()); 3431 if (atoken != null) { 3432 Slog.w(TAG, "Attempted to add existing app token: " + token); 3433 return; 3434 } 3435 atoken = new AppWindowToken(this, token); 3436 atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos; 3437 atoken.groupId = taskId; 3438 atoken.appFullscreen = fullscreen; 3439 atoken.showWhenLocked = showWhenLocked; 3440 atoken.requestedOrientation = requestedOrientation; 3441 if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken 3442 + " to stack=" + stackId + " task=" + taskId + " at " + addPos); 3443 3444 Task task = mTaskIdToTask.get(taskId); 3445 if (task == null) { 3446 task = createTask(taskId, stackId, userId, atoken); 3447 } else { 3448 task.addAppToken(addPos, atoken); 3449 } 3450 3451 mTokenMap.put(token.asBinder(), atoken); 3452 3453 // Application tokens start out hidden. 3454 atoken.hidden = true; 3455 atoken.hiddenRequested = true; 3456 3457 //dump(); 3458 } 3459 } 3460 3461 @Override 3462 public void setAppGroupId(IBinder token, int groupId) { 3463 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3464 "setAppGroupId()")) { 3465 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3466 } 3467 3468 synchronized(mWindowMap) { 3469 final AppWindowToken atoken = findAppWindowToken(token); 3470 if (atoken == null) { 3471 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token); 3472 return; 3473 } 3474 Task oldTask = mTaskIdToTask.get(atoken.groupId); 3475 oldTask.removeAppToken(atoken); 3476 3477 atoken.groupId = groupId; 3478 Task newTask = mTaskIdToTask.get(groupId); 3479 if (newTask == null) { 3480 newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken); 3481 } 3482 newTask.mAppTokens.add(atoken); 3483 } 3484 } 3485 3486 public int getOrientationFromWindowsLocked() { 3487 if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 3488 // If the display is frozen, some activities may be in the middle 3489 // of restarting, and thus have removed their old window. If the 3490 // window has the flag to hide the lock screen, then the lock screen 3491 // can re-appear and inflict its own orientation on us. Keep the 3492 // orientation stable until this all settles down. 3493 return mLastWindowForcedOrientation; 3494 } 3495 3496 // TODO(multidisplay): Change to the correct display. 3497 final WindowList windows = getDefaultWindowListLocked(); 3498 int pos = windows.size() - 1; 3499 while (pos >= 0) { 3500 WindowState win = windows.get(pos); 3501 pos--; 3502 if (win.mAppToken != null) { 3503 // We hit an application window. so the orientation will be determined by the 3504 // app window. No point in continuing further. 3505 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3506 } 3507 if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) { 3508 continue; 3509 } 3510 int req = win.mAttrs.screenOrientation; 3511 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) || 3512 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){ 3513 continue; 3514 } 3515 3516 if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req); 3517 return (mLastWindowForcedOrientation=req); 3518 } 3519 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3520 } 3521 3522 public int getOrientationFromAppTokensLocked() { 3523 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3524 boolean findingBehind = false; 3525 boolean lastFullscreen = false; 3526 // TODO: Multi window. 3527 DisplayContent displayContent = getDefaultDisplayContentLocked(); 3528 final ArrayList<Task> tasks = displayContent.getTasks(); 3529 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 3530 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 3531 final int firstToken = tokens.size() - 1; 3532 for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) { 3533 final AppWindowToken atoken = tokens.get(tokenNdx); 3534 3535 if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken); 3536 3537 // if we're about to tear down this window and not seek for 3538 // the behind activity, don't use it for orientation 3539 if (!findingBehind 3540 && (!atoken.hidden && atoken.hiddenRequested)) { 3541 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken 3542 + " -- going to hide"); 3543 continue; 3544 } 3545 3546 if (tokenNdx == firstToken) { 3547 // If we have hit a new Task, and the bottom 3548 // of the previous group didn't explicitly say to use 3549 // the orientation behind it, and the last app was 3550 // full screen, then we'll stick with the 3551 // user's orientation. 3552 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND 3553 && lastFullscreen) { 3554 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3555 + " -- end of group, return " + lastOrientation); 3556 return lastOrientation; 3557 } 3558 } 3559 3560 // We ignore any hidden applications on the top. 3561 if (atoken.hiddenRequested || atoken.willBeHidden) { 3562 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken 3563 + " -- hidden on top"); 3564 continue; 3565 } 3566 3567 if (tokenNdx == 0) { 3568 // Last token in this task. 3569 lastOrientation = atoken.requestedOrientation; 3570 } 3571 3572 int or = atoken.requestedOrientation; 3573 // If this application is fullscreen, and didn't explicitly say 3574 // to use the orientation behind it, then just take whatever 3575 // orientation it has and ignores whatever is under it. 3576 lastFullscreen = atoken.appFullscreen; 3577 if (lastFullscreen 3578 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { 3579 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3580 + " -- full screen, return " + or); 3581 return or; 3582 } 3583 // If this application has requested an explicit orientation, 3584 // then use it. 3585 if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 3586 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { 3587 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3588 + " -- explicitly set, return " + or); 3589 return or; 3590 } 3591 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND); 3592 } 3593 } 3594 if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation"); 3595 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3596 } 3597 3598 @Override 3599 public Configuration updateOrientationFromAppTokens( 3600 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3601 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3602 "updateOrientationFromAppTokens()")) { 3603 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3604 } 3605 3606 Configuration config = null; 3607 long ident = Binder.clearCallingIdentity(); 3608 3609 synchronized(mWindowMap) { 3610 config = updateOrientationFromAppTokensLocked(currentConfig, 3611 freezeThisOneIfNeeded); 3612 } 3613 3614 Binder.restoreCallingIdentity(ident); 3615 return config; 3616 } 3617 3618 private Configuration updateOrientationFromAppTokensLocked( 3619 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3620 Configuration config = null; 3621 3622 if (updateOrientationFromAppTokensLocked(false)) { 3623 if (freezeThisOneIfNeeded != null) { 3624 AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded); 3625 if (atoken != null) { 3626 startAppFreezingScreenLocked(atoken, ActivityInfo.CONFIG_ORIENTATION); 3627 } 3628 } 3629 config = computeNewConfigurationLocked(); 3630 3631 } else if (currentConfig != null) { 3632 // No obvious action we need to take, but if our current 3633 // state mismatches the activity manager's, update it, 3634 // disregarding font scale, which should remain set to 3635 // the value of the previous configuration. 3636 mTempConfiguration.setToDefaults(); 3637 mTempConfiguration.fontScale = currentConfig.fontScale; 3638 if (computeScreenConfigurationLocked(mTempConfiguration)) { 3639 if (currentConfig.diff(mTempConfiguration) != 0) { 3640 mWaitingForConfig = true; 3641 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 3642 displayContent.layoutNeeded = true; 3643 int anim[] = new int[2]; 3644 if (displayContent.isDimming()) { 3645 anim[0] = anim[1] = 0; 3646 } else { 3647 mPolicy.selectRotationAnimationLw(anim); 3648 } 3649 startFreezingDisplayLocked(false, anim[0], anim[1]); 3650 config = new Configuration(mTempConfiguration); 3651 } 3652 } 3653 } 3654 3655 return config; 3656 } 3657 3658 /* 3659 * Determine the new desired orientation of the display, returning 3660 * a non-null new Configuration if it has changed from the current 3661 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL 3662 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE 3663 * SCREEN. This will typically be done for you if you call 3664 * sendNewConfiguration(). 3665 * 3666 * The orientation is computed from non-application windows first. If none of 3667 * the non-application windows specify orientation, the orientation is computed from 3668 * application tokens. 3669 * @see android.view.IWindowManager#updateOrientationFromAppTokens( 3670 * android.os.IBinder) 3671 */ 3672 boolean updateOrientationFromAppTokensLocked(boolean inTransaction) { 3673 long ident = Binder.clearCallingIdentity(); 3674 try { 3675 int req = getOrientationFromWindowsLocked(); 3676 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) { 3677 req = getOrientationFromAppTokensLocked(); 3678 } 3679 3680 if (req != mForcedAppOrientation) { 3681 mForcedAppOrientation = req; 3682 //send a message to Policy indicating orientation change to take 3683 //action like disabling/enabling sensors etc., 3684 mPolicy.setCurrentOrientationLw(req); 3685 if (updateRotationUncheckedLocked(inTransaction)) { 3686 // changed 3687 return true; 3688 } 3689 } 3690 3691 return false; 3692 } finally { 3693 Binder.restoreCallingIdentity(ident); 3694 } 3695 } 3696 3697 @Override 3698 public void setNewConfiguration(Configuration config) { 3699 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3700 "setNewConfiguration()")) { 3701 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3702 } 3703 3704 synchronized(mWindowMap) { 3705 mCurConfiguration = new Configuration(config); 3706 if (mWaitingForConfig) { 3707 mWaitingForConfig = false; 3708 mLastFinishedFreezeSource = "new-config"; 3709 } 3710 performLayoutAndPlaceSurfacesLocked(); 3711 } 3712 } 3713 3714 @Override 3715 public void setAppOrientation(IApplicationToken token, int requestedOrientation) { 3716 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3717 "setAppOrientation()")) { 3718 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3719 } 3720 3721 synchronized(mWindowMap) { 3722 AppWindowToken atoken = findAppWindowToken(token.asBinder()); 3723 if (atoken == null) { 3724 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token); 3725 return; 3726 } 3727 3728 atoken.requestedOrientation = requestedOrientation; 3729 } 3730 } 3731 3732 @Override 3733 public int getAppOrientation(IApplicationToken token) { 3734 synchronized(mWindowMap) { 3735 AppWindowToken wtoken = findAppWindowToken(token.asBinder()); 3736 if (wtoken == null) { 3737 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3738 } 3739 3740 return wtoken.requestedOrientation; 3741 } 3742 } 3743 3744 /** Call while in a Surface transaction. */ 3745 void setFocusedStackLayer() { 3746 mFocusedStackLayer = 0; 3747 if (mFocusedApp != null) { 3748 final WindowList windows = mFocusedApp.allAppWindows; 3749 for (int i = windows.size() - 1; i >= 0; --i) { 3750 final WindowState win = windows.get(i); 3751 final int animLayer = win.mWinAnimator.mAnimLayer; 3752 if (win.mAttachedWindow == null && win.isVisibleLw() && 3753 animLayer > mFocusedStackLayer) { 3754 mFocusedStackLayer = animLayer + LAYER_OFFSET_FOCUSED_STACK; 3755 } 3756 } 3757 } 3758 if (DEBUG_LAYERS) Slog.v(TAG, "Setting FocusedStackFrame to layer=" + 3759 mFocusedStackLayer); 3760 mFocusedStackFrame.setLayer(mFocusedStackLayer); 3761 } 3762 3763 void setFocusedStackFrame() { 3764 final TaskStack stack; 3765 if (mFocusedApp != null) { 3766 Task task = mTaskIdToTask.get(mFocusedApp.groupId); 3767 stack = task.mStack; 3768 task.getDisplayContent().setTouchExcludeRegion(stack); 3769 } else { 3770 stack = null; 3771 } 3772 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame"); 3773 SurfaceControl.openTransaction(); 3774 try { 3775 if (stack == null) { 3776 mFocusedStackFrame.setVisibility(false); 3777 } else { 3778 final StackBox box = stack.mStackBox; 3779 final Rect bounds = box.mBounds; 3780 final boolean multipleStacks = box.mParent != null; 3781 mFocusedStackFrame.setBounds(bounds); 3782 mFocusedStackFrame.setVisibility(multipleStacks); 3783 } 3784 } finally { 3785 SurfaceControl.closeTransaction(); 3786 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame"); 3787 } 3788 } 3789 3790 @Override 3791 public void setFocusedApp(IBinder token, boolean moveFocusNow) { 3792 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3793 "setFocusedApp()")) { 3794 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3795 } 3796 3797 synchronized(mWindowMap) { 3798 boolean changed = false; 3799 if (token == null) { 3800 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp); 3801 changed = mFocusedApp != null; 3802 mFocusedApp = null; 3803 if (changed) { 3804 mInputMonitor.setFocusedAppLw(null); 3805 } 3806 } else { 3807 AppWindowToken newFocus = findAppWindowToken(token); 3808 if (newFocus == null) { 3809 Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token); 3810 return; 3811 } 3812 changed = mFocusedApp != newFocus; 3813 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus 3814 + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow); 3815 mFocusedApp = newFocus; 3816 if (changed) { 3817 mInputMonitor.setFocusedAppLw(newFocus); 3818 } 3819 } 3820 3821 if (moveFocusNow && changed) { 3822 final long origId = Binder.clearCallingIdentity(); 3823 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 3824 Binder.restoreCallingIdentity(origId); 3825 } 3826 } 3827 } 3828 3829 @Override 3830 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) { 3831 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3832 "prepareAppTransition()")) { 3833 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3834 } 3835 3836 synchronized(mWindowMap) { 3837 if (DEBUG_APP_TRANSITIONS) Slog.v( 3838 TAG, "Prepare app transition: transit=" + transit 3839 + " " + mAppTransition 3840 + " alwaysKeepCurrent=" + alwaysKeepCurrent 3841 + " Callers=" + Debug.getCallers(3)); 3842 if (okToDisplay()) { 3843 if (!mAppTransition.isTransitionSet() || mAppTransition.isTransitionNone()) { 3844 mAppTransition.setAppTransition(transit); 3845 } else if (!alwaysKeepCurrent) { 3846 if (transit == AppTransition.TRANSIT_TASK_OPEN 3847 && mAppTransition.isTransitionEqual( 3848 AppTransition.TRANSIT_TASK_CLOSE)) { 3849 // Opening a new task always supersedes a close for the anim. 3850 mAppTransition.setAppTransition(transit); 3851 } else if (transit == AppTransition.TRANSIT_ACTIVITY_OPEN 3852 && mAppTransition.isTransitionEqual( 3853 AppTransition.TRANSIT_ACTIVITY_CLOSE)) { 3854 // Opening a new activity always supersedes a close for the anim. 3855 mAppTransition.setAppTransition(transit); 3856 } 3857 } 3858 mAppTransition.prepare(); 3859 mStartingIconInTransition = false; 3860 mSkipAppTransitionAnimation = false; 3861 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 3862 mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000); 3863 } 3864 } 3865 } 3866 3867 @Override 3868 public int getPendingAppTransition() { 3869 return mAppTransition.getAppTransition(); 3870 } 3871 3872 @Override 3873 public void overridePendingAppTransition(String packageName, 3874 int enterAnim, int exitAnim, IRemoteCallback startedCallback) { 3875 synchronized(mWindowMap) { 3876 mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim, 3877 startedCallback); 3878 } 3879 } 3880 3881 @Override 3882 public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, 3883 int startHeight) { 3884 synchronized(mWindowMap) { 3885 mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth, 3886 startHeight); 3887 } 3888 } 3889 3890 @Override 3891 public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, 3892 int startY, IRemoteCallback startedCallback, boolean scaleUp) { 3893 synchronized(mWindowMap) { 3894 mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY, 3895 startedCallback, scaleUp); 3896 } 3897 } 3898 3899 @Override 3900 public void executeAppTransition() { 3901 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3902 "executeAppTransition()")) { 3903 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3904 } 3905 3906 synchronized(mWindowMap) { 3907 if (DEBUG_APP_TRANSITIONS) { 3908 RuntimeException e = new RuntimeException("here"); 3909 e.fillInStackTrace(); 3910 Slog.w(TAG, "Execute app transition: " + mAppTransition, e); 3911 } 3912 if (mAppTransition.isTransitionSet()) { 3913 mAppTransition.setReady(); 3914 final long origId = Binder.clearCallingIdentity(); 3915 performLayoutAndPlaceSurfacesLocked(); 3916 Binder.restoreCallingIdentity(origId); 3917 } 3918 } 3919 } 3920 3921 @Override 3922 public void setAppStartingWindow(IBinder token, String pkg, 3923 int theme, CompatibilityInfo compatInfo, 3924 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, 3925 int windowFlags, IBinder transferFrom, boolean createIfNeeded) { 3926 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3927 "setAppStartingWindow()")) { 3928 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3929 } 3930 3931 synchronized(mWindowMap) { 3932 if (DEBUG_STARTING_WINDOW) Slog.v( 3933 TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg 3934 + " transferFrom=" + transferFrom); 3935 3936 AppWindowToken wtoken = findAppWindowToken(token); 3937 if (wtoken == null) { 3938 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token); 3939 return; 3940 } 3941 3942 // If the display is frozen, we won't do anything until the 3943 // actual window is displayed so there is no reason to put in 3944 // the starting window. 3945 if (!okToDisplay()) { 3946 return; 3947 } 3948 3949 if (wtoken.startingData != null) { 3950 return; 3951 } 3952 3953 if (transferFrom != null) { 3954 AppWindowToken ttoken = findAppWindowToken(transferFrom); 3955 if (ttoken != null) { 3956 WindowState startingWindow = ttoken.startingWindow; 3957 if (startingWindow != null) { 3958 if (mStartingIconInTransition) { 3959 // In this case, the starting icon has already 3960 // been displayed, so start letting windows get 3961 // shown immediately without any more transitions. 3962 mSkipAppTransitionAnimation = true; 3963 } 3964 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 3965 "Moving existing starting " + startingWindow + " from " + ttoken 3966 + " to " + wtoken); 3967 final long origId = Binder.clearCallingIdentity(); 3968 3969 // Transfer the starting window over to the new 3970 // token. 3971 wtoken.startingData = ttoken.startingData; 3972 wtoken.startingView = ttoken.startingView; 3973 wtoken.startingDisplayed = ttoken.startingDisplayed; 3974 ttoken.startingDisplayed = false; 3975 wtoken.startingWindow = startingWindow; 3976 wtoken.reportedVisible = ttoken.reportedVisible; 3977 ttoken.startingData = null; 3978 ttoken.startingView = null; 3979 ttoken.startingWindow = null; 3980 ttoken.startingMoved = true; 3981 startingWindow.mToken = wtoken; 3982 startingWindow.mRootToken = wtoken; 3983 startingWindow.mAppToken = wtoken; 3984 startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator; 3985 3986 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) { 3987 Slog.v(TAG, "Removing starting window: " + startingWindow); 3988 } 3989 removeStartingWindowTimeout(ttoken); 3990 startingWindow.getWindowList().remove(startingWindow); 3991 mWindowsChanged = true; 3992 if (DEBUG_ADD_REMOVE) Slog.v(TAG, 3993 "Removing starting " + startingWindow + " from " + ttoken); 3994 ttoken.windows.remove(startingWindow); 3995 ttoken.allAppWindows.remove(startingWindow); 3996 addWindowToListInOrderLocked(startingWindow, true); 3997 3998 // Propagate other interesting state between the 3999 // tokens. If the old token is displayed, we should 4000 // immediately force the new one to be displayed. If 4001 // it is animating, we need to move that animation to 4002 // the new one. 4003 if (ttoken.allDrawn) { 4004 wtoken.allDrawn = true; 4005 wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn; 4006 } 4007 if (ttoken.firstWindowDrawn) { 4008 wtoken.firstWindowDrawn = true; 4009 } 4010 if (!ttoken.hidden) { 4011 wtoken.hidden = false; 4012 wtoken.hiddenRequested = false; 4013 wtoken.willBeHidden = false; 4014 } 4015 if (wtoken.clientHidden != ttoken.clientHidden) { 4016 wtoken.clientHidden = ttoken.clientHidden; 4017 wtoken.sendAppVisibilityToClients(); 4018 } 4019 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4020 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4021 if (tAppAnimator.animation != null) { 4022 wAppAnimator.animation = tAppAnimator.animation; 4023 wAppAnimator.animating = tAppAnimator.animating; 4024 wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment; 4025 tAppAnimator.animation = null; 4026 tAppAnimator.animLayerAdjustment = 0; 4027 wAppAnimator.updateLayers(); 4028 tAppAnimator.updateLayers(); 4029 } 4030 4031 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4032 true /*updateInputWindows*/); 4033 getDefaultDisplayContentLocked().layoutNeeded = true; 4034 performLayoutAndPlaceSurfacesLocked(); 4035 Binder.restoreCallingIdentity(origId); 4036 return; 4037 } else if (ttoken.startingData != null) { 4038 // The previous app was getting ready to show a 4039 // starting window, but hasn't yet done so. Steal it! 4040 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4041 "Moving pending starting from " + ttoken 4042 + " to " + wtoken); 4043 wtoken.startingData = ttoken.startingData; 4044 ttoken.startingData = null; 4045 ttoken.startingMoved = true; 4046 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4047 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4048 // want to process the message ASAP, before any other queued 4049 // messages. 4050 mH.sendMessageAtFrontOfQueue(m); 4051 return; 4052 } 4053 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4054 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4055 if (tAppAnimator.thumbnail != null) { 4056 // The old token is animating with a thumbnail, transfer 4057 // that to the new token. 4058 if (wAppAnimator.thumbnail != null) { 4059 wAppAnimator.thumbnail.destroy(); 4060 } 4061 wAppAnimator.thumbnail = tAppAnimator.thumbnail; 4062 wAppAnimator.thumbnailX = tAppAnimator.thumbnailX; 4063 wAppAnimator.thumbnailY = tAppAnimator.thumbnailY; 4064 wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer; 4065 wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation; 4066 tAppAnimator.thumbnail = null; 4067 } 4068 } 4069 } 4070 4071 // There is no existing starting window, and the caller doesn't 4072 // want us to create one, so that's it! 4073 if (!createIfNeeded) { 4074 return; 4075 } 4076 4077 // If this is a translucent window, then don't 4078 // show a starting window -- the current effect (a full-screen 4079 // opaque starting window that fades away to the real contents 4080 // when it is ready) does not work for this. 4081 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x" 4082 + Integer.toHexString(theme)); 4083 if (theme != 0) { 4084 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme, 4085 com.android.internal.R.styleable.Window, mCurrentUserId); 4086 if (ent == null) { 4087 // Whoops! App doesn't exist. Um. Okay. We'll just 4088 // pretend like we didn't see that. 4089 return; 4090 } 4091 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent=" 4092 + ent.array.getBoolean( 4093 com.android.internal.R.styleable.Window_windowIsTranslucent, false) 4094 + " Floating=" 4095 + ent.array.getBoolean( 4096 com.android.internal.R.styleable.Window_windowIsFloating, false) 4097 + " ShowWallpaper=" 4098 + ent.array.getBoolean( 4099 com.android.internal.R.styleable.Window_windowShowWallpaper, false)); 4100 if (ent.array.getBoolean( 4101 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) { 4102 return; 4103 } 4104 if (ent.array.getBoolean( 4105 com.android.internal.R.styleable.Window_windowIsFloating, false)) { 4106 return; 4107 } 4108 if (ent.array.getBoolean( 4109 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) { 4110 if (mWallpaperTarget == null) { 4111 // If this theme is requesting a wallpaper, and the wallpaper 4112 // is not curently visible, then this effectively serves as 4113 // an opaque window and our starting window transition animation 4114 // can still work. We just need to make sure the starting window 4115 // is also showing the wallpaper. 4116 windowFlags |= FLAG_SHOW_WALLPAPER; 4117 } else { 4118 return; 4119 } 4120 } 4121 } 4122 4123 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData"); 4124 mStartingIconInTransition = true; 4125 wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel, 4126 labelRes, icon, logo, windowFlags); 4127 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4128 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4129 // want to process the message ASAP, before any other queued 4130 // messages. 4131 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING"); 4132 mH.sendMessageAtFrontOfQueue(m); 4133 } 4134 } 4135 4136 @Override 4137 public void setAppWillBeHidden(IBinder token) { 4138 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4139 "setAppWillBeHidden()")) { 4140 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4141 } 4142 4143 AppWindowToken wtoken; 4144 4145 synchronized(mWindowMap) { 4146 wtoken = findAppWindowToken(token); 4147 if (wtoken == null) { 4148 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token); 4149 return; 4150 } 4151 wtoken.willBeHidden = true; 4152 } 4153 } 4154 4155 public void setAppFullscreen(IBinder token, boolean toOpaque) { 4156 AppWindowToken atoken = findAppWindowToken(token); 4157 if (atoken != null) { 4158 atoken.appFullscreen = toOpaque; 4159 requestTraversal(); 4160 } 4161 } 4162 4163 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp, 4164 boolean visible, int transit, boolean performLayout) { 4165 boolean delayed = false; 4166 4167 if (wtoken.clientHidden == visible) { 4168 wtoken.clientHidden = !visible; 4169 wtoken.sendAppVisibilityToClients(); 4170 } 4171 4172 wtoken.willBeHidden = false; 4173 if (wtoken.hidden == visible) { 4174 boolean changed = false; 4175 if (DEBUG_APP_TRANSITIONS) Slog.v( 4176 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden 4177 + " performLayout=" + performLayout); 4178 4179 boolean runningAppAnimation = false; 4180 4181 if (transit != AppTransition.TRANSIT_UNSET) { 4182 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { 4183 wtoken.mAppAnimator.animation = null; 4184 } 4185 if (applyAnimationLocked(wtoken, lp, transit, visible)) { 4186 delayed = runningAppAnimation = true; 4187 } 4188 WindowState window = wtoken.findMainWindow(); 4189 //TODO (multidisplay): Magnification is supported only for the default display. 4190 if (window != null && mDisplayMagnifier != null 4191 && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 4192 mDisplayMagnifier.onAppWindowTransitionLocked(window, transit); 4193 } 4194 changed = true; 4195 } 4196 4197 final int N = wtoken.allAppWindows.size(); 4198 for (int i=0; i<N; i++) { 4199 WindowState win = wtoken.allAppWindows.get(i); 4200 if (win == wtoken.startingWindow) { 4201 continue; 4202 } 4203 4204 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible()); 4205 //win.dump(" "); 4206 if (visible) { 4207 if (!win.isVisibleNow()) { 4208 if (!runningAppAnimation) { 4209 win.mWinAnimator.applyAnimationLocked( 4210 WindowManagerPolicy.TRANSIT_ENTER, true); 4211 //TODO (multidisplay): Magnification is supported only for the default 4212 if (mDisplayMagnifier != null 4213 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4214 mDisplayMagnifier.onWindowTransitionLocked(win, 4215 WindowManagerPolicy.TRANSIT_ENTER); 4216 } 4217 } 4218 changed = true; 4219 win.mDisplayContent.layoutNeeded = true; 4220 } 4221 } else if (win.isVisibleNow()) { 4222 if (!runningAppAnimation) { 4223 win.mWinAnimator.applyAnimationLocked( 4224 WindowManagerPolicy.TRANSIT_EXIT, false); 4225 //TODO (multidisplay): Magnification is supported only for the default 4226 if (mDisplayMagnifier != null 4227 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4228 mDisplayMagnifier.onWindowTransitionLocked(win, 4229 WindowManagerPolicy.TRANSIT_EXIT); 4230 } 4231 } 4232 changed = true; 4233 win.mDisplayContent.layoutNeeded = true; 4234 } 4235 } 4236 4237 wtoken.hidden = wtoken.hiddenRequested = !visible; 4238 if (!visible) { 4239 unsetAppFreezingScreenLocked(wtoken, true, true); 4240 } else { 4241 // If we are being set visible, and the starting window is 4242 // not yet displayed, then make sure it doesn't get displayed. 4243 WindowState swin = wtoken.startingWindow; 4244 if (swin != null && !swin.isDrawnLw()) { 4245 swin.mPolicyVisibility = false; 4246 swin.mPolicyVisibilityAfterAnim = false; 4247 } 4248 } 4249 4250 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken 4251 + ": hidden=" + wtoken.hidden + " hiddenRequested=" 4252 + wtoken.hiddenRequested); 4253 4254 if (changed) { 4255 mInputMonitor.setUpdateInputWindowsNeededLw(); 4256 if (performLayout) { 4257 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4258 false /*updateInputWindows*/); 4259 performLayoutAndPlaceSurfacesLocked(); 4260 } 4261 mInputMonitor.updateInputWindowsLw(false /*force*/); 4262 } 4263 } 4264 4265 if (wtoken.mAppAnimator.animation != null) { 4266 delayed = true; 4267 } 4268 4269 for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) { 4270 if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) { 4271 delayed = true; 4272 } 4273 } 4274 4275 return delayed; 4276 } 4277 4278 @Override 4279 public void setAppVisibility(IBinder token, boolean visible) { 4280 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4281 "setAppVisibility()")) { 4282 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4283 } 4284 4285 AppWindowToken wtoken; 4286 4287 synchronized(mWindowMap) { 4288 wtoken = findAppWindowToken(token); 4289 if (wtoken == null) { 4290 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token); 4291 return; 4292 } 4293 4294 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) { 4295 RuntimeException e = null; 4296 if (!HIDE_STACK_CRAWLS) { 4297 e = new RuntimeException(); 4298 e.fillInStackTrace(); 4299 } 4300 Slog.v(TAG, "setAppVisibility(" + token + ", visible=" + visible 4301 + "): " + mAppTransition 4302 + " hidden=" + wtoken.hidden 4303 + " hiddenRequested=" + wtoken.hiddenRequested, e); 4304 } 4305 4306 // If we are preparing an app transition, then delay changing 4307 // the visibility of this token until we execute that transition. 4308 if (okToDisplay() && mAppTransition.isTransitionSet()) { 4309 // Already in requested state, don't do anything more. 4310 if (wtoken.hiddenRequested != visible) { 4311 return; 4312 } 4313 wtoken.hiddenRequested = !visible; 4314 4315 if (!wtoken.startingDisplayed) { 4316 if (DEBUG_APP_TRANSITIONS) Slog.v( 4317 TAG, "Setting dummy animation on: " + wtoken); 4318 wtoken.mAppAnimator.setDummyAnimation(); 4319 } 4320 mOpeningApps.remove(wtoken); 4321 mClosingApps.remove(wtoken); 4322 wtoken.waitingToShow = wtoken.waitingToHide = false; 4323 wtoken.inPendingTransaction = true; 4324 if (visible) { 4325 mOpeningApps.add(wtoken); 4326 wtoken.startingMoved = false; 4327 4328 // If the token is currently hidden (should be the 4329 // common case), then we need to set up to wait for 4330 // its windows to be ready. 4331 if (wtoken.hidden) { 4332 wtoken.allDrawn = false; 4333 wtoken.deferClearAllDrawn = false; 4334 wtoken.waitingToShow = true; 4335 4336 if (wtoken.clientHidden) { 4337 // In the case where we are making an app visible 4338 // but holding off for a transition, we still need 4339 // to tell the client to make its windows visible so 4340 // they get drawn. Otherwise, we will wait on 4341 // performing the transition until all windows have 4342 // been drawn, they never will be, and we are sad. 4343 wtoken.clientHidden = false; 4344 wtoken.sendAppVisibilityToClients(); 4345 } 4346 } 4347 } else { 4348 mClosingApps.add(wtoken); 4349 4350 // If the token is currently visible (should be the 4351 // common case), then set up to wait for it to be hidden. 4352 if (!wtoken.hidden) { 4353 wtoken.waitingToHide = true; 4354 } 4355 } 4356 return; 4357 } 4358 4359 final long origId = Binder.clearCallingIdentity(); 4360 setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET, 4361 true); 4362 wtoken.updateReportedVisibilityLocked(); 4363 Binder.restoreCallingIdentity(origId); 4364 } 4365 } 4366 4367 void unsetAppFreezingScreenLocked(AppWindowToken wtoken, 4368 boolean unfreezeSurfaceNow, boolean force) { 4369 if (wtoken.mAppAnimator.freezingScreen) { 4370 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken 4371 + " force=" + force); 4372 final int N = wtoken.allAppWindows.size(); 4373 boolean unfrozeWindows = false; 4374 for (int i=0; i<N; i++) { 4375 WindowState w = wtoken.allAppWindows.get(i); 4376 if (w.mAppFreezing) { 4377 w.mAppFreezing = false; 4378 if (w.mHasSurface && !w.mOrientationChanging) { 4379 if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w); 4380 w.mOrientationChanging = true; 4381 mInnerFields.mOrientationChangeComplete = false; 4382 } 4383 w.mLastFreezeDuration = 0; 4384 unfrozeWindows = true; 4385 w.mDisplayContent.layoutNeeded = true; 4386 } 4387 } 4388 if (force || unfrozeWindows) { 4389 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken); 4390 wtoken.mAppAnimator.freezingScreen = false; 4391 wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime() 4392 - mDisplayFreezeTime); 4393 mAppsFreezingScreen--; 4394 mLastFinishedFreezeSource = wtoken; 4395 } 4396 if (unfreezeSurfaceNow) { 4397 if (unfrozeWindows) { 4398 performLayoutAndPlaceSurfacesLocked(); 4399 } 4400 stopFreezingDisplayLocked(); 4401 } 4402 } 4403 } 4404 4405 public void startAppFreezingScreenLocked(AppWindowToken wtoken, 4406 int configChanges) { 4407 if (DEBUG_ORIENTATION) { 4408 RuntimeException e = null; 4409 if (!HIDE_STACK_CRAWLS) { 4410 e = new RuntimeException(); 4411 e.fillInStackTrace(); 4412 } 4413 Slog.i(TAG, "Set freezing of " + wtoken.appToken 4414 + ": hidden=" + wtoken.hidden + " freezing=" 4415 + wtoken.mAppAnimator.freezingScreen, e); 4416 } 4417 if (!wtoken.hiddenRequested) { 4418 if (!wtoken.mAppAnimator.freezingScreen) { 4419 wtoken.mAppAnimator.freezingScreen = true; 4420 wtoken.mAppAnimator.lastFreezeDuration = 0; 4421 mAppsFreezingScreen++; 4422 if (mAppsFreezingScreen == 1) { 4423 startFreezingDisplayLocked(false, 0, 0); 4424 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 4425 mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000); 4426 } 4427 } 4428 final int N = wtoken.allAppWindows.size(); 4429 for (int i=0; i<N; i++) { 4430 WindowState w = wtoken.allAppWindows.get(i); 4431 w.mAppFreezing = true; 4432 } 4433 } 4434 } 4435 4436 @Override 4437 public void startAppFreezingScreen(IBinder token, int configChanges) { 4438 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4439 "setAppFreezingScreen()")) { 4440 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4441 } 4442 4443 synchronized(mWindowMap) { 4444 if (configChanges == 0 && okToDisplay()) { 4445 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token); 4446 return; 4447 } 4448 4449 AppWindowToken wtoken = findAppWindowToken(token); 4450 if (wtoken == null || wtoken.appToken == null) { 4451 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken); 4452 return; 4453 } 4454 final long origId = Binder.clearCallingIdentity(); 4455 startAppFreezingScreenLocked(wtoken, configChanges); 4456 Binder.restoreCallingIdentity(origId); 4457 } 4458 } 4459 4460 @Override 4461 public void stopAppFreezingScreen(IBinder token, boolean force) { 4462 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4463 "setAppFreezingScreen()")) { 4464 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4465 } 4466 4467 synchronized(mWindowMap) { 4468 AppWindowToken wtoken = findAppWindowToken(token); 4469 if (wtoken == null || wtoken.appToken == null) { 4470 return; 4471 } 4472 final long origId = Binder.clearCallingIdentity(); 4473 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token 4474 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen); 4475 unsetAppFreezingScreenLocked(wtoken, true, force); 4476 Binder.restoreCallingIdentity(origId); 4477 } 4478 } 4479 4480 @Override 4481 public void removeAppToken(IBinder token) { 4482 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4483 "removeAppToken()")) { 4484 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4485 } 4486 4487 AppWindowToken wtoken = null; 4488 AppWindowToken startingToken = null; 4489 boolean delayed = false; 4490 4491 final long origId = Binder.clearCallingIdentity(); 4492 synchronized(mWindowMap) { 4493 WindowToken basewtoken = mTokenMap.remove(token); 4494 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) { 4495 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken); 4496 delayed = setTokenVisibilityLocked(wtoken, null, false, 4497 AppTransition.TRANSIT_UNSET, true); 4498 wtoken.inPendingTransaction = false; 4499 mOpeningApps.remove(wtoken); 4500 wtoken.waitingToShow = false; 4501 if (mClosingApps.contains(wtoken)) { 4502 delayed = true; 4503 } else if (mAppTransition.isTransitionSet()) { 4504 mClosingApps.add(wtoken); 4505 wtoken.waitingToHide = true; 4506 delayed = true; 4507 } 4508 if (DEBUG_APP_TRANSITIONS) Slog.v( 4509 TAG, "Removing app " + wtoken + " delayed=" + delayed 4510 + " animation=" + wtoken.mAppAnimator.animation 4511 + " animating=" + wtoken.mAppAnimator.animating); 4512 final Task task = mTaskIdToTask.get(wtoken.groupId); 4513 DisplayContent displayContent = task.getDisplayContent(); 4514 if (delayed) { 4515 // set the token aside because it has an active animation to be finished 4516 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4517 "removeAppToken make exiting: " + wtoken); 4518 displayContent.mExitingAppTokens.add(wtoken); 4519 } else { 4520 // Make sure there is no animation running on this token, 4521 // so any windows associated with it will be removed as 4522 // soon as their animations are complete 4523 wtoken.mAppAnimator.clearAnimation(); 4524 wtoken.mAppAnimator.animating = false; 4525 } 4526 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4527 "removeAppToken: " + wtoken); 4528 4529 if (task.removeAppToken(wtoken)) { 4530 mTaskIdToTask.delete(wtoken.groupId); 4531 } 4532 wtoken.removed = true; 4533 if (wtoken.startingData != null) { 4534 startingToken = wtoken; 4535 } 4536 unsetAppFreezingScreenLocked(wtoken, true, true); 4537 if (mFocusedApp == wtoken) { 4538 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Removing focused app token:" + wtoken); 4539 mFocusedApp = null; 4540 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 4541 mInputMonitor.setFocusedAppLw(null); 4542 } 4543 } else { 4544 Slog.w(TAG, "Attempted to remove non-existing app token: " + token); 4545 } 4546 4547 if (!delayed && wtoken != null) { 4548 wtoken.updateReportedVisibilityLocked(); 4549 } 4550 } 4551 Binder.restoreCallingIdentity(origId); 4552 4553 // Will only remove if startingToken non null. 4554 scheduleRemoveStartingWindow(startingToken); 4555 } 4556 4557 void removeStartingWindowTimeout(AppWindowToken wtoken) { 4558 if (wtoken != null) { 4559 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) + 4560 ": Remove starting window timeout " + wtoken + (wtoken != null ? 4561 " startingWindow=" + wtoken.startingWindow : "")); 4562 mH.removeMessages(H.REMOVE_STARTING_TIMEOUT, wtoken); 4563 } 4564 } 4565 4566 void scheduleRemoveStartingWindow(AppWindowToken wtoken) { 4567 if (wtoken != null && wtoken.startingWindow != null) { 4568 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) + 4569 ": Schedule remove starting " + wtoken + (wtoken != null ? 4570 " startingWindow=" + wtoken.startingWindow : "")); 4571 removeStartingWindowTimeout(wtoken); 4572 Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken); 4573 mH.sendMessage(m); 4574 } 4575 } 4576 private boolean tmpRemoveAppWindowsLocked(WindowToken token) { 4577 final int NW = token.windows.size(); 4578 if (NW > 0) { 4579 mWindowsChanged = true; 4580 } 4581 for (int i=0; i<NW; i++) { 4582 WindowState win = token.windows.get(i); 4583 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win); 4584 win.getWindowList().remove(win); 4585 int j = win.mChildWindows.size(); 4586 while (j > 0) { 4587 j--; 4588 WindowState cwin = win.mChildWindows.get(j); 4589 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 4590 "Tmp removing child window " + cwin); 4591 cwin.getWindowList().remove(cwin); 4592 } 4593 } 4594 return NW > 0; 4595 } 4596 4597 void dumpAppTokensLocked() { 4598 final int numDisplays = mDisplayContents.size(); 4599 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 4600 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 4601 Slog.v(TAG, " Display " + displayContent.getDisplayId()); 4602 final ArrayList<Task> tasks = displayContent.getTasks(); 4603 int i = displayContent.numTokens(); 4604 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 4605 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 4606 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 4607 final AppWindowToken wtoken = tokens.get(tokenNdx); 4608 Slog.v(TAG, " #" + --i + ": " + wtoken.token); 4609 } 4610 } 4611 } 4612 } 4613 4614 void dumpWindowsLocked() { 4615 int i = 0; 4616 final int numDisplays = mDisplayContents.size(); 4617 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 4618 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 4619 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 4620 Slog.v(TAG, " #" + i++ + ": " + windows.get(winNdx)); 4621 } 4622 } 4623 } 4624 4625 private int findAppWindowInsertionPointLocked(AppWindowToken target) { 4626 final int taskId = target.groupId; 4627 Task targetTask = mTaskIdToTask.get(taskId); 4628 if (targetTask == null) { 4629 Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId=" 4630 + taskId); 4631 return 0; 4632 } 4633 DisplayContent displayContent = targetTask.getDisplayContent(); 4634 if (displayContent == null) { 4635 Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target); 4636 return 0; 4637 } 4638 final WindowList windows = displayContent.getWindowList(); 4639 final int NW = windows.size(); 4640 4641 boolean found = false; 4642 final ArrayList<Task> tasks = displayContent.getTasks(); 4643 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 4644 final Task task = tasks.get(taskNdx); 4645 if (!found && task.taskId != taskId) { 4646 continue; 4647 } 4648 AppTokenList tokens = task.mAppTokens; 4649 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 4650 final AppWindowToken wtoken = tokens.get(tokenNdx); 4651 if (!found && wtoken == target) { 4652 found = true; 4653 } 4654 if (found) { 4655 // Find the first app token below the new position that has 4656 // a window displayed. 4657 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token); 4658 if (wtoken.sendingToBottom) { 4659 if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom"); 4660 continue; 4661 } 4662 for (int i = wtoken.windows.size() - 1; i >= 0; --i) { 4663 WindowState win = wtoken.windows.get(i); 4664 for (int j = win.mChildWindows.size() - 1; j >= 0; --j) { 4665 WindowState cwin = win.mChildWindows.get(j); 4666 if (cwin.mSubLayer >= 0) { 4667 for (int pos = NW - 1; pos >= 0; pos--) { 4668 if (windows.get(pos) == cwin) { 4669 if (DEBUG_REORDER) Slog.v(TAG, 4670 "Found child win @" + (pos + 1)); 4671 return pos + 1; 4672 } 4673 } 4674 } 4675 } 4676 for (int pos = NW - 1; pos >= 0; pos--) { 4677 if (windows.get(pos) == win) { 4678 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1)); 4679 return pos + 1; 4680 } 4681 } 4682 } 4683 } 4684 } 4685 } 4686 // Never put an app window underneath wallpaper. 4687 for (int pos = NW - 1; pos >= 0; pos--) { 4688 if (windows.get(pos).mIsWallpaper) { 4689 if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos); 4690 return pos + 1; 4691 } 4692 } 4693 return 0; 4694 } 4695 4696 private final int reAddWindowLocked(int index, WindowState win) { 4697 final WindowList windows = win.getWindowList(); 4698 final int NCW = win.mChildWindows.size(); 4699 boolean added = false; 4700 for (int j=0; j<NCW; j++) { 4701 WindowState cwin = win.mChildWindows.get(j); 4702 if (!added && cwin.mSubLayer >= 0) { 4703 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at " 4704 + index + ": " + cwin); 4705 win.mRebuilding = false; 4706 windows.add(index, win); 4707 index++; 4708 added = true; 4709 } 4710 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4711 + index + ": " + cwin); 4712 cwin.mRebuilding = false; 4713 windows.add(index, cwin); 4714 index++; 4715 } 4716 if (!added) { 4717 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4718 + index + ": " + win); 4719 win.mRebuilding = false; 4720 windows.add(index, win); 4721 index++; 4722 } 4723 mWindowsChanged = true; 4724 return index; 4725 } 4726 4727 private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index, 4728 WindowToken token) { 4729 final int NW = token.windows.size(); 4730 for (int i=0; i<NW; i++) { 4731 final WindowState win = token.windows.get(i); 4732 if (win.mDisplayContent == displayContent) { 4733 index = reAddWindowLocked(index, win); 4734 } 4735 } 4736 return index; 4737 } 4738 4739 void moveStackWindowsLocked(DisplayContent displayContent) { 4740 // First remove all of the windows from the list. 4741 final ArrayList<Task> tasks = displayContent.getTasks(); 4742 final int numTasks = tasks.size(); 4743 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4744 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 4745 final int numTokens = tokens.size(); 4746 for (int tokenNdx = numTokens - 1; tokenNdx >= 0; --tokenNdx) { 4747 tmpRemoveAppWindowsLocked(tokens.get(tokenNdx)); 4748 } 4749 } 4750 4751 // And now add them back at the correct place. 4752 // Where to start adding? 4753 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4754 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 4755 int pos = findAppWindowInsertionPointLocked(tokens.get(0)); 4756 final int numTokens = tokens.size(); 4757 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 4758 final AppWindowToken wtoken = tokens.get(tokenNdx); 4759 if (wtoken != null) { 4760 final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken); 4761 if (newPos != pos) { 4762 displayContent.layoutNeeded = true; 4763 } 4764 pos = newPos; 4765 } 4766 } 4767 } 4768 4769 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4770 false /*updateInputWindows*/)) { 4771 assignLayersLocked(displayContent.getWindowList()); 4772 } 4773 4774 mInputMonitor.setUpdateInputWindowsNeededLw(); 4775 performLayoutAndPlaceSurfacesLocked(); 4776 mInputMonitor.updateInputWindowsLw(false /*force*/); 4777 4778 //dump(); 4779 } 4780 4781 public void moveTaskToTop(int taskId) { 4782 final long origId = Binder.clearCallingIdentity(); 4783 try { 4784 synchronized(mWindowMap) { 4785 Task task = mTaskIdToTask.get(taskId); 4786 if (task == null) { 4787 // Normal behavior, addAppToken will be called next and task will be created. 4788 return; 4789 } 4790 final TaskStack stack = task.mStack; 4791 final DisplayContent displayContent = task.getDisplayContent(); 4792 final boolean isHomeStackTask = stack.isHomeStack(); 4793 if (isHomeStackTask != displayContent.homeOnTop()) { 4794 // First move the stack itself. 4795 displayContent.moveHomeStackBox(isHomeStackTask); 4796 } 4797 stack.moveTaskToTop(task); 4798 displayContent.moveStack(stack, true); 4799 } 4800 } finally { 4801 Binder.restoreCallingIdentity(origId); 4802 } 4803 } 4804 4805 public void moveTaskToBottom(int taskId) { 4806 final long origId = Binder.clearCallingIdentity(); 4807 try { 4808 synchronized(mWindowMap) { 4809 Task task = mTaskIdToTask.get(taskId); 4810 if (task == null) { 4811 Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId 4812 + " not found in mTaskIdToTask"); 4813 return; 4814 } 4815 final TaskStack stack = task.mStack; 4816 stack.moveTaskToBottom(task); 4817 moveStackWindowsLocked(stack.getDisplayContent()); 4818 } 4819 } finally { 4820 Binder.restoreCallingIdentity(origId); 4821 } 4822 } 4823 4824 /** 4825 * Create a new TaskStack and place it next to an existing stack. 4826 * @param stackId The unique identifier of the new stack. 4827 * @param relativeStackBoxId The existing stack that this stack goes before or after. 4828 * @param position One of: 4829 * {@link StackBox#TASK_STACK_GOES_BEFORE} 4830 * {@link StackBox#TASK_STACK_GOES_AFTER} 4831 * {@link StackBox#TASK_STACK_GOES_ABOVE} 4832 * {@link StackBox#TASK_STACK_GOES_BELOW} 4833 * {@link StackBox#TASK_STACK_GOES_UNDER} 4834 * {@link StackBox#TASK_STACK_GOES_OVER} 4835 * @param weight Relative weight for determining how big to make the new TaskStack. 4836 */ 4837 public void createStack(int stackId, int relativeStackBoxId, int position, float weight) { 4838 synchronized (mWindowMap) { 4839 if (position <= StackBox.TASK_STACK_GOES_BELOW && 4840 (weight < STACK_WEIGHT_MIN || weight > STACK_WEIGHT_MAX)) { 4841 throw new IllegalArgumentException( 4842 "createStack: weight must be between " + STACK_WEIGHT_MIN + " and " + 4843 STACK_WEIGHT_MAX + ", weight=" + weight); 4844 } 4845 final int numDisplays = mDisplayContents.size(); 4846 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 4847 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 4848 TaskStack stack = displayContent.createStack(stackId, relativeStackBoxId, position, 4849 weight); 4850 if (stack != null) { 4851 mStackIdToStack.put(stackId, stack); 4852 displayContent.moveStack(stack, true); 4853 performLayoutAndPlaceSurfacesLocked(); 4854 return; 4855 } 4856 } 4857 Slog.e(TAG, "createStack: Unable to find relativeStackBoxId=" + relativeStackBoxId); 4858 } 4859 } 4860 4861 public int removeStack(int stackId) { 4862 synchronized (mWindowMap) { 4863 final TaskStack stack = mStackIdToStack.get(stackId); 4864 if (stack != null) { 4865 mStackIdToStack.delete(stackId); 4866 int nextStackId = stack.remove(); 4867 stack.getDisplayContent().layoutNeeded = true; 4868 requestTraversalLocked(); 4869 return nextStackId; 4870 } 4871 if (DEBUG_STACK) Slog.i(TAG, "removeStack: could not find stackId=" + stackId); 4872 } 4873 return HOME_STACK_ID; 4874 } 4875 4876 public void removeTask(int taskId) { 4877 synchronized (mWindowMap) { 4878 Task task = mTaskIdToTask.get(taskId); 4879 if (task == null) { 4880 if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId); 4881 return; 4882 } 4883 final TaskStack stack = task.mStack; 4884 stack.removeTask(task); 4885 stack.getDisplayContent().layoutNeeded = true; 4886 } 4887 } 4888 4889 public void addTask(int taskId, int stackId, boolean toTop) { 4890 synchronized (mWindowMap) { 4891 Task task = mTaskIdToTask.get(taskId); 4892 if (task == null) { 4893 return; 4894 } 4895 TaskStack stack = mStackIdToStack.get(stackId); 4896 stack.addTask(task, toTop); 4897 final DisplayContent displayContent = stack.getDisplayContent(); 4898 displayContent.layoutNeeded = true; 4899 performLayoutAndPlaceSurfacesLocked(); 4900 } 4901 } 4902 4903 public void resizeStackBox(int stackBoxId, float weight) { 4904 if (weight < STACK_WEIGHT_MIN || weight > STACK_WEIGHT_MAX) { 4905 throw new IllegalArgumentException( 4906 "resizeStack: weight must be between " + STACK_WEIGHT_MIN + " and " + 4907 STACK_WEIGHT_MAX + ", weight=" + weight); 4908 } 4909 synchronized (mWindowMap) { 4910 final int numDisplays = mDisplayContents.size(); 4911 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 4912 if (mDisplayContents.valueAt(displayNdx).resizeStack(stackBoxId, weight)) { 4913 performLayoutAndPlaceSurfacesLocked(); 4914 return; 4915 } 4916 } 4917 } 4918 throw new IllegalArgumentException("resizeStack: stackBoxId " + stackBoxId 4919 + " not found."); 4920 } 4921 4922 public ArrayList<StackBoxInfo> getStackBoxInfos() { 4923 synchronized(mWindowMap) { 4924 return getDefaultDisplayContentLocked().getStackBoxInfos(); 4925 } 4926 } 4927 4928 public Rect getStackBounds(int stackId) { 4929 final int numDisplays = mDisplayContents.size(); 4930 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 4931 Rect bounds = mDisplayContents.valueAt(displayNdx).getStackBounds(stackId); 4932 if (bounds != null) { 4933 return bounds; 4934 } 4935 } 4936 return null; 4937 } 4938 4939 // ------------------------------------------------------------- 4940 // Misc IWindowSession methods 4941 // ------------------------------------------------------------- 4942 4943 @Override 4944 public void startFreezingScreen(int exitAnim, int enterAnim) { 4945 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 4946 "startFreezingScreen()")) { 4947 throw new SecurityException("Requires FREEZE_SCREEN permission"); 4948 } 4949 4950 synchronized(mWindowMap) { 4951 if (!mClientFreezingScreen) { 4952 mClientFreezingScreen = true; 4953 final long origId = Binder.clearCallingIdentity(); 4954 try { 4955 startFreezingDisplayLocked(false, exitAnim, enterAnim); 4956 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 4957 mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000); 4958 } finally { 4959 Binder.restoreCallingIdentity(origId); 4960 } 4961 } 4962 } 4963 } 4964 4965 @Override 4966 public void stopFreezingScreen() { 4967 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 4968 "stopFreezingScreen()")) { 4969 throw new SecurityException("Requires FREEZE_SCREEN permission"); 4970 } 4971 4972 synchronized(mWindowMap) { 4973 if (mClientFreezingScreen) { 4974 mClientFreezingScreen = false; 4975 mLastFinishedFreezeSource = "client"; 4976 final long origId = Binder.clearCallingIdentity(); 4977 try { 4978 stopFreezingDisplayLocked(); 4979 } finally { 4980 Binder.restoreCallingIdentity(origId); 4981 } 4982 } 4983 } 4984 } 4985 4986 @Override 4987 public void disableKeyguard(IBinder token, String tag) { 4988 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 4989 != PackageManager.PERMISSION_GRANTED) { 4990 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 4991 } 4992 4993 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 4994 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag))); 4995 } 4996 4997 @Override 4998 public void reenableKeyguard(IBinder token) { 4999 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5000 != PackageManager.PERMISSION_GRANTED) { 5001 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5002 } 5003 5004 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5005 KeyguardDisableHandler.KEYGUARD_REENABLE, token)); 5006 } 5007 5008 /** 5009 * @see android.app.KeyguardManager#exitKeyguardSecurely 5010 */ 5011 @Override 5012 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) { 5013 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5014 != PackageManager.PERMISSION_GRANTED) { 5015 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5016 } 5017 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() { 5018 @Override 5019 public void onKeyguardExitResult(boolean success) { 5020 try { 5021 callback.onKeyguardExitResult(success); 5022 } catch (RemoteException e) { 5023 // Client has died, we don't care. 5024 } 5025 } 5026 }); 5027 } 5028 5029 @Override 5030 public boolean inKeyguardRestrictedInputMode() { 5031 return mPolicy.inKeyguardRestrictedKeyInputMode(); 5032 } 5033 5034 @Override 5035 public boolean isKeyguardLocked() { 5036 return mPolicy.isKeyguardLocked(); 5037 } 5038 5039 @Override 5040 public boolean isKeyguardSecure() { 5041 return mPolicy.isKeyguardSecure(); 5042 } 5043 5044 @Override 5045 public void dismissKeyguard() { 5046 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5047 != PackageManager.PERMISSION_GRANTED) { 5048 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5049 } 5050 synchronized(mWindowMap) { 5051 mPolicy.dismissKeyguardLw(); 5052 } 5053 } 5054 5055 @Override 5056 public void closeSystemDialogs(String reason) { 5057 synchronized(mWindowMap) { 5058 final int numDisplays = mDisplayContents.size(); 5059 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5060 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5061 final int numWindows = windows.size(); 5062 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5063 final WindowState w = windows.get(winNdx); 5064 if (w.mHasSurface) { 5065 try { 5066 w.mClient.closeSystemDialogs(reason); 5067 } catch (RemoteException e) { 5068 } 5069 } 5070 } 5071 } 5072 } 5073 } 5074 5075 static float fixScale(float scale) { 5076 if (scale < 0) scale = 0; 5077 else if (scale > 20) scale = 20; 5078 return Math.abs(scale); 5079 } 5080 5081 @Override 5082 public void setAnimationScale(int which, float scale) { 5083 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5084 "setAnimationScale()")) { 5085 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5086 } 5087 5088 scale = fixScale(scale); 5089 switch (which) { 5090 case 0: mWindowAnimationScale = scale; break; 5091 case 1: mTransitionAnimationScale = scale; break; 5092 case 2: mAnimatorDurationScale = scale; break; 5093 } 5094 5095 // Persist setting 5096 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5097 } 5098 5099 @Override 5100 public void setAnimationScales(float[] scales) { 5101 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5102 "setAnimationScale()")) { 5103 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5104 } 5105 5106 if (scales != null) { 5107 if (scales.length >= 1) { 5108 mWindowAnimationScale = fixScale(scales[0]); 5109 } 5110 if (scales.length >= 2) { 5111 mTransitionAnimationScale = fixScale(scales[1]); 5112 } 5113 if (scales.length >= 3) { 5114 setAnimatorDurationScale(fixScale(scales[2])); 5115 } 5116 } 5117 5118 // Persist setting 5119 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5120 } 5121 5122 private void setAnimatorDurationScale(float scale) { 5123 mAnimatorDurationScale = scale; 5124 ValueAnimator.setDurationScale(scale); 5125 } 5126 5127 @Override 5128 public float getAnimationScale(int which) { 5129 switch (which) { 5130 case 0: return mWindowAnimationScale; 5131 case 1: return mTransitionAnimationScale; 5132 case 2: return mAnimatorDurationScale; 5133 } 5134 return 0; 5135 } 5136 5137 @Override 5138 public float[] getAnimationScales() { 5139 return new float[] { mWindowAnimationScale, mTransitionAnimationScale, 5140 mAnimatorDurationScale }; 5141 } 5142 5143 @Override 5144 public void registerPointerEventListener(PointerEventListener listener) { 5145 mPointerEventDispatcher.registerInputEventListener(listener); 5146 } 5147 5148 @Override 5149 public void unregisterPointerEventListener(PointerEventListener listener) { 5150 mPointerEventDispatcher.unregisterInputEventListener(listener); 5151 } 5152 5153 // Called by window manager policy. Not exposed externally. 5154 @Override 5155 public int getLidState() { 5156 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 5157 InputManagerService.SW_LID); 5158 if (sw > 0) { 5159 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 5160 return LID_CLOSED; 5161 } else if (sw == 0) { 5162 // Switch state: AKEY_STATE_UP. 5163 return LID_OPEN; 5164 } else { 5165 // Switch state: AKEY_STATE_UNKNOWN. 5166 return LID_ABSENT; 5167 } 5168 } 5169 5170 // Called by window manager policy. Not exposed externally. 5171 @Override 5172 public void switchKeyboardLayout(int deviceId, int direction) { 5173 mInputManager.switchKeyboardLayout(deviceId, direction); 5174 } 5175 5176 // Called by window manager policy. Not exposed externally. 5177 @Override 5178 public void shutdown(boolean confirm) { 5179 ShutdownThread.shutdown(mContext, confirm); 5180 } 5181 5182 // Called by window manager policy. Not exposed externally. 5183 @Override 5184 public void rebootSafeMode(boolean confirm) { 5185 ShutdownThread.rebootSafeMode(mContext, confirm); 5186 } 5187 5188 @Override 5189 public void setInputFilter(IInputFilter filter) { 5190 if (!checkCallingPermission(android.Manifest.permission.FILTER_EVENTS, "setInputFilter()")) { 5191 throw new SecurityException("Requires FILTER_EVENTS permission"); 5192 } 5193 mInputManager.setInputFilter(filter); 5194 } 5195 5196 @Override 5197 public void setTouchExplorationEnabled(boolean enabled) { 5198 mPolicy.setTouchExplorationEnabled(enabled); 5199 } 5200 5201 public void setCurrentUser(final int newUserId) { 5202 synchronized (mWindowMap) { 5203 int oldUserId = mCurrentUserId; 5204 mCurrentUserId = newUserId; 5205 mAppTransition.setCurrentUser(newUserId); 5206 mPolicy.setCurrentUserLw(newUserId); 5207 5208 // Hide windows that should not be seen by the new user. 5209 final int numDisplays = mDisplayContents.size(); 5210 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5211 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 5212 displayContent.switchUserStacks(oldUserId, newUserId); 5213 rebuildAppWindowListLocked(displayContent); 5214 } 5215 performLayoutAndPlaceSurfacesLocked(); 5216 } 5217 } 5218 5219 public void enableScreenAfterBoot() { 5220 synchronized(mWindowMap) { 5221 if (DEBUG_BOOT) { 5222 RuntimeException here = new RuntimeException("here"); 5223 here.fillInStackTrace(); 5224 Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled 5225 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5226 + " mShowingBootMessages=" + mShowingBootMessages 5227 + " mSystemBooted=" + mSystemBooted, here); 5228 } 5229 if (mSystemBooted) { 5230 return; 5231 } 5232 mSystemBooted = true; 5233 hideBootMessagesLocked(); 5234 // If the screen still doesn't come up after 30 seconds, give 5235 // up and turn it on. 5236 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000); 5237 } 5238 5239 mPolicy.systemBooted(); 5240 5241 performEnableScreen(); 5242 } 5243 5244 void enableScreenIfNeededLocked() { 5245 if (DEBUG_BOOT) { 5246 RuntimeException here = new RuntimeException("here"); 5247 here.fillInStackTrace(); 5248 Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled 5249 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5250 + " mShowingBootMessages=" + mShowingBootMessages 5251 + " mSystemBooted=" + mSystemBooted, here); 5252 } 5253 if (mDisplayEnabled) { 5254 return; 5255 } 5256 if (!mSystemBooted && !mShowingBootMessages) { 5257 return; 5258 } 5259 mH.sendEmptyMessage(H.ENABLE_SCREEN); 5260 } 5261 5262 public void performBootTimeout() { 5263 synchronized(mWindowMap) { 5264 if (mDisplayEnabled || mHeadless) { 5265 return; 5266 } 5267 Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled"); 5268 mForceDisplayEnabled = true; 5269 } 5270 performEnableScreen(); 5271 } 5272 5273 public void performEnableScreen() { 5274 synchronized(mWindowMap) { 5275 if (DEBUG_BOOT) { 5276 RuntimeException here = new RuntimeException("here"); 5277 here.fillInStackTrace(); 5278 Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled 5279 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5280 + " mShowingBootMessages=" + mShowingBootMessages 5281 + " mSystemBooted=" + mSystemBooted 5282 + " mOnlyCore=" + mOnlyCore, here); 5283 } 5284 if (mDisplayEnabled) { 5285 return; 5286 } 5287 if (!mSystemBooted && !mShowingBootMessages) { 5288 return; 5289 } 5290 5291 if (!mForceDisplayEnabled) { 5292 // Don't enable the screen until all existing windows 5293 // have been drawn. 5294 boolean haveBootMsg = false; 5295 boolean haveApp = false; 5296 // if the wallpaper service is disabled on the device, we're never going to have 5297 // wallpaper, don't bother waiting for it 5298 boolean haveWallpaper = false; 5299 boolean wallpaperEnabled = mContext.getResources().getBoolean( 5300 com.android.internal.R.bool.config_enableWallpaperService) 5301 && !mOnlyCore; 5302 boolean haveKeyguard = true; 5303 // TODO(multidisplay): Expand to all displays? 5304 final WindowList windows = getDefaultWindowListLocked(); 5305 final int N = windows.size(); 5306 for (int i=0; i<N; i++) { 5307 WindowState w = windows.get(i); 5308 if (w.mAttrs.type == TYPE_KEYGUARD) { 5309 // Only if there is a keyguard attached to the window manager 5310 // will we consider ourselves as having a keyguard. If it 5311 // isn't attached, we don't know if it wants to be shown or 5312 // hidden. If it is attached, we will say we have a keyguard 5313 // if the window doesn't want to be visible, because in that 5314 // case it explicitly doesn't want to be shown so we should 5315 // not delay turning the screen on for it. 5316 boolean vis = w.mViewVisibility == View.VISIBLE 5317 && w.mPolicyVisibility; 5318 haveKeyguard = !vis; 5319 } 5320 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 5321 return; 5322 } 5323 if (w.isDrawnLw()) { 5324 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { 5325 haveBootMsg = true; 5326 } else if (w.mAttrs.type == TYPE_APPLICATION) { 5327 haveApp = true; 5328 } else if (w.mAttrs.type == TYPE_WALLPAPER) { 5329 haveWallpaper = true; 5330 } else if (w.mAttrs.type == TYPE_KEYGUARD) { 5331 haveKeyguard = true; 5332 } 5333 } 5334 } 5335 5336 if (DEBUG_SCREEN_ON || DEBUG_BOOT) { 5337 Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages 5338 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp 5339 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled 5340 + " haveKeyguard=" + haveKeyguard); 5341 } 5342 5343 // If we are turning on the screen to show the boot message, 5344 // don't do it until the boot message is actually displayed. 5345 if (!mSystemBooted && !haveBootMsg) { 5346 return; 5347 } 5348 5349 // If we are turning on the screen after the boot is completed 5350 // normally, don't do so until we have the application and 5351 // wallpaper. 5352 if (mSystemBooted && ((!haveApp && !haveKeyguard) || 5353 (wallpaperEnabled && !haveWallpaper))) { 5354 return; 5355 } 5356 } 5357 5358 mDisplayEnabled = true; 5359 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!"); 5360 if (false) { 5361 StringWriter sw = new StringWriter(); 5362 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 5363 this.dump(null, pw, null); 5364 pw.flush(); 5365 Slog.i(TAG, sw.toString()); 5366 } 5367 try { 5368 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); 5369 if (surfaceFlinger != null) { 5370 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); 5371 Parcel data = Parcel.obtain(); 5372 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 5373 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED 5374 data, null, 0); 5375 data.recycle(); 5376 } 5377 } catch (RemoteException ex) { 5378 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); 5379 } 5380 5381 // Enable input dispatch. 5382 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled); 5383 } 5384 5385 mPolicy.enableScreenAfterBoot(); 5386 5387 // Make sure the last requested orientation has been applied. 5388 updateRotationUnchecked(false, false); 5389 } 5390 5391 public void showBootMessage(final CharSequence msg, final boolean always) { 5392 boolean first = false; 5393 synchronized(mWindowMap) { 5394 if (DEBUG_BOOT) { 5395 RuntimeException here = new RuntimeException("here"); 5396 here.fillInStackTrace(); 5397 Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always 5398 + " mAllowBootMessages=" + mAllowBootMessages 5399 + " mShowingBootMessages=" + mShowingBootMessages 5400 + " mSystemBooted=" + mSystemBooted, here); 5401 } 5402 if (!mAllowBootMessages) { 5403 return; 5404 } 5405 if (!mShowingBootMessages) { 5406 if (!always) { 5407 return; 5408 } 5409 first = true; 5410 } 5411 if (mSystemBooted) { 5412 return; 5413 } 5414 mShowingBootMessages = true; 5415 mPolicy.showBootMessage(msg, always); 5416 } 5417 if (first) { 5418 performEnableScreen(); 5419 } 5420 } 5421 5422 public void hideBootMessagesLocked() { 5423 if (DEBUG_BOOT) { 5424 RuntimeException here = new RuntimeException("here"); 5425 here.fillInStackTrace(); 5426 Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled 5427 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5428 + " mShowingBootMessages=" + mShowingBootMessages 5429 + " mSystemBooted=" + mSystemBooted, here); 5430 } 5431 if (mShowingBootMessages) { 5432 mShowingBootMessages = false; 5433 mPolicy.hideBootMessages(); 5434 } 5435 } 5436 5437 @Override 5438 public void setInTouchMode(boolean mode) { 5439 synchronized(mWindowMap) { 5440 mInTouchMode = mode; 5441 } 5442 } 5443 5444 // TODO: more accounting of which pid(s) turned it on, keep count, 5445 // only allow disables from pids which have count on, etc. 5446 @Override 5447 public void showStrictModeViolation(boolean on) { 5448 if (mHeadless) return; 5449 int pid = Binder.getCallingPid(); 5450 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid)); 5451 } 5452 5453 private void showStrictModeViolation(int arg, int pid) { 5454 final boolean on = arg != 0; 5455 synchronized(mWindowMap) { 5456 // Ignoring requests to enable the red border from clients 5457 // which aren't on screen. (e.g. Broadcast Receivers in 5458 // the background..) 5459 if (on) { 5460 boolean isVisible = false; 5461 final int numDisplays = mDisplayContents.size(); 5462 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5463 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5464 final int numWindows = windows.size(); 5465 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5466 final WindowState ws = windows.get(winNdx); 5467 if (ws.mSession.mPid == pid && ws.isVisibleLw()) { 5468 isVisible = true; 5469 break; 5470 } 5471 } 5472 } 5473 if (!isVisible) { 5474 return; 5475 } 5476 } 5477 5478 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5479 ">>> OPEN TRANSACTION showStrictModeViolation"); 5480 SurfaceControl.openTransaction(); 5481 try { 5482 // TODO(multi-display): support multiple displays 5483 if (mStrictModeFlash == null) { 5484 mStrictModeFlash = new StrictModeFlash( 5485 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 5486 } 5487 mStrictModeFlash.setVisibility(on); 5488 } finally { 5489 SurfaceControl.closeTransaction(); 5490 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5491 "<<< CLOSE TRANSACTION showStrictModeViolation"); 5492 } 5493 } 5494 } 5495 5496 @Override 5497 public void setStrictModeVisualIndicatorPreference(String value) { 5498 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 5499 } 5500 5501 /** 5502 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 5503 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 5504 * of the target image. 5505 * 5506 * @param displayId the Display to take a screenshot of. 5507 * @param width the width of the target bitmap 5508 * @param height the height of the target bitmap 5509 * @param force565 if true the returned bitmap will be RGB_565, otherwise it 5510 * will be the same config as the surface 5511 */ 5512 @Override 5513 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, 5514 int height, boolean force565) { 5515 if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, 5516 "screenshotApplications()")) { 5517 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 5518 } 5519 5520 Bitmap rawss = null; 5521 5522 int maxLayer = 0; 5523 final Rect frame = new Rect(); 5524 5525 float scale = 0; 5526 int dw, dh; 5527 int rot = Surface.ROTATION_0; 5528 5529 boolean screenshotReady; 5530 int minLayer; 5531 if (appToken == null) { 5532 screenshotReady = true; 5533 minLayer = 0; 5534 } else { 5535 screenshotReady = false; 5536 minLayer = Integer.MAX_VALUE; 5537 } 5538 5539 int retryCount = 0; 5540 WindowState appWin = null; 5541 5542 do { 5543 if (retryCount++ > 0) { 5544 try { 5545 Thread.sleep(100); 5546 } catch (InterruptedException e) { 5547 } 5548 } 5549 synchronized(mWindowMap) { 5550 final DisplayContent displayContent = getDisplayContentLocked(displayId); 5551 if (displayContent == null) { 5552 return null; 5553 } 5554 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 5555 dw = displayInfo.logicalWidth; 5556 dh = displayInfo.logicalHeight; 5557 5558 int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) 5559 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 5560 aboveAppLayer += TYPE_LAYER_MULTIPLIER; 5561 5562 boolean isImeTarget = mInputMethodTarget != null 5563 && mInputMethodTarget.mAppToken != null 5564 && mInputMethodTarget.mAppToken.appToken != null 5565 && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken; 5566 5567 // Figure out the part of the screen that is actually the app. 5568 boolean including = false; 5569 appWin = null; 5570 final WindowList windows = displayContent.getWindowList(); 5571 final Rect stackBounds = new Rect(); 5572 for (int i = windows.size() - 1; i >= 0; i--) { 5573 WindowState ws = windows.get(i); 5574 if (!ws.mHasSurface) { 5575 continue; 5576 } 5577 if (ws.mLayer >= aboveAppLayer) { 5578 continue; 5579 } 5580 // When we will skip windows: when we are not including 5581 // ones behind a window we didn't skip, and we are actually 5582 // taking a screenshot of a specific app. 5583 if (!including && appToken != null) { 5584 // Also, we can possibly skip this window if it is not 5585 // an IME target or the application for the screenshot 5586 // is not the current IME target. 5587 if (!ws.mIsImWindow || !isImeTarget) { 5588 // And finally, this window is of no interest if it 5589 // is not associated with the screenshot app. 5590 if (ws.mAppToken == null || ws.mAppToken.token != appToken) { 5591 continue; 5592 } 5593 appWin = ws; 5594 stackBounds.set(ws.getStackBounds()); 5595 } 5596 } 5597 5598 // We keep on including windows until we go past a full-screen 5599 // window. 5600 boolean fullscreen = ws.isFullscreen(dw, dh); 5601 including = !ws.mIsImWindow && !fullscreen; 5602 5603 final WindowStateAnimator winAnim = ws.mWinAnimator; 5604 if (maxLayer < winAnim.mSurfaceLayer) { 5605 maxLayer = winAnim.mSurfaceLayer; 5606 } 5607 if (minLayer > winAnim.mSurfaceLayer) { 5608 minLayer = winAnim.mSurfaceLayer; 5609 } 5610 5611 // Don't include wallpaper in bounds calculation 5612 if (!ws.mIsWallpaper) { 5613 final Rect wf = ws.mFrame; 5614 final Rect cr = ws.mContentInsets; 5615 int left = wf.left + cr.left; 5616 int top = wf.top + cr.top; 5617 int right = wf.right - cr.right; 5618 int bottom = wf.bottom - cr.bottom; 5619 frame.union(left, top, right, bottom); 5620 frame.intersect(stackBounds); 5621 } 5622 5623 if (ws.mAppToken != null && ws.mAppToken.token == appToken && 5624 ws.isDisplayedLw()) { 5625 screenshotReady = true; 5626 } 5627 5628 if (fullscreen) { 5629 // No point in continuing down through windows. 5630 break; 5631 } 5632 } 5633 5634 if (appToken != null && appWin == null) { 5635 // Can't find a window to snapshot. 5636 if (DEBUG_SCREENSHOT) Slog.i(TAG, 5637 "Screenshot: Couldn't find a surface matching " + appToken); 5638 return null; 5639 } 5640 if (!screenshotReady) { 5641 // Delay and hope that window gets drawn. 5642 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken 5643 + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState); 5644 continue; 5645 } 5646 5647 // Constrain frame to the screen size. 5648 frame.intersect(0, 0, dw, dh); 5649 5650 if (frame.isEmpty() || maxLayer == 0) { 5651 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 5652 + ": returning null frame=" + frame.toShortString() + " maxLayer=" 5653 + maxLayer); 5654 return null; 5655 } 5656 5657 // The screenshot API does not apply the current screen rotation. 5658 rot = getDefaultDisplayContentLocked().getDisplay().getRotation(); 5659 int fw = frame.width(); 5660 int fh = frame.height(); 5661 5662 // Constrain thumbnail to smaller of screen width or height. Assumes aspect 5663 // of thumbnail is the same as the screen (in landscape) or square. 5664 scale = Math.max(width / (float) fw, height / (float) fh); 5665 /* 5666 float targetWidthScale = width / (float) fw; 5667 float targetHeightScale = height / (float) fh; 5668 if (fw <= fh) { 5669 scale = targetWidthScale; 5670 // If aspect of thumbnail is the same as the screen (in landscape), 5671 // select the slightly larger value so we fill the entire bitmap 5672 if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) { 5673 scale = targetHeightScale; 5674 } 5675 } else { 5676 scale = targetHeightScale; 5677 // If aspect of thumbnail is the same as the screen (in landscape), 5678 // select the slightly larger value so we fill the entire bitmap 5679 if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) { 5680 scale = targetWidthScale; 5681 } 5682 } 5683 */ 5684 5685 // The screen shot will contain the entire screen. 5686 dw = (int)(dw*scale); 5687 dh = (int)(dh*scale); 5688 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 5689 int tmp = dw; 5690 dw = dh; 5691 dh = tmp; 5692 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; 5693 } 5694 if (DEBUG_SCREENSHOT) { 5695 Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 5696 + maxLayer + " appToken=" + appToken); 5697 for (int i = 0; i < windows.size(); i++) { 5698 WindowState win = windows.get(i); 5699 Slog.i(TAG, win + ": " + win.mLayer 5700 + " animLayer=" + win.mWinAnimator.mAnimLayer 5701 + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer); 5702 } 5703 } 5704 rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer); 5705 } 5706 } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES); 5707 if (retryCount > MAX_SCREENSHOT_RETRIES) Slog.i(TAG, "Screenshot max retries " + 5708 retryCount + " of " + appToken + " appWin=" + (appWin == null ? 5709 "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState))); 5710 5711 if (rawss == null) { 5712 Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh 5713 + ") to layer " + maxLayer); 5714 return null; 5715 } 5716 5717 Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig()); 5718 frame.scale(scale); 5719 Matrix matrix = new Matrix(); 5720 ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix); 5721 // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left 5722 matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top)); 5723 Canvas canvas = new Canvas(bm); 5724 canvas.drawColor(0xFF000000); 5725 canvas.drawBitmap(rawss, matrix, null); 5726 canvas.setBitmap(null); 5727 5728 if (DEBUG_SCREENSHOT) { 5729 // TEST IF IT's ALL BLACK 5730 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 5731 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 5732 boolean allBlack = true; 5733 final int firstColor = buffer[0]; 5734 for (int i = 0; i < buffer.length; i++) { 5735 if (buffer[i] != firstColor) { 5736 allBlack = false; 5737 break; 5738 } 5739 } 5740 if (allBlack) { 5741 Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" + 5742 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 5743 (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") + 5744 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 5745 } 5746 } 5747 5748 rawss.recycle(); 5749 return bm; 5750 } 5751 5752 /** 5753 * Freeze rotation changes. (Enable "rotation lock".) 5754 * Persists across reboots. 5755 * @param rotation The desired rotation to freeze to, or -1 to use the 5756 * current rotation. 5757 */ 5758 @Override 5759 public void freezeRotation(int rotation) { 5760 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5761 "freezeRotation()")) { 5762 throw new SecurityException("Requires SET_ORIENTATION permission"); 5763 } 5764 if (rotation < -1 || rotation > Surface.ROTATION_270) { 5765 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 5766 + "rotation constant."); 5767 } 5768 5769 if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); 5770 5771 long origId = Binder.clearCallingIdentity(); 5772 try { 5773 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, 5774 rotation == -1 ? mRotation : rotation); 5775 } finally { 5776 Binder.restoreCallingIdentity(origId); 5777 } 5778 5779 updateRotationUnchecked(false, false); 5780 } 5781 5782 /** 5783 * Thaw rotation changes. (Disable "rotation lock".) 5784 * Persists across reboots. 5785 */ 5786 @Override 5787 public void thawRotation() { 5788 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5789 "thawRotation()")) { 5790 throw new SecurityException("Requires SET_ORIENTATION permission"); 5791 } 5792 5793 if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); 5794 5795 long origId = Binder.clearCallingIdentity(); 5796 try { 5797 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 5798 777); // rot not used 5799 } finally { 5800 Binder.restoreCallingIdentity(origId); 5801 } 5802 5803 updateRotationUnchecked(false, false); 5804 } 5805 5806 /** 5807 * Recalculate the current rotation. 5808 * 5809 * Called by the window manager policy whenever the state of the system changes 5810 * such that the current rotation might need to be updated, such as when the 5811 * device is docked or rotated into a new posture. 5812 */ 5813 @Override 5814 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 5815 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 5816 } 5817 5818 /** 5819 * Temporarily pauses rotation changes until resumed. 5820 * 5821 * This can be used to prevent rotation changes from occurring while the user is 5822 * performing certain operations, such as drag and drop. 5823 * 5824 * This call nests and must be matched by an equal number of calls to 5825 * {@link #resumeRotationLocked}. 5826 */ 5827 void pauseRotationLocked() { 5828 mDeferredRotationPauseCount += 1; 5829 } 5830 5831 /** 5832 * Resumes normal rotation changes after being paused. 5833 */ 5834 void resumeRotationLocked() { 5835 if (mDeferredRotationPauseCount > 0) { 5836 mDeferredRotationPauseCount -= 1; 5837 if (mDeferredRotationPauseCount == 0) { 5838 boolean changed = updateRotationUncheckedLocked(false); 5839 if (changed) { 5840 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 5841 } 5842 } 5843 } 5844 } 5845 5846 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 5847 if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" 5848 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); 5849 5850 long origId = Binder.clearCallingIdentity(); 5851 boolean changed; 5852 synchronized(mWindowMap) { 5853 changed = updateRotationUncheckedLocked(false); 5854 if (!changed || forceRelayout) { 5855 getDefaultDisplayContentLocked().layoutNeeded = true; 5856 performLayoutAndPlaceSurfacesLocked(); 5857 } 5858 } 5859 5860 if (changed || alwaysSendConfiguration) { 5861 sendNewConfiguration(); 5862 } 5863 5864 Binder.restoreCallingIdentity(origId); 5865 } 5866 5867 // TODO(multidisplay): Rotate any display? 5868 /** 5869 * Updates the current rotation. 5870 * 5871 * Returns true if the rotation has been changed. In this case YOU 5872 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. 5873 */ 5874 public boolean updateRotationUncheckedLocked(boolean inTransaction) { 5875 if (mDeferredRotationPauseCount > 0) { 5876 // Rotation updates have been paused temporarily. Defer the update until 5877 // updates have been resumed. 5878 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused."); 5879 return false; 5880 } 5881 5882 ScreenRotationAnimation screenRotationAnimation = 5883 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 5884 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 5885 // Rotation updates cannot be performed while the previous rotation change 5886 // animation is still in progress. Skip this update. We will try updating 5887 // again after the animation is finished and the display is unfrozen. 5888 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress."); 5889 return false; 5890 } 5891 5892 if (!mDisplayEnabled) { 5893 // No point choosing a rotation if the display is not enabled. 5894 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled."); 5895 return false; 5896 } 5897 5898 // TODO: Implement forced rotation changes. 5899 // Set mAltOrientation to indicate that the application is receiving 5900 // an orientation that has different metrics than it expected. 5901 // eg. Portrait instead of Landscape. 5902 5903 int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation); 5904 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 5905 mForcedAppOrientation, rotation); 5906 5907 if (DEBUG_ORIENTATION) { 5908 Slog.v(TAG, "Application requested orientation " 5909 + mForcedAppOrientation + ", got rotation " + rotation 5910 + " which has " + (altOrientation ? "incompatible" : "compatible") 5911 + " metrics"); 5912 } 5913 5914 if (mRotation == rotation && mAltOrientation == altOrientation) { 5915 // No change. 5916 return false; 5917 } 5918 5919 if (DEBUG_ORIENTATION) { 5920 Slog.v(TAG, 5921 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") 5922 + " from " + mRotation + (mAltOrientation ? " (alt)" : "") 5923 + ", forceApp=" + mForcedAppOrientation); 5924 } 5925 5926 mRotation = rotation; 5927 mAltOrientation = altOrientation; 5928 mPolicy.setRotationLw(mRotation); 5929 5930 mWindowsFreezingScreen = true; 5931 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 5932 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION); 5933 mWaitingForConfig = true; 5934 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 5935 displayContent.layoutNeeded = true; 5936 final int[] anim = new int[2]; 5937 if (displayContent.isDimming()) { 5938 anim[0] = anim[1] = 0; 5939 } else { 5940 mPolicy.selectRotationAnimationLw(anim); 5941 } 5942 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]); 5943 // startFreezingDisplayLocked can reset the ScreenRotationAnimation. 5944 screenRotationAnimation = 5945 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 5946 5947 // We need to update our screen size information to match the new 5948 // rotation. Note that this is redundant with the later call to 5949 // sendNewConfiguration() that must be called after this function 5950 // returns... however we need to do the screen size part of that 5951 // before then so we have the correct size to use when initializing 5952 // the rotation animation for the new rotation. 5953 computeScreenConfigurationLocked(null); 5954 5955 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 5956 if (!inTransaction) { 5957 if (SHOW_TRANSACTIONS) { 5958 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked"); 5959 } 5960 SurfaceControl.openTransaction(); 5961 } 5962 try { 5963 // NOTE: We disable the rotation in the emulator because 5964 // it doesn't support hardware OpenGL emulation yet. 5965 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 5966 && screenRotationAnimation.hasScreenshot()) { 5967 if (screenRotationAnimation.setRotationInTransaction( 5968 rotation, mFxSession, 5969 MAX_ANIMATION_DURATION, mTransitionAnimationScale, 5970 displayInfo.logicalWidth, displayInfo.logicalHeight)) { 5971 scheduleAnimationLocked(); 5972 } 5973 } 5974 5975 mDisplayManagerService.performTraversalInTransactionFromWindowManager(); 5976 } finally { 5977 if (!inTransaction) { 5978 SurfaceControl.closeTransaction(); 5979 if (SHOW_LIGHT_TRANSACTIONS) { 5980 Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked"); 5981 } 5982 } 5983 } 5984 5985 final WindowList windows = displayContent.getWindowList(); 5986 for (int i = windows.size() - 1; i >= 0; i--) { 5987 WindowState w = windows.get(i); 5988 if (w.mHasSurface) { 5989 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w); 5990 w.mOrientationChanging = true; 5991 mInnerFields.mOrientationChangeComplete = false; 5992 } 5993 w.mLastFreezeDuration = 0; 5994 } 5995 5996 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 5997 try { 5998 mRotationWatchers.get(i).onRotationChanged(rotation); 5999 } catch (RemoteException e) { 6000 } 6001 } 6002 6003 //TODO (multidisplay): Magnification is supported only for the default display. 6004 if (mDisplayMagnifier != null 6005 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 6006 mDisplayMagnifier.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation); 6007 } 6008 6009 return true; 6010 } 6011 6012 @Override 6013 public int getRotation() { 6014 return mRotation; 6015 } 6016 6017 @Override 6018 public boolean isRotationFrozen() { 6019 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED; 6020 } 6021 6022 @Override 6023 public int watchRotation(IRotationWatcher watcher) { 6024 final IBinder watcherBinder = watcher.asBinder(); 6025 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 6026 @Override 6027 public void binderDied() { 6028 synchronized (mWindowMap) { 6029 for (int i=0; i<mRotationWatchers.size(); i++) { 6030 if (watcherBinder == mRotationWatchers.get(i).asBinder()) { 6031 IRotationWatcher removed = mRotationWatchers.remove(i); 6032 if (removed != null) { 6033 removed.asBinder().unlinkToDeath(this, 0); 6034 } 6035 i--; 6036 } 6037 } 6038 } 6039 } 6040 }; 6041 6042 synchronized (mWindowMap) { 6043 try { 6044 watcher.asBinder().linkToDeath(dr, 0); 6045 mRotationWatchers.add(watcher); 6046 } catch (RemoteException e) { 6047 // Client died, no cleanup needed. 6048 } 6049 6050 return mRotation; 6051 } 6052 } 6053 6054 @Override 6055 public void removeRotationWatcher(IRotationWatcher watcher) { 6056 final IBinder watcherBinder = watcher.asBinder(); 6057 synchronized (mWindowMap) { 6058 for (int i=0; i<mRotationWatchers.size(); i++) { 6059 if (watcherBinder == mRotationWatchers.get(i).asBinder()) { 6060 mRotationWatchers.remove(i); 6061 i--; 6062 } 6063 } 6064 } 6065 } 6066 6067 /** 6068 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 6069 * theme attribute) on devices that feature a physical options menu key attempt to position 6070 * their menu panel window along the edge of the screen nearest the physical menu key. 6071 * This lowers the travel distance between invoking the menu panel and selecting 6072 * a menu option. 6073 * 6074 * This method helps control where that menu is placed. Its current implementation makes 6075 * assumptions about the menu key and its relationship to the screen based on whether 6076 * the device's natural orientation is portrait (width < height) or landscape. 6077 * 6078 * The menu key is assumed to be located along the bottom edge of natural-portrait 6079 * devices and along the right edge of natural-landscape devices. If these assumptions 6080 * do not hold for the target device, this method should be changed to reflect that. 6081 * 6082 * @return A {@link Gravity} value for placing the options menu window 6083 */ 6084 @Override 6085 public int getPreferredOptionsPanelGravity() { 6086 synchronized (mWindowMap) { 6087 final int rotation = getRotation(); 6088 6089 // TODO(multidisplay): Assume that such devices physical keys are on the main screen. 6090 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6091 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) { 6092 // On devices with a natural orientation of portrait 6093 switch (rotation) { 6094 default: 6095 case Surface.ROTATION_0: 6096 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6097 case Surface.ROTATION_90: 6098 return Gravity.RIGHT | Gravity.BOTTOM; 6099 case Surface.ROTATION_180: 6100 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6101 case Surface.ROTATION_270: 6102 return Gravity.START | Gravity.BOTTOM; 6103 } 6104 } 6105 6106 // On devices with a natural orientation of landscape 6107 switch (rotation) { 6108 default: 6109 case Surface.ROTATION_0: 6110 return Gravity.RIGHT | Gravity.BOTTOM; 6111 case Surface.ROTATION_90: 6112 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6113 case Surface.ROTATION_180: 6114 return Gravity.START | Gravity.BOTTOM; 6115 case Surface.ROTATION_270: 6116 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6117 } 6118 } 6119 } 6120 6121 /** 6122 * Starts the view server on the specified port. 6123 * 6124 * @param port The port to listener to. 6125 * 6126 * @return True if the server was successfully started, false otherwise. 6127 * 6128 * @see com.android.server.wm.ViewServer 6129 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 6130 */ 6131 @Override 6132 public boolean startViewServer(int port) { 6133 if (isSystemSecure()) { 6134 return false; 6135 } 6136 6137 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 6138 return false; 6139 } 6140 6141 if (port < 1024) { 6142 return false; 6143 } 6144 6145 if (mViewServer != null) { 6146 if (!mViewServer.isRunning()) { 6147 try { 6148 return mViewServer.start(); 6149 } catch (IOException e) { 6150 Slog.w(TAG, "View server did not start"); 6151 } 6152 } 6153 return false; 6154 } 6155 6156 try { 6157 mViewServer = new ViewServer(this, port); 6158 return mViewServer.start(); 6159 } catch (IOException e) { 6160 Slog.w(TAG, "View server did not start"); 6161 } 6162 return false; 6163 } 6164 6165 private boolean isSystemSecure() { 6166 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 6167 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 6168 } 6169 6170 /** 6171 * Stops the view server if it exists. 6172 * 6173 * @return True if the server stopped, false if it wasn't started or 6174 * couldn't be stopped. 6175 * 6176 * @see com.android.server.wm.ViewServer 6177 */ 6178 @Override 6179 public boolean stopViewServer() { 6180 if (isSystemSecure()) { 6181 return false; 6182 } 6183 6184 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 6185 return false; 6186 } 6187 6188 if (mViewServer != null) { 6189 return mViewServer.stop(); 6190 } 6191 return false; 6192 } 6193 6194 /** 6195 * Indicates whether the view server is running. 6196 * 6197 * @return True if the server is running, false otherwise. 6198 * 6199 * @see com.android.server.wm.ViewServer 6200 */ 6201 @Override 6202 public boolean isViewServerRunning() { 6203 if (isSystemSecure()) { 6204 return false; 6205 } 6206 6207 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 6208 return false; 6209 } 6210 6211 return mViewServer != null && mViewServer.isRunning(); 6212 } 6213 6214 /** 6215 * Lists all availble windows in the system. The listing is written in the 6216 * specified Socket's output stream with the following syntax: 6217 * windowHashCodeInHexadecimal windowName 6218 * Each line of the ouput represents a different window. 6219 * 6220 * @param client The remote client to send the listing to. 6221 * @return False if an error occured, true otherwise. 6222 */ 6223 boolean viewServerListWindows(Socket client) { 6224 if (isSystemSecure()) { 6225 return false; 6226 } 6227 6228 boolean result = true; 6229 6230 WindowList windows = new WindowList(); 6231 synchronized (mWindowMap) { 6232 //noinspection unchecked 6233 final int numDisplays = mDisplayContents.size(); 6234 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6235 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 6236 windows.addAll(displayContent.getWindowList()); 6237 } 6238 } 6239 6240 BufferedWriter out = null; 6241 6242 // Any uncaught exception will crash the system process 6243 try { 6244 OutputStream clientStream = client.getOutputStream(); 6245 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6246 6247 final int count = windows.size(); 6248 for (int i = 0; i < count; i++) { 6249 final WindowState w = windows.get(i); 6250 out.write(Integer.toHexString(System.identityHashCode(w))); 6251 out.write(' '); 6252 out.append(w.mAttrs.getTitle()); 6253 out.write('\n'); 6254 } 6255 6256 out.write("DONE.\n"); 6257 out.flush(); 6258 } catch (Exception e) { 6259 result = false; 6260 } finally { 6261 if (out != null) { 6262 try { 6263 out.close(); 6264 } catch (IOException e) { 6265 result = false; 6266 } 6267 } 6268 } 6269 6270 return result; 6271 } 6272 6273 // TODO(multidisplay): Extend to multiple displays. 6274 /** 6275 * Returns the focused window in the following format: 6276 * windowHashCodeInHexadecimal windowName 6277 * 6278 * @param client The remote client to send the listing to. 6279 * @return False if an error occurred, true otherwise. 6280 */ 6281 boolean viewServerGetFocusedWindow(Socket client) { 6282 if (isSystemSecure()) { 6283 return false; 6284 } 6285 6286 boolean result = true; 6287 6288 WindowState focusedWindow = getFocusedWindow(); 6289 6290 BufferedWriter out = null; 6291 6292 // Any uncaught exception will crash the system process 6293 try { 6294 OutputStream clientStream = client.getOutputStream(); 6295 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6296 6297 if(focusedWindow != null) { 6298 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 6299 out.write(' '); 6300 out.append(focusedWindow.mAttrs.getTitle()); 6301 } 6302 out.write('\n'); 6303 out.flush(); 6304 } catch (Exception e) { 6305 result = false; 6306 } finally { 6307 if (out != null) { 6308 try { 6309 out.close(); 6310 } catch (IOException e) { 6311 result = false; 6312 } 6313 } 6314 } 6315 6316 return result; 6317 } 6318 6319 /** 6320 * Sends a command to a target window. The result of the command, if any, will be 6321 * written in the output stream of the specified socket. 6322 * 6323 * The parameters must follow this syntax: 6324 * windowHashcode extra 6325 * 6326 * Where XX is the length in characeters of the windowTitle. 6327 * 6328 * The first parameter is the target window. The window with the specified hashcode 6329 * will be the target. If no target can be found, nothing happens. The extra parameters 6330 * will be delivered to the target window and as parameters to the command itself. 6331 * 6332 * @param client The remote client to sent the result, if any, to. 6333 * @param command The command to execute. 6334 * @param parameters The command parameters. 6335 * 6336 * @return True if the command was successfully delivered, false otherwise. This does 6337 * not indicate whether the command itself was successful. 6338 */ 6339 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 6340 if (isSystemSecure()) { 6341 return false; 6342 } 6343 6344 boolean success = true; 6345 Parcel data = null; 6346 Parcel reply = null; 6347 6348 BufferedWriter out = null; 6349 6350 // Any uncaught exception will crash the system process 6351 try { 6352 // Find the hashcode of the window 6353 int index = parameters.indexOf(' '); 6354 if (index == -1) { 6355 index = parameters.length(); 6356 } 6357 final String code = parameters.substring(0, index); 6358 int hashCode = (int) Long.parseLong(code, 16); 6359 6360 // Extract the command's parameter after the window description 6361 if (index < parameters.length()) { 6362 parameters = parameters.substring(index + 1); 6363 } else { 6364 parameters = ""; 6365 } 6366 6367 final WindowState window = findWindow(hashCode); 6368 if (window == null) { 6369 return false; 6370 } 6371 6372 data = Parcel.obtain(); 6373 data.writeInterfaceToken("android.view.IWindow"); 6374 data.writeString(command); 6375 data.writeString(parameters); 6376 data.writeInt(1); 6377 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 6378 6379 reply = Parcel.obtain(); 6380 6381 final IBinder binder = window.mClient.asBinder(); 6382 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 6383 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 6384 6385 reply.readException(); 6386 6387 if (!client.isOutputShutdown()) { 6388 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 6389 out.write("DONE\n"); 6390 out.flush(); 6391 } 6392 6393 } catch (Exception e) { 6394 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); 6395 success = false; 6396 } finally { 6397 if (data != null) { 6398 data.recycle(); 6399 } 6400 if (reply != null) { 6401 reply.recycle(); 6402 } 6403 if (out != null) { 6404 try { 6405 out.close(); 6406 } catch (IOException e) { 6407 6408 } 6409 } 6410 } 6411 6412 return success; 6413 } 6414 6415 public void addWindowChangeListener(WindowChangeListener listener) { 6416 synchronized(mWindowMap) { 6417 mWindowChangeListeners.add(listener); 6418 } 6419 } 6420 6421 public void removeWindowChangeListener(WindowChangeListener listener) { 6422 synchronized(mWindowMap) { 6423 mWindowChangeListeners.remove(listener); 6424 } 6425 } 6426 6427 private void notifyWindowsChanged() { 6428 WindowChangeListener[] windowChangeListeners; 6429 synchronized(mWindowMap) { 6430 if(mWindowChangeListeners.isEmpty()) { 6431 return; 6432 } 6433 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6434 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6435 } 6436 int N = windowChangeListeners.length; 6437 for(int i = 0; i < N; i++) { 6438 windowChangeListeners[i].windowsChanged(); 6439 } 6440 } 6441 6442 private void notifyFocusChanged() { 6443 WindowChangeListener[] windowChangeListeners; 6444 synchronized(mWindowMap) { 6445 if(mWindowChangeListeners.isEmpty()) { 6446 return; 6447 } 6448 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6449 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6450 } 6451 int N = windowChangeListeners.length; 6452 for(int i = 0; i < N; i++) { 6453 windowChangeListeners[i].focusChanged(); 6454 } 6455 } 6456 6457 private WindowState findWindow(int hashCode) { 6458 if (hashCode == -1) { 6459 // TODO(multidisplay): Extend to multiple displays. 6460 return getFocusedWindow(); 6461 } 6462 6463 synchronized (mWindowMap) { 6464 final int numDisplays = mDisplayContents.size(); 6465 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6466 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 6467 final int numWindows = windows.size(); 6468 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 6469 final WindowState w = windows.get(winNdx); 6470 if (System.identityHashCode(w) == hashCode) { 6471 return w; 6472 } 6473 } 6474 } 6475 } 6476 6477 return null; 6478 } 6479 6480 /* 6481 * Instruct the Activity Manager to fetch the current configuration and broadcast 6482 * that to config-changed listeners if appropriate. 6483 */ 6484 void sendNewConfiguration() { 6485 try { 6486 mActivityManager.updateConfiguration(null); 6487 } catch (RemoteException e) { 6488 } 6489 } 6490 6491 public Configuration computeNewConfiguration() { 6492 synchronized (mWindowMap) { 6493 Configuration config = computeNewConfigurationLocked(); 6494 if (config == null && mWaitingForConfig) { 6495 // Nothing changed but we are waiting for something... stop that! 6496 mWaitingForConfig = false; 6497 mLastFinishedFreezeSource = "new-config"; 6498 performLayoutAndPlaceSurfacesLocked(); 6499 } 6500 return config; 6501 } 6502 } 6503 6504 Configuration computeNewConfigurationLocked() { 6505 Configuration config = new Configuration(); 6506 config.fontScale = 0; 6507 if (!computeScreenConfigurationLocked(config)) { 6508 return null; 6509 } 6510 return config; 6511 } 6512 6513 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) { 6514 // TODO: Multidisplay: for now only use with default display. 6515 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation); 6516 if (width < displayInfo.smallestNominalAppWidth) { 6517 displayInfo.smallestNominalAppWidth = width; 6518 } 6519 if (width > displayInfo.largestNominalAppWidth) { 6520 displayInfo.largestNominalAppWidth = width; 6521 } 6522 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation); 6523 if (height < displayInfo.smallestNominalAppHeight) { 6524 displayInfo.smallestNominalAppHeight = height; 6525 } 6526 if (height > displayInfo.largestNominalAppHeight) { 6527 displayInfo.largestNominalAppHeight = height; 6528 } 6529 } 6530 6531 private int reduceConfigLayout(int curLayout, int rotation, float density, 6532 int dw, int dh) { 6533 // TODO: Multidisplay: for now only use with default display. 6534 // Get the app screen size at this rotation. 6535 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6536 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6537 6538 // Compute the screen layout size class for this rotation. 6539 int longSize = w; 6540 int shortSize = h; 6541 if (longSize < shortSize) { 6542 int tmp = longSize; 6543 longSize = shortSize; 6544 shortSize = tmp; 6545 } 6546 longSize = (int)(longSize/density); 6547 shortSize = (int)(shortSize/density); 6548 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 6549 } 6550 6551 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 6552 int dw, int dh, float density, Configuration outConfig) { 6553 // TODO: Multidisplay: for now only use with default display. 6554 6555 // We need to determine the smallest width that will occur under normal 6556 // operation. To this, start with the base screen size and compute the 6557 // width under the different possible rotations. We need to un-rotate 6558 // the current screen dimensions before doing this. 6559 int unrotDw, unrotDh; 6560 if (rotated) { 6561 unrotDw = dh; 6562 unrotDh = dw; 6563 } else { 6564 unrotDw = dw; 6565 unrotDh = dh; 6566 } 6567 displayInfo.smallestNominalAppWidth = 1<<30; 6568 displayInfo.smallestNominalAppHeight = 1<<30; 6569 displayInfo.largestNominalAppWidth = 0; 6570 displayInfo.largestNominalAppHeight = 0; 6571 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh); 6572 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw); 6573 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh); 6574 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw); 6575 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 6576 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh); 6577 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw); 6578 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); 6579 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); 6580 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 6581 outConfig.screenLayout = sl; 6582 } 6583 6584 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, 6585 int dw, int dh) { 6586 // TODO: Multidisplay: for now only use with default display. 6587 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6588 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6589 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 6590 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 6591 if (curSize == 0 || size < curSize) { 6592 curSize = size; 6593 } 6594 return curSize; 6595 } 6596 6597 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) { 6598 // TODO: Multidisplay: for now only use with default display. 6599 mTmpDisplayMetrics.setTo(dm); 6600 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 6601 final int unrotDw, unrotDh; 6602 if (rotated) { 6603 unrotDw = dh; 6604 unrotDh = dw; 6605 } else { 6606 unrotDw = dw; 6607 unrotDh = dh; 6608 } 6609 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh); 6610 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw); 6611 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh); 6612 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw); 6613 return sw; 6614 } 6615 6616 boolean computeScreenConfigurationLocked(Configuration config) { 6617 if (!mDisplayReady) { 6618 return false; 6619 } 6620 6621 // TODO(multidisplay): For now, apply Configuration to main screen only. 6622 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6623 6624 // Use the effective "visual" dimensions based on current rotation 6625 final boolean rotated = (mRotation == Surface.ROTATION_90 6626 || mRotation == Surface.ROTATION_270); 6627 final int realdw = rotated ? 6628 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; 6629 final int realdh = rotated ? 6630 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; 6631 int dw = realdw; 6632 int dh = realdh; 6633 6634 if (mAltOrientation) { 6635 if (realdw > realdh) { 6636 // Turn landscape into portrait. 6637 int maxw = (int)(realdh/1.3f); 6638 if (maxw < realdw) { 6639 dw = maxw; 6640 } 6641 } else { 6642 // Turn portrait into landscape. 6643 int maxh = (int)(realdw/1.3f); 6644 if (maxh < realdh) { 6645 dh = maxh; 6646 } 6647 } 6648 } 6649 6650 if (config != null) { 6651 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : 6652 Configuration.ORIENTATION_LANDSCAPE; 6653 } 6654 6655 // Update application display metrics. 6656 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); 6657 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); 6658 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6659 synchronized(displayContent.mDisplaySizeLock) { 6660 displayInfo.rotation = mRotation; 6661 displayInfo.logicalWidth = dw; 6662 displayInfo.logicalHeight = dh; 6663 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; 6664 displayInfo.appWidth = appWidth; 6665 displayInfo.appHeight = appHeight; 6666 displayInfo.getLogicalMetrics(mRealDisplayMetrics, 6667 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 6668 displayInfo.getAppMetrics(mDisplayMetrics); 6669 mDisplayManagerService.setDisplayInfoOverrideFromWindowManager( 6670 displayContent.getDisplayId(), displayInfo); 6671 } 6672 if (false) { 6673 Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); 6674 } 6675 6676 final DisplayMetrics dm = mDisplayMetrics; 6677 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, 6678 mCompatDisplayMetrics); 6679 6680 if (config != null) { 6681 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) 6682 / dm.density); 6683 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) 6684 / dm.density); 6685 computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config); 6686 6687 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 6688 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 6689 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); 6690 config.densityDpi = displayContent.mBaseDisplayDensity; 6691 6692 // Update the configuration based on available input devices, lid switch, 6693 // and platform configuration. 6694 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6695 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6696 config.navigation = Configuration.NAVIGATION_NONAV; 6697 6698 int keyboardPresence = 0; 6699 int navigationPresence = 0; 6700 final InputDevice[] devices = mInputManager.getInputDevices(); 6701 final int len = devices.length; 6702 for (int i = 0; i < len; i++) { 6703 InputDevice device = devices[i]; 6704 if (!device.isVirtual()) { 6705 final int sources = device.getSources(); 6706 final int presenceFlag = device.isExternal() ? 6707 WindowManagerPolicy.PRESENCE_EXTERNAL : 6708 WindowManagerPolicy.PRESENCE_INTERNAL; 6709 6710 if (mIsTouchDevice) { 6711 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 6712 InputDevice.SOURCE_TOUCHSCREEN) { 6713 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 6714 } 6715 } else { 6716 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6717 } 6718 6719 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 6720 config.navigation = Configuration.NAVIGATION_TRACKBALL; 6721 navigationPresence |= presenceFlag; 6722 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 6723 && config.navigation == Configuration.NAVIGATION_NONAV) { 6724 config.navigation = Configuration.NAVIGATION_DPAD; 6725 navigationPresence |= presenceFlag; 6726 } 6727 6728 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 6729 config.keyboard = Configuration.KEYBOARD_QWERTY; 6730 keyboardPresence |= presenceFlag; 6731 } 6732 } 6733 } 6734 6735 // Determine whether a hard keyboard is available and enabled. 6736 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 6737 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 6738 mHardKeyboardAvailable = hardKeyboardAvailable; 6739 mHardKeyboardEnabled = hardKeyboardAvailable; 6740 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6741 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6742 } 6743 if (!mHardKeyboardEnabled) { 6744 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6745 } 6746 6747 // Let the policy update hidden states. 6748 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 6749 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 6750 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 6751 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 6752 } 6753 6754 return true; 6755 } 6756 6757 public boolean isHardKeyboardAvailable() { 6758 synchronized (mWindowMap) { 6759 return mHardKeyboardAvailable; 6760 } 6761 } 6762 6763 public boolean isHardKeyboardEnabled() { 6764 synchronized (mWindowMap) { 6765 return mHardKeyboardEnabled; 6766 } 6767 } 6768 6769 public void setHardKeyboardEnabled(boolean enabled) { 6770 synchronized (mWindowMap) { 6771 if (mHardKeyboardEnabled != enabled) { 6772 mHardKeyboardEnabled = enabled; 6773 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6774 } 6775 } 6776 } 6777 6778 public void setOnHardKeyboardStatusChangeListener( 6779 OnHardKeyboardStatusChangeListener listener) { 6780 synchronized (mWindowMap) { 6781 mHardKeyboardStatusChangeListener = listener; 6782 } 6783 } 6784 6785 void notifyHardKeyboardStatusChange() { 6786 final boolean available, enabled; 6787 final OnHardKeyboardStatusChangeListener listener; 6788 synchronized (mWindowMap) { 6789 listener = mHardKeyboardStatusChangeListener; 6790 available = mHardKeyboardAvailable; 6791 enabled = mHardKeyboardEnabled; 6792 } 6793 if (listener != null) { 6794 listener.onHardKeyboardStatusChange(available, enabled); 6795 } 6796 } 6797 6798 // ------------------------------------------------------------- 6799 // Drag and drop 6800 // ------------------------------------------------------------- 6801 6802 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 6803 int flags, int width, int height, Surface outSurface) { 6804 if (DEBUG_DRAG) { 6805 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 6806 + " flags=" + Integer.toHexString(flags) + " win=" + window 6807 + " asbinder=" + window.asBinder()); 6808 } 6809 6810 final int callerPid = Binder.getCallingPid(); 6811 final long origId = Binder.clearCallingIdentity(); 6812 IBinder token = null; 6813 6814 try { 6815 synchronized (mWindowMap) { 6816 try { 6817 if (mDragState == null) { 6818 // TODO(multi-display): support other displays 6819 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6820 final Display display = displayContent.getDisplay(); 6821 SurfaceControl surface = new SurfaceControl(session, "drag surface", 6822 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 6823 surface.setLayerStack(display.getLayerStack()); 6824 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 6825 + surface + ": CREATE"); 6826 outSurface.copyFrom(surface); 6827 final IBinder winBinder = window.asBinder(); 6828 token = new Binder(); 6829 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 6830 token = mDragState.mToken = new Binder(); 6831 6832 // 5 second timeout for this window to actually begin the drag 6833 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 6834 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 6835 mH.sendMessageDelayed(msg, 5000); 6836 } else { 6837 Slog.w(TAG, "Drag already in progress"); 6838 } 6839 } catch (OutOfResourcesException e) { 6840 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 6841 if (mDragState != null) { 6842 mDragState.reset(); 6843 mDragState = null; 6844 } 6845 } 6846 } 6847 } finally { 6848 Binder.restoreCallingIdentity(origId); 6849 } 6850 6851 return token; 6852 } 6853 6854 // ------------------------------------------------------------- 6855 // Input Events and Focus Management 6856 // ------------------------------------------------------------- 6857 6858 final InputMonitor mInputMonitor = new InputMonitor(this); 6859 private boolean mEventDispatchingEnabled; 6860 6861 @Override 6862 public void pauseKeyDispatching(IBinder _token) { 6863 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6864 "pauseKeyDispatching()")) { 6865 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6866 } 6867 6868 synchronized (mWindowMap) { 6869 WindowToken token = mTokenMap.get(_token); 6870 if (token != null) { 6871 mInputMonitor.pauseDispatchingLw(token); 6872 } 6873 } 6874 } 6875 6876 @Override 6877 public void resumeKeyDispatching(IBinder _token) { 6878 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6879 "resumeKeyDispatching()")) { 6880 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6881 } 6882 6883 synchronized (mWindowMap) { 6884 WindowToken token = mTokenMap.get(_token); 6885 if (token != null) { 6886 mInputMonitor.resumeDispatchingLw(token); 6887 } 6888 } 6889 } 6890 6891 @Override 6892 public void setEventDispatching(boolean enabled) { 6893 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6894 "setEventDispatching()")) { 6895 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6896 } 6897 6898 synchronized (mWindowMap) { 6899 mEventDispatchingEnabled = enabled; 6900 if (mDisplayEnabled) { 6901 mInputMonitor.setEventDispatchingLw(enabled); 6902 } 6903 sendScreenStatusToClientsLocked(); 6904 } 6905 } 6906 6907 @Override 6908 public IBinder getFocusedWindowToken() { 6909 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 6910 "getFocusedWindowToken()")) { 6911 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission."); 6912 } 6913 synchronized (mWindowMap) { 6914 WindowState windowState = getFocusedWindowLocked(); 6915 if (windowState != null) { 6916 return windowState.mClient.asBinder(); 6917 } 6918 return null; 6919 } 6920 } 6921 6922 private WindowState getFocusedWindow() { 6923 synchronized (mWindowMap) { 6924 return getFocusedWindowLocked(); 6925 } 6926 } 6927 6928 private WindowState getFocusedWindowLocked() { 6929 return mCurrentFocus; 6930 } 6931 6932 public boolean detectSafeMode() { 6933 if (!mInputMonitor.waitForInputDevicesReady( 6934 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 6935 Slog.w(TAG, "Devices still not ready after waiting " 6936 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 6937 + " milliseconds before attempting to detect safe mode."); 6938 } 6939 6940 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 6941 KeyEvent.KEYCODE_MENU); 6942 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 6943 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 6944 KeyEvent.KEYCODE_DPAD_CENTER); 6945 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 6946 InputManagerService.BTN_MOUSE); 6947 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 6948 KeyEvent.KEYCODE_VOLUME_DOWN); 6949 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 6950 || volumeDownState > 0; 6951 try { 6952 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 6953 mSafeMode = true; 6954 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 6955 } 6956 } catch (IllegalArgumentException e) { 6957 } 6958 if (mSafeMode) { 6959 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 6960 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 6961 } else { 6962 Log.i(TAG, "SAFE MODE not enabled"); 6963 } 6964 mPolicy.setSafeMode(mSafeMode); 6965 return mSafeMode; 6966 } 6967 6968 public void displayReady() { 6969 displayReady(Display.DEFAULT_DISPLAY); 6970 6971 synchronized(mWindowMap) { 6972 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6973 readForcedDisplaySizeAndDensityLocked(displayContent); 6974 mDisplayReady = true; 6975 } 6976 6977 try { 6978 mActivityManager.updateConfiguration(null); 6979 } catch (RemoteException e) { 6980 } 6981 6982 synchronized(mWindowMap) { 6983 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 6984 PackageManager.FEATURE_TOUCHSCREEN); 6985 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 6986 } 6987 6988 try { 6989 mActivityManager.updateConfiguration(null); 6990 } catch (RemoteException e) { 6991 } 6992 } 6993 6994 private void displayReady(int displayId) { 6995 synchronized(mWindowMap) { 6996 final DisplayContent displayContent = getDisplayContentLocked(displayId); 6997 if (displayContent != null) { 6998 mAnimator.addDisplayLocked(displayId); 6999 synchronized(displayContent.mDisplaySizeLock) { 7000 // Bootstrap the default logical display from the display manager. 7001 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7002 DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId); 7003 if (newDisplayInfo != null) { 7004 displayInfo.copyFrom(newDisplayInfo); 7005 } 7006 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; 7007 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; 7008 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; 7009 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; 7010 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; 7011 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; 7012 displayContent.mBaseDisplayRect.set(0, 0, 7013 displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight); 7014 } 7015 } 7016 } 7017 } 7018 7019 public void systemReady() { 7020 mPolicy.systemReady(); 7021 } 7022 7023 // TODO(multidisplay): Call isScreenOn for each display. 7024 private void sendScreenStatusToClientsLocked() { 7025 final boolean on = mPowerManager.isScreenOn(); 7026 final int numDisplays = mDisplayContents.size(); 7027 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 7028 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 7029 final int numWindows = windows.size(); 7030 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 7031 try { 7032 windows.get(winNdx).mClient.dispatchScreenState(on); 7033 } catch (RemoteException e) { 7034 // Ignored 7035 } 7036 } 7037 } 7038 } 7039 7040 // ------------------------------------------------------------- 7041 // Async Handler 7042 // ------------------------------------------------------------- 7043 7044 final class H extends Handler { 7045 public static final int REPORT_FOCUS_CHANGE = 2; 7046 public static final int REPORT_LOSING_FOCUS = 3; 7047 public static final int DO_TRAVERSAL = 4; 7048 public static final int ADD_STARTING = 5; 7049 public static final int REMOVE_STARTING = 6; 7050 public static final int FINISHED_STARTING = 7; 7051 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 7052 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 7053 public static final int WINDOW_FREEZE_TIMEOUT = 11; 7054 7055 public static final int APP_TRANSITION_TIMEOUT = 13; 7056 public static final int PERSIST_ANIMATION_SCALE = 14; 7057 public static final int FORCE_GC = 15; 7058 public static final int ENABLE_SCREEN = 16; 7059 public static final int APP_FREEZE_TIMEOUT = 17; 7060 public static final int SEND_NEW_CONFIGURATION = 18; 7061 public static final int REPORT_WINDOWS_CHANGE = 19; 7062 public static final int DRAG_START_TIMEOUT = 20; 7063 public static final int DRAG_END_TIMEOUT = 21; 7064 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 7065 public static final int BOOT_TIMEOUT = 23; 7066 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 7067 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 7068 public static final int DO_ANIMATION_CALLBACK = 26; 7069 7070 public static final int DO_DISPLAY_ADDED = 27; 7071 public static final int DO_DISPLAY_REMOVED = 28; 7072 public static final int DO_DISPLAY_CHANGED = 29; 7073 7074 public static final int CLIENT_FREEZE_TIMEOUT = 30; 7075 public static final int TAP_OUTSIDE_STACK = 31; 7076 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 7077 7078 public static final int REMOVE_STARTING_TIMEOUT = 33; 7079 7080 @Override 7081 public void handleMessage(Message msg) { 7082 if (DEBUG_WINDOW_TRACE) { 7083 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 7084 } 7085 switch (msg.what) { 7086 case REPORT_FOCUS_CHANGE: { 7087 WindowState lastFocus; 7088 WindowState newFocus; 7089 7090 synchronized(mWindowMap) { 7091 lastFocus = mLastFocus; 7092 newFocus = mCurrentFocus; 7093 if (lastFocus == newFocus) { 7094 // Focus is not changing, so nothing to do. 7095 return; 7096 } 7097 mLastFocus = newFocus; 7098 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus + 7099 " to " + newFocus); 7100 if (newFocus != null && lastFocus != null 7101 && !newFocus.isDisplayedLw()) { 7102 //Slog.i(TAG, "Delaying loss of focus..."); 7103 mLosingFocus.add(lastFocus); 7104 lastFocus = null; 7105 } 7106 } 7107 7108 //System.out.println("Changing focus from " + lastFocus 7109 // + " to " + newFocus); 7110 if (newFocus != null) { 7111 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus); 7112 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 7113 notifyFocusChanged(); 7114 } 7115 7116 if (lastFocus != null) { 7117 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus); 7118 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 7119 } 7120 } break; 7121 7122 case REPORT_LOSING_FOCUS: { 7123 ArrayList<WindowState> losers; 7124 7125 synchronized(mWindowMap) { 7126 losers = mLosingFocus; 7127 mLosingFocus = new ArrayList<WindowState>(); 7128 } 7129 7130 final int N = losers.size(); 7131 for (int i=0; i<N; i++) { 7132 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " + 7133 losers.get(i)); 7134 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 7135 } 7136 } break; 7137 7138 case DO_TRAVERSAL: { 7139 synchronized(mWindowMap) { 7140 mTraversalScheduled = false; 7141 performLayoutAndPlaceSurfacesLocked(); 7142 } 7143 } break; 7144 7145 case ADD_STARTING: { 7146 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7147 final StartingData sd = wtoken.startingData; 7148 7149 if (sd == null) { 7150 // Animation has been canceled... do nothing. 7151 return; 7152 } 7153 7154 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 7155 + wtoken + ": pkg=" + sd.pkg); 7156 7157 View view = null; 7158 try { 7159 view = mPolicy.addStartingWindow( 7160 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 7161 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags); 7162 } catch (Exception e) { 7163 Slog.w(TAG, "Exception when adding starting window", e); 7164 } 7165 7166 if (view != null) { 7167 boolean abort = false; 7168 7169 synchronized(mWindowMap) { 7170 if (wtoken.removed || wtoken.startingData == null) { 7171 // If the window was successfully added, then 7172 // we need to remove it. 7173 if (wtoken.startingWindow != null) { 7174 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7175 "Aborted starting " + wtoken 7176 + ": removed=" + wtoken.removed 7177 + " startingData=" + wtoken.startingData); 7178 removeStartingWindowTimeout(wtoken); 7179 wtoken.startingWindow = null; 7180 wtoken.startingData = null; 7181 abort = true; 7182 } 7183 } else { 7184 wtoken.startingView = view; 7185 } 7186 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7187 "Added starting " + wtoken 7188 + ": startingWindow=" 7189 + wtoken.startingWindow + " startingView=" 7190 + wtoken.startingView); 7191 } 7192 7193 if (abort) { 7194 try { 7195 mPolicy.removeStartingWindow(wtoken.token, view); 7196 } catch (Exception e) { 7197 Slog.w(TAG, "Exception when removing starting window", e); 7198 } 7199 } 7200 } 7201 } break; 7202 7203 case REMOVE_STARTING_TIMEOUT: { 7204 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7205 Slog.e(TAG, "Starting window " + wtoken + " timed out"); 7206 // Fall through. 7207 } 7208 case REMOVE_STARTING: { 7209 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7210 IBinder token = null; 7211 View view = null; 7212 synchronized (mWindowMap) { 7213 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7214 + wtoken + ": startingWindow=" 7215 + wtoken.startingWindow + " startingView=" 7216 + wtoken.startingView); 7217 if (wtoken.startingWindow != null) { 7218 view = wtoken.startingView; 7219 token = wtoken.token; 7220 wtoken.startingData = null; 7221 wtoken.startingView = null; 7222 wtoken.startingWindow = null; 7223 wtoken.startingDisplayed = false; 7224 } 7225 } 7226 if (view != null) { 7227 try { 7228 mPolicy.removeStartingWindow(token, view); 7229 } catch (Exception e) { 7230 Slog.w(TAG, "Exception when removing starting window", e); 7231 } 7232 } 7233 } break; 7234 7235 case FINISHED_STARTING: { 7236 IBinder token = null; 7237 View view = null; 7238 while (true) { 7239 synchronized (mWindowMap) { 7240 final int N = mFinishedStarting.size(); 7241 if (N <= 0) { 7242 break; 7243 } 7244 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7245 7246 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7247 "Finished starting " + wtoken 7248 + ": startingWindow=" + wtoken.startingWindow 7249 + " startingView=" + wtoken.startingView); 7250 7251 if (wtoken.startingWindow == null) { 7252 continue; 7253 } 7254 7255 view = wtoken.startingView; 7256 token = wtoken.token; 7257 wtoken.startingData = null; 7258 wtoken.startingView = null; 7259 wtoken.startingWindow = null; 7260 wtoken.startingDisplayed = false; 7261 } 7262 7263 try { 7264 mPolicy.removeStartingWindow(token, view); 7265 } catch (Exception e) { 7266 Slog.w(TAG, "Exception when removing starting window", e); 7267 } 7268 } 7269 } break; 7270 7271 case REPORT_APPLICATION_TOKEN_DRAWN: { 7272 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7273 7274 try { 7275 if (DEBUG_VISIBILITY) Slog.v( 7276 TAG, "Reporting drawn in " + wtoken); 7277 wtoken.appToken.windowsDrawn(); 7278 } catch (RemoteException ex) { 7279 } 7280 } break; 7281 7282 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7283 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7284 7285 boolean nowVisible = msg.arg1 != 0; 7286 boolean nowGone = msg.arg2 != 0; 7287 7288 try { 7289 if (DEBUG_VISIBILITY) Slog.v( 7290 TAG, "Reporting visible in " + wtoken 7291 + " visible=" + nowVisible 7292 + " gone=" + nowGone); 7293 if (nowVisible) { 7294 wtoken.appToken.windowsVisible(); 7295 } else { 7296 wtoken.appToken.windowsGone(); 7297 } 7298 } catch (RemoteException ex) { 7299 } 7300 } break; 7301 7302 case WINDOW_FREEZE_TIMEOUT: { 7303 // TODO(multidisplay): Can non-default displays rotate? 7304 synchronized (mWindowMap) { 7305 Slog.w(TAG, "Window freeze timeout expired."); 7306 final WindowList windows = getDefaultWindowListLocked(); 7307 int i = windows.size(); 7308 while (i > 0) { 7309 i--; 7310 WindowState w = windows.get(i); 7311 if (w.mOrientationChanging) { 7312 w.mOrientationChanging = false; 7313 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 7314 - mDisplayFreezeTime); 7315 Slog.w(TAG, "Force clearing orientation change: " + w); 7316 } 7317 } 7318 performLayoutAndPlaceSurfacesLocked(); 7319 } 7320 break; 7321 } 7322 7323 case APP_TRANSITION_TIMEOUT: { 7324 synchronized (mWindowMap) { 7325 if (mAppTransition.isTransitionSet()) { 7326 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT"); 7327 mAppTransition.setTimeout(); 7328 performLayoutAndPlaceSurfacesLocked(); 7329 } 7330 } 7331 break; 7332 } 7333 7334 case PERSIST_ANIMATION_SCALE: { 7335 Settings.Global.putFloat(mContext.getContentResolver(), 7336 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); 7337 Settings.Global.putFloat(mContext.getContentResolver(), 7338 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); 7339 Settings.Global.putFloat(mContext.getContentResolver(), 7340 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale); 7341 break; 7342 } 7343 7344 case FORCE_GC: { 7345 synchronized (mWindowMap) { 7346 // Since we're holding both mWindowMap and mAnimator we don't need to 7347 // hold mAnimator.mLayoutToAnim. 7348 if (mAnimator.mAnimating || mAnimationScheduled) { 7349 // If we are animating, don't do the gc now but 7350 // delay a bit so we don't interrupt the animation. 7351 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 7352 return; 7353 } 7354 // If we are currently rotating the display, it will 7355 // schedule a new message when done. 7356 if (mDisplayFrozen) { 7357 return; 7358 } 7359 } 7360 Runtime.getRuntime().gc(); 7361 break; 7362 } 7363 7364 case ENABLE_SCREEN: { 7365 performEnableScreen(); 7366 break; 7367 } 7368 7369 case APP_FREEZE_TIMEOUT: { 7370 synchronized (mWindowMap) { 7371 Slog.w(TAG, "App freeze timeout expired."); 7372 DisplayContent displayContent = getDefaultDisplayContentLocked(); 7373 final ArrayList<Task> tasks = displayContent.getTasks(); 7374 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 7375 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 7376 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 7377 AppWindowToken tok = tokens.get(tokenNdx); 7378 if (tok.mAppAnimator.freezingScreen) { 7379 Slog.w(TAG, "Force clearing freeze: " + tok); 7380 unsetAppFreezingScreenLocked(tok, true, true); 7381 } 7382 } 7383 } 7384 } 7385 break; 7386 } 7387 7388 case CLIENT_FREEZE_TIMEOUT: { 7389 synchronized (mWindowMap) { 7390 if (mClientFreezingScreen) { 7391 mClientFreezingScreen = false; 7392 mLastFinishedFreezeSource = "client-timeout"; 7393 stopFreezingDisplayLocked(); 7394 } 7395 } 7396 break; 7397 } 7398 7399 case SEND_NEW_CONFIGURATION: { 7400 removeMessages(SEND_NEW_CONFIGURATION); 7401 sendNewConfiguration(); 7402 break; 7403 } 7404 7405 case REPORT_WINDOWS_CHANGE: { 7406 if (mWindowsChanged) { 7407 synchronized (mWindowMap) { 7408 mWindowsChanged = false; 7409 } 7410 notifyWindowsChanged(); 7411 } 7412 break; 7413 } 7414 7415 case DRAG_START_TIMEOUT: { 7416 IBinder win = (IBinder)msg.obj; 7417 if (DEBUG_DRAG) { 7418 Slog.w(TAG, "Timeout starting drag by win " + win); 7419 } 7420 synchronized (mWindowMap) { 7421 // !!! TODO: ANR the app that has failed to start the drag in time 7422 if (mDragState != null) { 7423 mDragState.unregister(); 7424 mInputMonitor.updateInputWindowsLw(true /*force*/); 7425 mDragState.reset(); 7426 mDragState = null; 7427 } 7428 } 7429 break; 7430 } 7431 7432 case DRAG_END_TIMEOUT: { 7433 IBinder win = (IBinder)msg.obj; 7434 if (DEBUG_DRAG) { 7435 Slog.w(TAG, "Timeout ending drag to win " + win); 7436 } 7437 synchronized (mWindowMap) { 7438 // !!! TODO: ANR the drag-receiving app 7439 if (mDragState != null) { 7440 mDragState.mDragResult = false; 7441 mDragState.endDragLw(); 7442 } 7443 } 7444 break; 7445 } 7446 7447 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7448 notifyHardKeyboardStatusChange(); 7449 break; 7450 } 7451 7452 case BOOT_TIMEOUT: { 7453 performBootTimeout(); 7454 break; 7455 } 7456 7457 case WAITING_FOR_DRAWN_TIMEOUT: { 7458 Pair<WindowState, IRemoteCallback> pair; 7459 synchronized (mWindowMap) { 7460 pair = (Pair<WindowState, IRemoteCallback>)msg.obj; 7461 Slog.w(TAG, "Timeout waiting for drawn: " + pair.first); 7462 if (!mWaitingForDrawn.remove(pair)) { 7463 return; 7464 } 7465 } 7466 try { 7467 pair.second.sendResult(null); 7468 } catch (RemoteException e) { 7469 } 7470 break; 7471 } 7472 7473 case SHOW_STRICT_MODE_VIOLATION: { 7474 showStrictModeViolation(msg.arg1, msg.arg2); 7475 break; 7476 } 7477 7478 case DO_ANIMATION_CALLBACK: { 7479 try { 7480 ((IRemoteCallback)msg.obj).sendResult(null); 7481 } catch (RemoteException e) { 7482 } 7483 break; 7484 } 7485 7486 case DO_DISPLAY_ADDED: 7487 synchronized (mWindowMap) { 7488 handleDisplayAddedLocked(msg.arg1); 7489 } 7490 break; 7491 7492 case DO_DISPLAY_REMOVED: 7493 synchronized (mWindowMap) { 7494 handleDisplayRemovedLocked(msg.arg1); 7495 } 7496 break; 7497 7498 case DO_DISPLAY_CHANGED: 7499 synchronized (mWindowMap) { 7500 handleDisplayChangedLocked(msg.arg1); 7501 } 7502 break; 7503 7504 case TAP_OUTSIDE_STACK: { 7505 int stackId; 7506 synchronized (mWindowMap) { 7507 stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2); 7508 } 7509 if (stackId >= 0) { 7510 try { 7511 mActivityManager.setFocusedStack(stackId); 7512 } catch (RemoteException e) { 7513 } 7514 } 7515 } 7516 break; 7517 case NOTIFY_ACTIVITY_DRAWN: 7518 try { 7519 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 7520 } catch (RemoteException e) { 7521 } 7522 break; 7523 } 7524 if (DEBUG_WINDOW_TRACE) { 7525 Slog.v(TAG, "handleMessage: exit"); 7526 } 7527 } 7528 } 7529 7530 // ------------------------------------------------------------- 7531 // IWindowManager API 7532 // ------------------------------------------------------------- 7533 7534 @Override 7535 public IWindowSession openSession(IInputMethodClient client, 7536 IInputContext inputContext) { 7537 if (client == null) throw new IllegalArgumentException("null client"); 7538 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7539 Session session = new Session(this, client, inputContext); 7540 return session; 7541 } 7542 7543 @Override 7544 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7545 synchronized (mWindowMap) { 7546 // The focus for the client is the window immediately below 7547 // where we would place the input method window. 7548 int idx = findDesiredInputMethodWindowIndexLocked(false); 7549 if (idx > 0) { 7550 // TODO(multidisplay): IMEs are only supported on the default display. 7551 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 7552 if (DEBUG_INPUT_METHOD) { 7553 Slog.i(TAG, "Desired input method target: " + imFocus); 7554 Slog.i(TAG, "Current focus: " + mCurrentFocus); 7555 Slog.i(TAG, "Last focus: " + mLastFocus); 7556 } 7557 if (imFocus != null) { 7558 // This may be a starting window, in which case we still want 7559 // to count it as okay. 7560 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7561 && imFocus.mAppToken != null) { 7562 // The client has definitely started, so it really should 7563 // have a window in this app token. Let's look for it. 7564 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7565 WindowState w = imFocus.mAppToken.windows.get(i); 7566 if (w != imFocus) { 7567 Log.i(TAG, "Switching to real app window: " + w); 7568 imFocus = w; 7569 break; 7570 } 7571 } 7572 } 7573 if (DEBUG_INPUT_METHOD) { 7574 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7575 if (imFocus.mSession.mClient != null) { 7576 Slog.i(TAG, "IM target client binder: " 7577 + imFocus.mSession.mClient.asBinder()); 7578 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 7579 } 7580 } 7581 if (imFocus.mSession.mClient != null && 7582 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7583 return true; 7584 } 7585 } 7586 } 7587 7588 // Okay, how about this... what is the current focus? 7589 // It seems in some cases we may not have moved the IM 7590 // target window, such as when it was in a pop-up window, 7591 // so let's also look at the current focus. (An example: 7592 // go to Gmail, start searching so the keyboard goes up, 7593 // press home. Sometimes the IME won't go down.) 7594 // Would be nice to fix this more correctly, but it's 7595 // way at the end of a release, and this should be good enough. 7596 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 7597 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7598 return true; 7599 } 7600 } 7601 return false; 7602 } 7603 7604 @Override 7605 public void getInitialDisplaySize(int displayId, Point size) { 7606 synchronized (mWindowMap) { 7607 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7608 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7609 synchronized(displayContent.mDisplaySizeLock) { 7610 size.x = displayContent.mInitialDisplayWidth; 7611 size.y = displayContent.mInitialDisplayHeight; 7612 } 7613 } 7614 } 7615 } 7616 7617 @Override 7618 public void getBaseDisplaySize(int displayId, Point size) { 7619 synchronized (mWindowMap) { 7620 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7621 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7622 synchronized(displayContent.mDisplaySizeLock) { 7623 size.x = displayContent.mBaseDisplayWidth; 7624 size.y = displayContent.mBaseDisplayHeight; 7625 } 7626 } 7627 } 7628 } 7629 7630 @Override 7631 public void setForcedDisplaySize(int displayId, int width, int height) { 7632 if (mContext.checkCallingOrSelfPermission( 7633 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7634 PackageManager.PERMISSION_GRANTED) { 7635 throw new SecurityException("Must hold permission " + 7636 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7637 } 7638 if (displayId != Display.DEFAULT_DISPLAY) { 7639 throw new IllegalArgumentException("Can only set the default display"); 7640 } 7641 final long ident = Binder.clearCallingIdentity(); 7642 try { 7643 synchronized(mWindowMap) { 7644 // Set some sort of reasonable bounds on the size of the display that we 7645 // will try to emulate. 7646 final int MIN_WIDTH = 200; 7647 final int MIN_HEIGHT = 200; 7648 final int MAX_SCALE = 2; 7649 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7650 if (displayContent != null) { 7651 width = Math.min(Math.max(width, MIN_WIDTH), 7652 displayContent.mInitialDisplayWidth * MAX_SCALE); 7653 height = Math.min(Math.max(height, MIN_HEIGHT), 7654 displayContent.mInitialDisplayHeight * MAX_SCALE); 7655 setForcedDisplaySizeLocked(displayContent, width, height); 7656 Settings.Global.putString(mContext.getContentResolver(), 7657 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 7658 } 7659 } 7660 } finally { 7661 Binder.restoreCallingIdentity(ident); 7662 } 7663 } 7664 7665 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 7666 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 7667 Settings.Global.DISPLAY_SIZE_FORCED); 7668 if (sizeStr == null || sizeStr.length() == 0) { 7669 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 7670 } 7671 if (sizeStr != null && sizeStr.length() > 0) { 7672 final int pos = sizeStr.indexOf(','); 7673 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 7674 int width, height; 7675 try { 7676 width = Integer.parseInt(sizeStr.substring(0, pos)); 7677 height = Integer.parseInt(sizeStr.substring(pos+1)); 7678 synchronized(displayContent.mDisplaySizeLock) { 7679 if (displayContent.mBaseDisplayWidth != width 7680 || displayContent.mBaseDisplayHeight != height) { 7681 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 7682 displayContent.mBaseDisplayWidth = width; 7683 displayContent.mBaseDisplayHeight = height; 7684 } 7685 } 7686 } catch (NumberFormatException ex) { 7687 } 7688 } 7689 } 7690 String densityStr = Settings.Global.getString(mContext.getContentResolver(), 7691 Settings.Global.DISPLAY_DENSITY_FORCED); 7692 if (densityStr == null || densityStr.length() == 0) { 7693 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 7694 } 7695 if (densityStr != null && densityStr.length() > 0) { 7696 int density; 7697 try { 7698 density = Integer.parseInt(densityStr); 7699 synchronized(displayContent.mDisplaySizeLock) { 7700 if (displayContent.mBaseDisplayDensity != density) { 7701 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 7702 displayContent.mBaseDisplayDensity = density; 7703 } 7704 } 7705 } catch (NumberFormatException ex) { 7706 } 7707 } 7708 } 7709 7710 // displayContent must not be null 7711 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 7712 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7713 7714 synchronized(displayContent.mDisplaySizeLock) { 7715 displayContent.mBaseDisplayWidth = width; 7716 displayContent.mBaseDisplayHeight = height; 7717 } 7718 reconfigureDisplayLocked(displayContent); 7719 } 7720 7721 @Override 7722 public void clearForcedDisplaySize(int displayId) { 7723 if (mContext.checkCallingOrSelfPermission( 7724 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7725 PackageManager.PERMISSION_GRANTED) { 7726 throw new SecurityException("Must hold permission " + 7727 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7728 } 7729 if (displayId != Display.DEFAULT_DISPLAY) { 7730 throw new IllegalArgumentException("Can only set the default display"); 7731 } 7732 final long ident = Binder.clearCallingIdentity(); 7733 try { 7734 synchronized(mWindowMap) { 7735 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7736 if (displayContent != null) { 7737 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 7738 displayContent.mInitialDisplayHeight); 7739 Settings.Global.putString(mContext.getContentResolver(), 7740 Settings.Global.DISPLAY_SIZE_FORCED, ""); 7741 } 7742 } 7743 } finally { 7744 Binder.restoreCallingIdentity(ident); 7745 } 7746 } 7747 7748 @Override 7749 public int getInitialDisplayDensity(int displayId) { 7750 synchronized (mWindowMap) { 7751 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7752 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7753 synchronized(displayContent.mDisplaySizeLock) { 7754 return displayContent.mInitialDisplayDensity; 7755 } 7756 } 7757 } 7758 return -1; 7759 } 7760 7761 @Override 7762 public int getBaseDisplayDensity(int displayId) { 7763 synchronized (mWindowMap) { 7764 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7765 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7766 synchronized(displayContent.mDisplaySizeLock) { 7767 return displayContent.mBaseDisplayDensity; 7768 } 7769 } 7770 } 7771 return -1; 7772 } 7773 7774 @Override 7775 public void setForcedDisplayDensity(int displayId, int density) { 7776 if (mContext.checkCallingOrSelfPermission( 7777 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7778 PackageManager.PERMISSION_GRANTED) { 7779 throw new SecurityException("Must hold permission " + 7780 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7781 } 7782 if (displayId != Display.DEFAULT_DISPLAY) { 7783 throw new IllegalArgumentException("Can only set the default display"); 7784 } 7785 final long ident = Binder.clearCallingIdentity(); 7786 try { 7787 synchronized(mWindowMap) { 7788 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7789 if (displayContent != null) { 7790 setForcedDisplayDensityLocked(displayContent, density); 7791 Settings.Global.putString(mContext.getContentResolver(), 7792 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 7793 } 7794 } 7795 } finally { 7796 Binder.restoreCallingIdentity(ident); 7797 } 7798 } 7799 7800 // displayContent must not be null 7801 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 7802 Slog.i(TAG, "Using new display density: " + density); 7803 7804 synchronized(displayContent.mDisplaySizeLock) { 7805 displayContent.mBaseDisplayDensity = density; 7806 } 7807 reconfigureDisplayLocked(displayContent); 7808 } 7809 7810 @Override 7811 public void clearForcedDisplayDensity(int displayId) { 7812 if (mContext.checkCallingOrSelfPermission( 7813 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7814 PackageManager.PERMISSION_GRANTED) { 7815 throw new SecurityException("Must hold permission " + 7816 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7817 } 7818 if (displayId != Display.DEFAULT_DISPLAY) { 7819 throw new IllegalArgumentException("Can only set the default display"); 7820 } 7821 final long ident = Binder.clearCallingIdentity(); 7822 try { 7823 synchronized(mWindowMap) { 7824 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7825 if (displayContent != null) { 7826 setForcedDisplayDensityLocked(displayContent, 7827 displayContent.mInitialDisplayDensity); 7828 Settings.Global.putString(mContext.getContentResolver(), 7829 Settings.Global.DISPLAY_DENSITY_FORCED, ""); 7830 } 7831 } 7832 } finally { 7833 Binder.restoreCallingIdentity(ident); 7834 } 7835 } 7836 7837 // displayContent must not be null 7838 private void reconfigureDisplayLocked(DisplayContent displayContent) { 7839 // TODO: Multidisplay: for now only use with default display. 7840 configureDisplayPolicyLocked(displayContent); 7841 displayContent.layoutNeeded = true; 7842 7843 boolean configChanged = updateOrientationFromAppTokensLocked(false); 7844 mTempConfiguration.setToDefaults(); 7845 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 7846 if (computeScreenConfigurationLocked(mTempConfiguration)) { 7847 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 7848 configChanged = true; 7849 } 7850 } 7851 7852 if (configChanged) { 7853 mWaitingForConfig = true; 7854 startFreezingDisplayLocked(false, 0, 0); 7855 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 7856 } 7857 7858 performLayoutAndPlaceSurfacesLocked(); 7859 } 7860 7861 private void configureDisplayPolicyLocked(DisplayContent displayContent) { 7862 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 7863 displayContent.mBaseDisplayWidth, 7864 displayContent.mBaseDisplayHeight, 7865 displayContent.mBaseDisplayDensity); 7866 7867 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7868 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 7869 displayInfo.overscanLeft, displayInfo.overscanTop, 7870 displayInfo.overscanRight, displayInfo.overscanBottom); 7871 } 7872 7873 @Override 7874 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 7875 if (mContext.checkCallingOrSelfPermission( 7876 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7877 PackageManager.PERMISSION_GRANTED) { 7878 throw new SecurityException("Must hold permission " + 7879 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7880 } 7881 final long ident = Binder.clearCallingIdentity(); 7882 try { 7883 synchronized(mWindowMap) { 7884 DisplayContent displayContent = getDisplayContentLocked(displayId); 7885 if (displayContent != null) { 7886 setOverscanLocked(displayContent, left, top, right, bottom); 7887 } 7888 } 7889 } finally { 7890 Binder.restoreCallingIdentity(ident); 7891 } 7892 } 7893 7894 private void setOverscanLocked(DisplayContent displayContent, 7895 int left, int top, int right, int bottom) { 7896 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7897 synchronized (displayContent.mDisplaySizeLock) { 7898 displayInfo.overscanLeft = left; 7899 displayInfo.overscanTop = top; 7900 displayInfo.overscanRight = right; 7901 displayInfo.overscanBottom = bottom; 7902 } 7903 7904 mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom); 7905 mDisplaySettings.writeSettingsLocked(); 7906 7907 reconfigureDisplayLocked(displayContent); 7908 } 7909 7910 // ------------------------------------------------------------- 7911 // Internals 7912 // ------------------------------------------------------------- 7913 7914 final WindowState windowForClientLocked(Session session, IWindow client, 7915 boolean throwOnError) { 7916 return windowForClientLocked(session, client.asBinder(), throwOnError); 7917 } 7918 7919 final WindowState windowForClientLocked(Session session, IBinder client, 7920 boolean throwOnError) { 7921 WindowState win = mWindowMap.get(client); 7922 if (localLOGV) Slog.v( 7923 TAG, "Looking up client " + client + ": " + win); 7924 if (win == null) { 7925 RuntimeException ex = new IllegalArgumentException( 7926 "Requested window " + client + " does not exist"); 7927 if (throwOnError) { 7928 throw ex; 7929 } 7930 Slog.w(TAG, "Failed looking up window", ex); 7931 return null; 7932 } 7933 if (session != null && win.mSession != session) { 7934 RuntimeException ex = new IllegalArgumentException( 7935 "Requested window " + client + " is in session " + 7936 win.mSession + ", not " + session); 7937 if (throwOnError) { 7938 throw ex; 7939 } 7940 Slog.w(TAG, "Failed looking up window", ex); 7941 return null; 7942 } 7943 7944 return win; 7945 } 7946 7947 final void rebuildAppWindowListLocked() { 7948 // TODO: Multidisplay, when ActivityStacks and tasks exist on more than one display. 7949 rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); 7950 } 7951 7952 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 7953 final WindowList windows = displayContent.getWindowList(); 7954 int NW = windows.size(); 7955 int i; 7956 int lastBelow = -1; 7957 int numRemoved = 0; 7958 7959 if (mRebuildTmp.length < NW) { 7960 mRebuildTmp = new WindowState[NW+10]; 7961 } 7962 7963 // First remove all existing app windows. 7964 i=0; 7965 while (i < NW) { 7966 WindowState w = windows.get(i); 7967 if (w.mAppToken != null) { 7968 WindowState win = windows.remove(i); 7969 win.mRebuilding = true; 7970 mRebuildTmp[numRemoved] = win; 7971 mWindowsChanged = true; 7972 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win); 7973 NW--; 7974 numRemoved++; 7975 continue; 7976 } else if (lastBelow == i-1) { 7977 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 7978 lastBelow = i; 7979 } 7980 } 7981 i++; 7982 } 7983 7984 // Keep whatever windows were below the app windows still below, 7985 // by skipping them. 7986 lastBelow++; 7987 i = lastBelow; 7988 7989 // First add all of the exiting app tokens... these are no longer 7990 // in the main app list, but still have windows shown. We put them 7991 // in the back because now that the animation is over we no longer 7992 // will care about them. 7993 AppTokenList exitingAppTokens = displayContent.mExitingAppTokens; 7994 int NT = exitingAppTokens.size(); 7995 for (int j=0; j<NT; j++) { 7996 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 7997 } 7998 7999 // And add in the still active app tokens in Z order. 8000 final ArrayList<Task> tasks = displayContent.getTasks(); 8001 final int numTasks = tasks.size(); 8002 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 8003 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8004 final int numTokens = tokens.size(); 8005 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 8006 final AppWindowToken wtoken = tokens.get(tokenNdx); 8007 i = reAddAppWindowsLocked(displayContent, i, wtoken); 8008 } 8009 } 8010 8011 i -= lastBelow; 8012 if (i != numRemoved) { 8013 Slog.w(TAG, "Rebuild removed " + numRemoved + " windows but added " + i, 8014 new RuntimeException("here").fillInStackTrace()); 8015 for (i=0; i<numRemoved; i++) { 8016 WindowState ws = mRebuildTmp[i]; 8017 if (ws.mRebuilding) { 8018 StringWriter sw = new StringWriter(); 8019 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 8020 ws.dump(pw, "", true); 8021 pw.flush(); 8022 Slog.w(TAG, "This window was lost: " + ws); 8023 Slog.w(TAG, sw.toString()); 8024 ws.mWinAnimator.destroySurfaceLocked(); 8025 } 8026 } 8027 Slog.w(TAG, "Current app token list:"); 8028 dumpAppTokensLocked(); 8029 Slog.w(TAG, "Final window list:"); 8030 dumpWindowsLocked(); 8031 } 8032 } 8033 8034 private final void assignLayersLocked(WindowList windows) { 8035 int N = windows.size(); 8036 int curBaseLayer = 0; 8037 int curLayer = 0; 8038 int i; 8039 8040 if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows, 8041 new RuntimeException("here").fillInStackTrace()); 8042 8043 boolean anyLayerChanged = false; 8044 8045 for (i=0; i<N; i++) { 8046 final WindowState w = windows.get(i); 8047 final WindowStateAnimator winAnimator = w.mWinAnimator; 8048 boolean layerChanged = false; 8049 int oldLayer = w.mLayer; 8050 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 8051 || (i > 0 && w.mIsWallpaper)) { 8052 curLayer += WINDOW_LAYER_MULTIPLIER; 8053 w.mLayer = curLayer; 8054 } else { 8055 curBaseLayer = curLayer = w.mBaseLayer; 8056 w.mLayer = curLayer; 8057 } 8058 if (w.mLayer != oldLayer) { 8059 layerChanged = true; 8060 anyLayerChanged = true; 8061 } 8062 final AppWindowToken wtoken = w.mAppToken; 8063 oldLayer = winAnimator.mAnimLayer; 8064 if (w.mTargetAppToken != null) { 8065 winAnimator.mAnimLayer = 8066 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 8067 } else if (wtoken != null) { 8068 winAnimator.mAnimLayer = 8069 w.mLayer + wtoken.mAppAnimator.animLayerAdjustment; 8070 } else { 8071 winAnimator.mAnimLayer = w.mLayer; 8072 } 8073 if (w.mIsImWindow) { 8074 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 8075 } else if (w.mIsWallpaper) { 8076 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 8077 } 8078 if (winAnimator.mAnimLayer != oldLayer) { 8079 layerChanged = true; 8080 anyLayerChanged = true; 8081 } 8082 if (layerChanged && w.getStack().isDimming(winAnimator)) { 8083 // Force an animation pass just to update the mDimLayer layer. 8084 scheduleAnimationLocked(); 8085 } 8086 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 8087 + "mBase=" + w.mBaseLayer 8088 + " mLayer=" + w.mLayer 8089 + (wtoken == null ? 8090 "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment) 8091 + " =mAnimLayer=" + winAnimator.mAnimLayer); 8092 //System.out.println( 8093 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 8094 } 8095 8096 //TODO (multidisplay): Magnification is supported only for the default display. 8097 if (mDisplayMagnifier != null && anyLayerChanged 8098 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) { 8099 mDisplayMagnifier.onWindowLayersChangedLocked(); 8100 } 8101 } 8102 8103 private final void performLayoutAndPlaceSurfacesLocked() { 8104 int loopCount = 6; 8105 do { 8106 mTraversalScheduled = false; 8107 performLayoutAndPlaceSurfacesLockedLoop(); 8108 mH.removeMessages(H.DO_TRAVERSAL); 8109 loopCount--; 8110 } while (mTraversalScheduled && loopCount > 0); 8111 mInnerFields.mWallpaperActionPending = false; 8112 } 8113 8114 private boolean mInLayout = false; 8115 private final void performLayoutAndPlaceSurfacesLockedLoop() { 8116 if (mInLayout) { 8117 if (DEBUG) { 8118 throw new RuntimeException("Recursive call!"); 8119 } 8120 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 8121 + Debug.getCallers(3)); 8122 return; 8123 } 8124 8125 if (mWaitingForConfig) { 8126 // Our configuration has changed (most likely rotation), but we 8127 // don't yet have the complete configuration to report to 8128 // applications. Don't do any window layout until we have it. 8129 return; 8130 } 8131 8132 if (!mDisplayReady) { 8133 // Not yet initialized, nothing to do. 8134 return; 8135 } 8136 8137 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 8138 mInLayout = true; 8139 boolean recoveringMemory = false; 8140 8141 try { 8142 if (mForceRemoves != null) { 8143 recoveringMemory = true; 8144 // Wait a little bit for things to settle down, and off we go. 8145 for (int i=0; i<mForceRemoves.size(); i++) { 8146 WindowState ws = mForceRemoves.get(i); 8147 Slog.i(TAG, "Force removing: " + ws); 8148 removeWindowInnerLocked(ws.mSession, ws); 8149 } 8150 mForceRemoves = null; 8151 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 8152 Object tmp = new Object(); 8153 synchronized (tmp) { 8154 try { 8155 tmp.wait(250); 8156 } catch (InterruptedException e) { 8157 } 8158 } 8159 } 8160 } catch (RuntimeException e) { 8161 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 8162 } 8163 8164 try { 8165 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 8166 8167 mInLayout = false; 8168 8169 if (needsLayout()) { 8170 if (++mLayoutRepeatCount < 6) { 8171 requestTraversalLocked(); 8172 } else { 8173 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 8174 mLayoutRepeatCount = 0; 8175 } 8176 } else { 8177 mLayoutRepeatCount = 0; 8178 } 8179 8180 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 8181 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 8182 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE); 8183 } 8184 } catch (RuntimeException e) { 8185 mInLayout = false; 8186 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 8187 } 8188 8189 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 8190 } 8191 8192 private final void performLayoutLockedInner(final DisplayContent displayContent, 8193 boolean initial, boolean updateInputWindows) { 8194 if (!displayContent.layoutNeeded) { 8195 return; 8196 } 8197 displayContent.layoutNeeded = false; 8198 WindowList windows = displayContent.getWindowList(); 8199 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 8200 8201 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8202 final int dw = displayInfo.logicalWidth; 8203 final int dh = displayInfo.logicalHeight; 8204 8205 final int NFW = mFakeWindows.size(); 8206 for (int i=0; i<NFW; i++) { 8207 mFakeWindows.get(i).layout(dw, dh); 8208 } 8209 8210 final int N = windows.size(); 8211 int i; 8212 8213 if (DEBUG_LAYOUT) { 8214 Slog.v(TAG, "-------------------------------------"); 8215 Slog.v(TAG, "performLayout: needed=" 8216 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 8217 } 8218 8219 WindowStateAnimator universeBackground = null; 8220 8221 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); 8222 if (isDefaultDisplay) { 8223 // Not needed on non-default displays. 8224 mSystemDecorLayer = mPolicy.getSystemDecorLayerLw(); 8225 mScreenRect.set(0, 0, dw, dh); 8226 } 8227 8228 mPolicy.getContentRectLw(mTmpContentRect); 8229 displayContent.setStackBoxSize(mTmpContentRect); 8230 8231 int seq = mLayoutSeq+1; 8232 if (seq < 0) seq = 0; 8233 mLayoutSeq = seq; 8234 8235 boolean behindDream = false; 8236 8237 // First perform layout of any root windows (not attached 8238 // to another window). 8239 int topAttached = -1; 8240 for (i = N-1; i >= 0; i--) { 8241 final WindowState win = windows.get(i); 8242 8243 // Don't do layout of a window if it is not visible, or 8244 // soon won't be visible, to avoid wasting time and funky 8245 // changes while a window is animating away. 8246 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) 8247 || win.isGoneForLayoutLw(); 8248 8249 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 8250 Slog.v(TAG, "1ST PASS " + win 8251 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 8252 + " mLayoutAttached=" + win.mLayoutAttached 8253 + " screen changed=" + win.isConfigChanged()); 8254 final AppWindowToken atoken = win.mAppToken; 8255 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 8256 + win.mViewVisibility + " mRelayoutCalled=" 8257 + win.mRelayoutCalled + " hidden=" 8258 + win.mRootToken.hidden + " hiddenRequested=" 8259 + (atoken != null && atoken.hiddenRequested) 8260 + " mAttachedHidden=" + win.mAttachedHidden); 8261 else Slog.v(TAG, " VIS: mViewVisibility=" 8262 + win.mViewVisibility + " mRelayoutCalled=" 8263 + win.mRelayoutCalled + " hidden=" 8264 + win.mRootToken.hidden + " hiddenRequested=" 8265 + (atoken != null && atoken.hiddenRequested) 8266 + " mAttachedHidden=" + win.mAttachedHidden); 8267 } 8268 8269 // If this view is GONE, then skip it -- keep the current 8270 // frame, and let the caller know so they can ignore it 8271 // if they want. (We do the normal layout for INVISIBLE 8272 // windows, since that means "perform layout as normal, 8273 // just don't display"). 8274 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 8275 || win.mAttrs.type == TYPE_KEYGUARD && win.isConfigChanged() 8276 || mOpeningApps.contains(win.mAppToken) 8277 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8278 if (!win.mLayoutAttached) { 8279 if (initial) { 8280 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8281 win.mContentChanged = false; 8282 } 8283 if (win.mAttrs.type == TYPE_DREAM) { 8284 // Don't layout windows behind a dream, so that if it 8285 // does stuff like hide the status bar we won't get a 8286 // bad transition when it goes away. 8287 behindDream = true; 8288 } 8289 win.mLayoutNeeded = false; 8290 win.prelayout(); 8291 mPolicy.layoutWindowLw(win, win.mAttrs, null); 8292 win.mLayoutSeq = seq; 8293 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8294 + win.mFrame + " mContainingFrame=" 8295 + win.mContainingFrame + " mDisplayFrame=" 8296 + win.mDisplayFrame); 8297 } else { 8298 if (topAttached < 0) topAttached = i; 8299 } 8300 } 8301 if (win.mViewVisibility == View.VISIBLE 8302 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 8303 && universeBackground == null) { 8304 universeBackground = win.mWinAnimator; 8305 } 8306 } 8307 8308 if (mAnimator.mUniverseBackground != universeBackground) { 8309 mFocusMayChange = true; 8310 mAnimator.mUniverseBackground = universeBackground; 8311 } 8312 8313 boolean attachedBehindDream = false; 8314 8315 // Now perform layout of attached windows, which usually 8316 // depend on the position of the window they are attached to. 8317 // XXX does not deal with windows that are attached to windows 8318 // that are themselves attached. 8319 for (i = topAttached; i >= 0; i--) { 8320 final WindowState win = windows.get(i); 8321 8322 if (win.mLayoutAttached) { 8323 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 8324 + " mHaveFrame=" + win.mHaveFrame 8325 + " mViewVisibility=" + win.mViewVisibility 8326 + " mRelayoutCalled=" + win.mRelayoutCalled); 8327 // If this view is GONE, then skip it -- keep the current 8328 // frame, and let the caller know so they can ignore it 8329 // if they want. (We do the normal layout for INVISIBLE 8330 // windows, since that means "perform layout as normal, 8331 // just don't display"). 8332 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) { 8333 continue; 8334 } 8335 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8336 || !win.mHaveFrame || win.mLayoutNeeded) { 8337 if (initial) { 8338 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8339 win.mContentChanged = false; 8340 } 8341 win.mLayoutNeeded = false; 8342 win.prelayout(); 8343 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 8344 win.mLayoutSeq = seq; 8345 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8346 + win.mFrame + " mContainingFrame=" 8347 + win.mContainingFrame + " mDisplayFrame=" 8348 + win.mDisplayFrame); 8349 } 8350 } else if (win.mAttrs.type == TYPE_DREAM) { 8351 // Don't layout windows behind a dream, so that if it 8352 // does stuff like hide the status bar we won't get a 8353 // bad transition when it goes away. 8354 attachedBehindDream = behindDream; 8355 } 8356 } 8357 8358 // Window frames may have changed. Tell the input dispatcher about it. 8359 mInputMonitor.setUpdateInputWindowsNeededLw(); 8360 if (updateInputWindows) { 8361 mInputMonitor.updateInputWindowsLw(false /*force*/); 8362 } 8363 8364 mPolicy.finishLayoutLw(); 8365 } 8366 8367 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8368 // If the screen is currently frozen or off, then keep 8369 // it frozen/off until this window draws at its new 8370 // orientation. 8371 if (!okToDisplay()) { 8372 if (DEBUG_ORIENTATION) Slog.v(TAG, 8373 "Changing surface while display frozen: " + w); 8374 w.mOrientationChanging = true; 8375 w.mLastFreezeDuration = 0; 8376 mInnerFields.mOrientationChangeComplete = false; 8377 if (!mWindowsFreezingScreen) { 8378 mWindowsFreezingScreen = true; 8379 // XXX should probably keep timeout from 8380 // when we first froze the display. 8381 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8382 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 8383 WINDOW_FREEZE_TIMEOUT_DURATION); 8384 } 8385 } 8386 } 8387 8388 /** 8389 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8390 * @param windows List of windows on default display. 8391 * @return bitmap indicating if another pass through layout must be made. 8392 */ 8393 public int handleAppTransitionReadyLocked(WindowList windows) { 8394 int changes = 0; 8395 int i; 8396 int NN = mOpeningApps.size(); 8397 boolean goodToGo = true; 8398 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8399 "Checking " + NN + " opening apps (frozen=" 8400 + mDisplayFrozen + " timeout=" 8401 + mAppTransition.isTimeout() + ")..."); 8402 if (!mDisplayFrozen && !mAppTransition.isTimeout()) { 8403 // If the display isn't frozen, wait to do anything until 8404 // all of the apps are ready. Otherwise just go because 8405 // we'll unfreeze the display when everyone is ready. 8406 for (i=0; i<NN && goodToGo; i++) { 8407 AppWindowToken wtoken = mOpeningApps.get(i); 8408 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8409 "Check opening app=" + wtoken + ": allDrawn=" 8410 + wtoken.allDrawn + " startingDisplayed=" 8411 + wtoken.startingDisplayed + " startingMoved=" 8412 + wtoken.startingMoved); 8413 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8414 && !wtoken.startingMoved) { 8415 goodToGo = false; 8416 } 8417 } 8418 } 8419 if (goodToGo) { 8420 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8421 int transit = mAppTransition.getAppTransition(); 8422 if (mSkipAppTransitionAnimation) { 8423 transit = AppTransition.TRANSIT_UNSET; 8424 } 8425 mAppTransition.goodToGo(); 8426 mStartingIconInTransition = false; 8427 mSkipAppTransitionAnimation = false; 8428 8429 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8430 8431 rebuildAppWindowListLocked(); 8432 8433 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8434 WindowState oldWallpaper = 8435 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8436 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8437 ? null : mWallpaperTarget; 8438 8439 mInnerFields.mWallpaperMayChange = false; 8440 8441 // The top-most window will supply the layout params, 8442 // and we will determine it below. 8443 LayoutParams animLp = null; 8444 int bestAnimLayer = -1; 8445 boolean fullscreenAnim = false; 8446 8447 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8448 "New wallpaper target=" + mWallpaperTarget 8449 + ", oldWallpaper=" + oldWallpaper 8450 + ", lower target=" + mLowerWallpaperTarget 8451 + ", upper target=" + mUpperWallpaperTarget); 8452 8453 boolean openingAppHasWallpaper = false; 8454 boolean closingAppHasWallpaper = false; 8455 final AppWindowToken lowerWallpaperAppToken; 8456 final AppWindowToken upperWallpaperAppToken; 8457 if (mLowerWallpaperTarget == null) { 8458 lowerWallpaperAppToken = upperWallpaperAppToken = null; 8459 } else { 8460 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken; 8461 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken; 8462 } 8463 8464 // Do a first pass through the tokens for two 8465 // things: 8466 // (1) Determine if both the closing and opening 8467 // app token sets are wallpaper targets, in which 8468 // case special animations are needed 8469 // (since the wallpaper needs to stay static 8470 // behind them). 8471 // (2) Find the layout params of the top-most 8472 // application window in the tokens, which is 8473 // what will control the animation theme. 8474 final int NC = mClosingApps.size(); 8475 NN = NC + mOpeningApps.size(); 8476 for (i=0; i<NN; i++) { 8477 final AppWindowToken wtoken; 8478 if (i < NC) { 8479 wtoken = mClosingApps.get(i); 8480 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8481 closingAppHasWallpaper = true; 8482 } 8483 } else { 8484 wtoken = mOpeningApps.get(i - NC); 8485 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8486 openingAppHasWallpaper = true; 8487 } 8488 } 8489 8490 if (wtoken.appFullscreen) { 8491 WindowState ws = wtoken.findMainWindow(); 8492 if (ws != null) { 8493 animLp = ws.mAttrs; 8494 bestAnimLayer = ws.mLayer; 8495 fullscreenAnim = true; 8496 } 8497 } else if (!fullscreenAnim) { 8498 WindowState ws = wtoken.findMainWindow(); 8499 if (ws != null) { 8500 if (ws.mLayer > bestAnimLayer) { 8501 animLp = ws.mAttrs; 8502 bestAnimLayer = ws.mLayer; 8503 } 8504 } 8505 } 8506 } 8507 8508 mAnimateWallpaperWithTarget = false; 8509 if (closingAppHasWallpaper && openingAppHasWallpaper) { 8510 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!"); 8511 switch (transit) { 8512 case AppTransition.TRANSIT_ACTIVITY_OPEN: 8513 case AppTransition.TRANSIT_TASK_OPEN: 8514 case AppTransition.TRANSIT_TASK_TO_FRONT: 8515 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN; 8516 break; 8517 case AppTransition.TRANSIT_ACTIVITY_CLOSE: 8518 case AppTransition.TRANSIT_TASK_CLOSE: 8519 case AppTransition.TRANSIT_TASK_TO_BACK: 8520 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; 8521 break; 8522 } 8523 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); 8524 } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty() 8525 && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 8526 // We are transitioning from an activity with 8527 // a wallpaper to one without. 8528 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; 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