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