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