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