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