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