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