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