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