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