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