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