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