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