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