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