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