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