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