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