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