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