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