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