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