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