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