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