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