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