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