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