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