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