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