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