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