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