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