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