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