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