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