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