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