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