WindowManagerService.java revision 8e79734ba371e123a63de3ac993fc3cae201a592
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 mTaskIdToTask.put(taskId, task); 3390 stack.addTask(task, true); 3391 stack.getDisplayContent().moveStack(stack, true); 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 void moveStackWindowsLocked(TaskStack stack) { 4728 DisplayContent displayContent = stack.getDisplayContent(); 4729 4730 // First remove all of the windows from the list. 4731 final ArrayList<Task> tasks = stack.getTasks(); 4732 final int numTasks = tasks.size(); 4733 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4734 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 4735 final int numTokens = tokens.size(); 4736 for (int tokenNdx = numTokens - 1; tokenNdx >= 0; --tokenNdx) { 4737 tmpRemoveAppWindowsLocked(tokens.get(tokenNdx)); 4738 } 4739 } 4740 4741 // And now add them back at the correct place. 4742 // Where to start adding? 4743 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4744 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 4745 int pos = findAppWindowInsertionPointLocked(tokens.get(0)); 4746 final int numTokens = tokens.size(); 4747 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 4748 final AppWindowToken wtoken = tokens.get(tokenNdx); 4749 if (wtoken != null) { 4750 final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken); 4751 if (newPos != pos) { 4752 displayContent.layoutNeeded = true; 4753 } 4754 pos = newPos; 4755 } 4756 } 4757 } 4758 4759 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4760 false /*updateInputWindows*/)) { 4761 assignLayersLocked(displayContent.getWindowList()); 4762 } 4763 4764 mInputMonitor.setUpdateInputWindowsNeededLw(); 4765 performLayoutAndPlaceSurfacesLocked(); 4766 mInputMonitor.updateInputWindowsLw(false /*force*/); 4767 4768 //dump(); 4769 } 4770 4771 public void moveTaskToTop(int taskId) { 4772 final long origId = Binder.clearCallingIdentity(); 4773 try { 4774 synchronized(mWindowMap) { 4775 Task task = mTaskIdToTask.get(taskId); 4776 if (task == null) { 4777 // Normal behavior, addAppToken will be called next and task will be created. 4778 return; 4779 } 4780 final TaskStack stack = task.mStack; 4781 final DisplayContent displayContent = task.getDisplayContent(); 4782 final boolean isHomeStackTask = stack.isHomeStack(); 4783 if (isHomeStackTask != displayContent.homeOnTop()) { 4784 // First move the stack itself. 4785 displayContent.moveHomeStackBox(isHomeStackTask); 4786 } 4787 stack.moveTaskToTop(task); 4788 displayContent.moveStack(stack, true); 4789 } 4790 } finally { 4791 Binder.restoreCallingIdentity(origId); 4792 } 4793 } 4794 4795 public void moveTaskToBottom(int taskId) { 4796 final long origId = Binder.clearCallingIdentity(); 4797 try { 4798 synchronized(mWindowMap) { 4799 Task task = mTaskIdToTask.get(taskId); 4800 if (task == null) { 4801 Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId 4802 + " not found in mTaskIdToTask"); 4803 return; 4804 } 4805 final TaskStack stack = task.mStack; 4806 stack.moveTaskToBottom(task); 4807 moveStackWindowsLocked(stack); 4808 } 4809 } finally { 4810 Binder.restoreCallingIdentity(origId); 4811 } 4812 } 4813 4814 /** 4815 * Create a new TaskStack and place it next to an existing stack. 4816 * @param stackId The unique identifier of the new stack. 4817 * @param relativeStackBoxId The existing stack that this stack goes before or after. 4818 * @param position One of: 4819 * {@link StackBox#TASK_STACK_GOES_BEFORE} 4820 * {@link StackBox#TASK_STACK_GOES_AFTER} 4821 * {@link StackBox#TASK_STACK_GOES_ABOVE} 4822 * {@link StackBox#TASK_STACK_GOES_BELOW} 4823 * {@link StackBox#TASK_STACK_GOES_UNDER} 4824 * {@link StackBox#TASK_STACK_GOES_OVER} 4825 * @param weight Relative weight for determining how big to make the new TaskStack. 4826 */ 4827 public void createStack(int stackId, int relativeStackBoxId, int position, float weight) { 4828 synchronized (mWindowMap) { 4829 if (position <= StackBox.TASK_STACK_GOES_BELOW && 4830 (weight < STACK_WEIGHT_MIN || weight > STACK_WEIGHT_MAX)) { 4831 throw new IllegalArgumentException( 4832 "createStack: weight must be between " + STACK_WEIGHT_MIN + " and " + 4833 STACK_WEIGHT_MAX + ", weight=" + weight); 4834 } 4835 final int numDisplays = mDisplayContents.size(); 4836 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 4837 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 4838 TaskStack stack = displayContent.createStack(stackId, relativeStackBoxId, position, 4839 weight); 4840 if (stack != null) { 4841 mStackIdToStack.put(stackId, stack); 4842 displayContent.moveStack(stack, true); 4843 performLayoutAndPlaceSurfacesLocked(); 4844 return; 4845 } 4846 } 4847 Slog.e(TAG, "createStack: Unable to find relativeStackBoxId=" + relativeStackBoxId); 4848 } 4849 } 4850 4851 public int removeStack(int stackId) { 4852 synchronized (mWindowMap) { 4853 final TaskStack stack = mStackIdToStack.get(stackId); 4854 if (stack != null) { 4855 mStackIdToStack.delete(stackId); 4856 int nextStackId = stack.remove(); 4857 stack.getDisplayContent().layoutNeeded = true; 4858 requestTraversalLocked(); 4859 return nextStackId; 4860 } 4861 if (DEBUG_STACK) Slog.i(TAG, "removeStack: could not find stackId=" + stackId); 4862 } 4863 return HOME_STACK_ID; 4864 } 4865 4866 public void removeTask(int taskId) { 4867 synchronized (mWindowMap) { 4868 Task task = mTaskIdToTask.get(taskId); 4869 if (task == null) { 4870 if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId); 4871 return; 4872 } 4873 final TaskStack stack = task.mStack; 4874 stack.removeTask(task); 4875 stack.getDisplayContent().layoutNeeded = true; 4876 } 4877 } 4878 4879 public void addTask(int taskId, int stackId, boolean toTop) { 4880 synchronized (mWindowMap) { 4881 Task task = mTaskIdToTask.get(taskId); 4882 if (task == null) { 4883 return; 4884 } 4885 TaskStack stack = mStackIdToStack.get(stackId); 4886 stack.addTask(task, toTop); 4887 final DisplayContent displayContent = stack.getDisplayContent(); 4888 displayContent.layoutNeeded = true; 4889 performLayoutAndPlaceSurfacesLocked(); 4890 } 4891 } 4892 4893 public void resizeStackBox(int stackBoxId, float weight) { 4894 if (weight < STACK_WEIGHT_MIN || weight > STACK_WEIGHT_MAX) { 4895 throw new IllegalArgumentException( 4896 "resizeStack: weight must be between " + STACK_WEIGHT_MIN + " and " + 4897 STACK_WEIGHT_MAX + ", weight=" + weight); 4898 } 4899 synchronized (mWindowMap) { 4900 final int numDisplays = mDisplayContents.size(); 4901 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 4902 if (mDisplayContents.valueAt(displayNdx).resizeStack(stackBoxId, weight)) { 4903 performLayoutAndPlaceSurfacesLocked(); 4904 return; 4905 } 4906 } 4907 } 4908 throw new IllegalArgumentException("resizeStack: stackBoxId " + stackBoxId 4909 + " not found."); 4910 } 4911 4912 public ArrayList<StackBoxInfo> getStackBoxInfos() { 4913 synchronized(mWindowMap) { 4914 return getDefaultDisplayContentLocked().getStackBoxInfos(); 4915 } 4916 } 4917 4918 public Rect getStackBounds(int stackId) { 4919 final int numDisplays = mDisplayContents.size(); 4920 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 4921 Rect bounds = mDisplayContents.valueAt(displayNdx).getStackBounds(stackId); 4922 if (bounds != null) { 4923 return bounds; 4924 } 4925 } 4926 return null; 4927 } 4928 4929 // ------------------------------------------------------------- 4930 // Misc IWindowSession methods 4931 // ------------------------------------------------------------- 4932 4933 @Override 4934 public void startFreezingScreen(int exitAnim, int enterAnim) { 4935 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 4936 "startFreezingScreen()")) { 4937 throw new SecurityException("Requires FREEZE_SCREEN permission"); 4938 } 4939 4940 synchronized(mWindowMap) { 4941 if (!mClientFreezingScreen) { 4942 mClientFreezingScreen = true; 4943 final long origId = Binder.clearCallingIdentity(); 4944 try { 4945 startFreezingDisplayLocked(false, exitAnim, enterAnim); 4946 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 4947 mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000); 4948 } finally { 4949 Binder.restoreCallingIdentity(origId); 4950 } 4951 } 4952 } 4953 } 4954 4955 @Override 4956 public void stopFreezingScreen() { 4957 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 4958 "stopFreezingScreen()")) { 4959 throw new SecurityException("Requires FREEZE_SCREEN permission"); 4960 } 4961 4962 synchronized(mWindowMap) { 4963 if (mClientFreezingScreen) { 4964 mClientFreezingScreen = false; 4965 mLastFinishedFreezeSource = "client"; 4966 final long origId = Binder.clearCallingIdentity(); 4967 try { 4968 stopFreezingDisplayLocked(); 4969 } finally { 4970 Binder.restoreCallingIdentity(origId); 4971 } 4972 } 4973 } 4974 } 4975 4976 @Override 4977 public void disableKeyguard(IBinder token, String tag) { 4978 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 4979 != PackageManager.PERMISSION_GRANTED) { 4980 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 4981 } 4982 4983 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 4984 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag))); 4985 } 4986 4987 @Override 4988 public void reenableKeyguard(IBinder token) { 4989 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 4990 != PackageManager.PERMISSION_GRANTED) { 4991 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 4992 } 4993 4994 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 4995 KeyguardDisableHandler.KEYGUARD_REENABLE, token)); 4996 } 4997 4998 /** 4999 * @see android.app.KeyguardManager#exitKeyguardSecurely 5000 */ 5001 @Override 5002 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) { 5003 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5004 != PackageManager.PERMISSION_GRANTED) { 5005 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5006 } 5007 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() { 5008 @Override 5009 public void onKeyguardExitResult(boolean success) { 5010 try { 5011 callback.onKeyguardExitResult(success); 5012 } catch (RemoteException e) { 5013 // Client has died, we don't care. 5014 } 5015 } 5016 }); 5017 } 5018 5019 @Override 5020 public boolean inKeyguardRestrictedInputMode() { 5021 return mPolicy.inKeyguardRestrictedKeyInputMode(); 5022 } 5023 5024 @Override 5025 public boolean isKeyguardLocked() { 5026 return mPolicy.isKeyguardLocked(); 5027 } 5028 5029 @Override 5030 public boolean isKeyguardSecure() { 5031 return mPolicy.isKeyguardSecure(); 5032 } 5033 5034 @Override 5035 public void dismissKeyguard() { 5036 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5037 != PackageManager.PERMISSION_GRANTED) { 5038 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5039 } 5040 synchronized(mWindowMap) { 5041 mPolicy.dismissKeyguardLw(); 5042 } 5043 } 5044 5045 @Override 5046 public void closeSystemDialogs(String reason) { 5047 synchronized(mWindowMap) { 5048 final int numDisplays = mDisplayContents.size(); 5049 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5050 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5051 final int numWindows = windows.size(); 5052 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5053 final WindowState w = windows.get(winNdx); 5054 if (w.mHasSurface) { 5055 try { 5056 w.mClient.closeSystemDialogs(reason); 5057 } catch (RemoteException e) { 5058 } 5059 } 5060 } 5061 } 5062 } 5063 } 5064 5065 static float fixScale(float scale) { 5066 if (scale < 0) scale = 0; 5067 else if (scale > 20) scale = 20; 5068 return Math.abs(scale); 5069 } 5070 5071 @Override 5072 public void setAnimationScale(int which, float scale) { 5073 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5074 "setAnimationScale()")) { 5075 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5076 } 5077 5078 scale = fixScale(scale); 5079 switch (which) { 5080 case 0: mWindowAnimationScale = scale; break; 5081 case 1: mTransitionAnimationScale = scale; break; 5082 case 2: mAnimatorDurationScale = scale; break; 5083 } 5084 5085 // Persist setting 5086 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5087 } 5088 5089 @Override 5090 public void setAnimationScales(float[] scales) { 5091 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5092 "setAnimationScale()")) { 5093 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5094 } 5095 5096 if (scales != null) { 5097 if (scales.length >= 1) { 5098 mWindowAnimationScale = fixScale(scales[0]); 5099 } 5100 if (scales.length >= 2) { 5101 mTransitionAnimationScale = fixScale(scales[1]); 5102 } 5103 if (scales.length >= 3) { 5104 setAnimatorDurationScale(fixScale(scales[2])); 5105 } 5106 } 5107 5108 // Persist setting 5109 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5110 } 5111 5112 private void setAnimatorDurationScale(float scale) { 5113 mAnimatorDurationScale = scale; 5114 ValueAnimator.setDurationScale(scale); 5115 } 5116 5117 @Override 5118 public float getAnimationScale(int which) { 5119 switch (which) { 5120 case 0: return mWindowAnimationScale; 5121 case 1: return mTransitionAnimationScale; 5122 case 2: return mAnimatorDurationScale; 5123 } 5124 return 0; 5125 } 5126 5127 @Override 5128 public float[] getAnimationScales() { 5129 return new float[] { mWindowAnimationScale, mTransitionAnimationScale, 5130 mAnimatorDurationScale }; 5131 } 5132 5133 @Override 5134 public void registerPointerEventListener(PointerEventListener listener) { 5135 mPointerEventDispatcher.registerInputEventListener(listener); 5136 } 5137 5138 @Override 5139 public void unregisterPointerEventListener(PointerEventListener listener) { 5140 mPointerEventDispatcher.unregisterInputEventListener(listener); 5141 } 5142 5143 // Called by window manager policy. Not exposed externally. 5144 @Override 5145 public int getLidState() { 5146 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 5147 InputManagerService.SW_LID); 5148 if (sw > 0) { 5149 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 5150 return LID_CLOSED; 5151 } else if (sw == 0) { 5152 // Switch state: AKEY_STATE_UP. 5153 return LID_OPEN; 5154 } else { 5155 // Switch state: AKEY_STATE_UNKNOWN. 5156 return LID_ABSENT; 5157 } 5158 } 5159 5160 // Called by window manager policy. Not exposed externally. 5161 @Override 5162 public void switchKeyboardLayout(int deviceId, int direction) { 5163 mInputManager.switchKeyboardLayout(deviceId, direction); 5164 } 5165 5166 // Called by window manager policy. Not exposed externally. 5167 @Override 5168 public void shutdown(boolean confirm) { 5169 ShutdownThread.shutdown(mContext, confirm); 5170 } 5171 5172 // Called by window manager policy. Not exposed externally. 5173 @Override 5174 public void rebootSafeMode(boolean confirm) { 5175 ShutdownThread.rebootSafeMode(mContext, confirm); 5176 } 5177 5178 @Override 5179 public void setInputFilter(IInputFilter filter) { 5180 if (!checkCallingPermission(android.Manifest.permission.FILTER_EVENTS, "setInputFilter()")) { 5181 throw new SecurityException("Requires FILTER_EVENTS permission"); 5182 } 5183 mInputManager.setInputFilter(filter); 5184 } 5185 5186 public void setCurrentUser(final int newUserId) { 5187 synchronized (mWindowMap) { 5188 int oldUserId = mCurrentUserId; 5189 mCurrentUserId = newUserId; 5190 mAppTransition.setCurrentUser(newUserId); 5191 mPolicy.setCurrentUserLw(newUserId); 5192 5193 // Hide windows that should not be seen by the new user. 5194 final int numDisplays = mDisplayContents.size(); 5195 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5196 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 5197 displayContent.switchUserStacks(oldUserId, newUserId); 5198 rebuildAppWindowListLocked(displayContent); 5199 } 5200 performLayoutAndPlaceSurfacesLocked(); 5201 } 5202 } 5203 5204 public void enableScreenAfterBoot() { 5205 synchronized(mWindowMap) { 5206 if (DEBUG_BOOT) { 5207 RuntimeException here = new RuntimeException("here"); 5208 here.fillInStackTrace(); 5209 Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled 5210 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5211 + " mShowingBootMessages=" + mShowingBootMessages 5212 + " mSystemBooted=" + mSystemBooted, here); 5213 } 5214 if (mSystemBooted) { 5215 return; 5216 } 5217 mSystemBooted = true; 5218 hideBootMessagesLocked(); 5219 // If the screen still doesn't come up after 30 seconds, give 5220 // up and turn it on. 5221 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000); 5222 } 5223 5224 mPolicy.systemBooted(); 5225 5226 performEnableScreen(); 5227 } 5228 5229 void enableScreenIfNeededLocked() { 5230 if (DEBUG_BOOT) { 5231 RuntimeException here = new RuntimeException("here"); 5232 here.fillInStackTrace(); 5233 Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled 5234 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5235 + " mShowingBootMessages=" + mShowingBootMessages 5236 + " mSystemBooted=" + mSystemBooted, here); 5237 } 5238 if (mDisplayEnabled) { 5239 return; 5240 } 5241 if (!mSystemBooted && !mShowingBootMessages) { 5242 return; 5243 } 5244 mH.sendEmptyMessage(H.ENABLE_SCREEN); 5245 } 5246 5247 public void performBootTimeout() { 5248 synchronized(mWindowMap) { 5249 if (mDisplayEnabled || mHeadless) { 5250 return; 5251 } 5252 Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled"); 5253 mForceDisplayEnabled = true; 5254 } 5255 performEnableScreen(); 5256 } 5257 5258 public void performEnableScreen() { 5259 synchronized(mWindowMap) { 5260 if (DEBUG_BOOT) { 5261 RuntimeException here = new RuntimeException("here"); 5262 here.fillInStackTrace(); 5263 Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled 5264 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5265 + " mShowingBootMessages=" + mShowingBootMessages 5266 + " mSystemBooted=" + mSystemBooted 5267 + " mOnlyCore=" + mOnlyCore, here); 5268 } 5269 if (mDisplayEnabled) { 5270 return; 5271 } 5272 if (!mSystemBooted && !mShowingBootMessages) { 5273 return; 5274 } 5275 5276 if (!mForceDisplayEnabled) { 5277 // Don't enable the screen until all existing windows 5278 // have been drawn. 5279 boolean haveBootMsg = false; 5280 boolean haveApp = false; 5281 // if the wallpaper service is disabled on the device, we're never going to have 5282 // wallpaper, don't bother waiting for it 5283 boolean haveWallpaper = false; 5284 boolean wallpaperEnabled = mContext.getResources().getBoolean( 5285 com.android.internal.R.bool.config_enableWallpaperService) 5286 && !mOnlyCore; 5287 boolean haveKeyguard = true; 5288 // TODO(multidisplay): Expand to all displays? 5289 final WindowList windows = getDefaultWindowListLocked(); 5290 final int N = windows.size(); 5291 for (int i=0; i<N; i++) { 5292 WindowState w = windows.get(i); 5293 if (w.mAttrs.type == TYPE_KEYGUARD) { 5294 // Only if there is a keyguard attached to the window manager 5295 // will we consider ourselves as having a keyguard. If it 5296 // isn't attached, we don't know if it wants to be shown or 5297 // hidden. If it is attached, we will say we have a keyguard 5298 // if the window doesn't want to be visible, because in that 5299 // case it explicitly doesn't want to be shown so we should 5300 // not delay turning the screen on for it. 5301 boolean vis = w.mViewVisibility == View.VISIBLE 5302 && w.mPolicyVisibility; 5303 haveKeyguard = !vis; 5304 } 5305 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 5306 return; 5307 } 5308 if (w.isDrawnLw()) { 5309 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { 5310 haveBootMsg = true; 5311 } else if (w.mAttrs.type == TYPE_APPLICATION) { 5312 haveApp = true; 5313 } else if (w.mAttrs.type == TYPE_WALLPAPER) { 5314 haveWallpaper = true; 5315 } else if (w.mAttrs.type == TYPE_KEYGUARD) { 5316 haveKeyguard = true; 5317 } 5318 } 5319 } 5320 5321 if (DEBUG_SCREEN_ON || DEBUG_BOOT) { 5322 Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages 5323 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp 5324 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled 5325 + " haveKeyguard=" + haveKeyguard); 5326 } 5327 5328 // If we are turning on the screen to show the boot message, 5329 // don't do it until the boot message is actually displayed. 5330 if (!mSystemBooted && !haveBootMsg) { 5331 return; 5332 } 5333 5334 // If we are turning on the screen after the boot is completed 5335 // normally, don't do so until we have the application and 5336 // wallpaper. 5337 if (mSystemBooted && ((!haveApp && !haveKeyguard) || 5338 (wallpaperEnabled && !haveWallpaper))) { 5339 return; 5340 } 5341 } 5342 5343 mDisplayEnabled = true; 5344 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!"); 5345 if (false) { 5346 StringWriter sw = new StringWriter(); 5347 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 5348 this.dump(null, pw, null); 5349 pw.flush(); 5350 Slog.i(TAG, sw.toString()); 5351 } 5352 try { 5353 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); 5354 if (surfaceFlinger != null) { 5355 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); 5356 Parcel data = Parcel.obtain(); 5357 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 5358 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED 5359 data, null, 0); 5360 data.recycle(); 5361 } 5362 } catch (RemoteException ex) { 5363 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); 5364 } 5365 5366 // Enable input dispatch. 5367 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled); 5368 } 5369 5370 mPolicy.enableScreenAfterBoot(); 5371 5372 // Make sure the last requested orientation has been applied. 5373 updateRotationUnchecked(false, false); 5374 } 5375 5376 public void showBootMessage(final CharSequence msg, final boolean always) { 5377 boolean first = false; 5378 synchronized(mWindowMap) { 5379 if (DEBUG_BOOT) { 5380 RuntimeException here = new RuntimeException("here"); 5381 here.fillInStackTrace(); 5382 Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always 5383 + " mAllowBootMessages=" + mAllowBootMessages 5384 + " mShowingBootMessages=" + mShowingBootMessages 5385 + " mSystemBooted=" + mSystemBooted, here); 5386 } 5387 if (!mAllowBootMessages) { 5388 return; 5389 } 5390 if (!mShowingBootMessages) { 5391 if (!always) { 5392 return; 5393 } 5394 first = true; 5395 } 5396 if (mSystemBooted) { 5397 return; 5398 } 5399 mShowingBootMessages = true; 5400 mPolicy.showBootMessage(msg, always); 5401 } 5402 if (first) { 5403 performEnableScreen(); 5404 } 5405 } 5406 5407 public void hideBootMessagesLocked() { 5408 if (DEBUG_BOOT) { 5409 RuntimeException here = new RuntimeException("here"); 5410 here.fillInStackTrace(); 5411 Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled 5412 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5413 + " mShowingBootMessages=" + mShowingBootMessages 5414 + " mSystemBooted=" + mSystemBooted, here); 5415 } 5416 if (mShowingBootMessages) { 5417 mShowingBootMessages = false; 5418 mPolicy.hideBootMessages(); 5419 } 5420 } 5421 5422 @Override 5423 public void setInTouchMode(boolean mode) { 5424 synchronized(mWindowMap) { 5425 mInTouchMode = mode; 5426 } 5427 } 5428 5429 // TODO: more accounting of which pid(s) turned it on, keep count, 5430 // only allow disables from pids which have count on, etc. 5431 @Override 5432 public void showStrictModeViolation(boolean on) { 5433 if (mHeadless) return; 5434 int pid = Binder.getCallingPid(); 5435 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid)); 5436 } 5437 5438 private void showStrictModeViolation(int arg, int pid) { 5439 final boolean on = arg != 0; 5440 synchronized(mWindowMap) { 5441 // Ignoring requests to enable the red border from clients 5442 // which aren't on screen. (e.g. Broadcast Receivers in 5443 // the background..) 5444 if (on) { 5445 boolean isVisible = false; 5446 final int numDisplays = mDisplayContents.size(); 5447 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5448 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5449 final int numWindows = windows.size(); 5450 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5451 final WindowState ws = windows.get(winNdx); 5452 if (ws.mSession.mPid == pid && ws.isVisibleLw()) { 5453 isVisible = true; 5454 break; 5455 } 5456 } 5457 } 5458 if (!isVisible) { 5459 return; 5460 } 5461 } 5462 5463 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5464 ">>> OPEN TRANSACTION showStrictModeViolation"); 5465 SurfaceControl.openTransaction(); 5466 try { 5467 // TODO(multi-display): support multiple displays 5468 if (mStrictModeFlash == null) { 5469 mStrictModeFlash = new StrictModeFlash( 5470 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 5471 } 5472 mStrictModeFlash.setVisibility(on); 5473 } finally { 5474 SurfaceControl.closeTransaction(); 5475 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5476 "<<< CLOSE TRANSACTION showStrictModeViolation"); 5477 } 5478 } 5479 } 5480 5481 @Override 5482 public void setStrictModeVisualIndicatorPreference(String value) { 5483 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 5484 } 5485 5486 /** 5487 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 5488 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 5489 * of the target image. 5490 * 5491 * @param displayId the Display to take a screenshot of. 5492 * @param width the width of the target bitmap 5493 * @param height the height of the target bitmap 5494 * @param force565 if true the returned bitmap will be RGB_565, otherwise it 5495 * will be the same config as the surface 5496 */ 5497 @Override 5498 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, 5499 int height, boolean force565) { 5500 if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, 5501 "screenshotApplications()")) { 5502 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 5503 } 5504 5505 Bitmap rawss = null; 5506 5507 int maxLayer = 0; 5508 final Rect frame = new Rect(); 5509 5510 float scale = 0; 5511 int dw, dh; 5512 int rot = Surface.ROTATION_0; 5513 5514 boolean screenshotReady; 5515 int minLayer; 5516 if (appToken == null) { 5517 screenshotReady = true; 5518 minLayer = 0; 5519 } else { 5520 screenshotReady = false; 5521 minLayer = Integer.MAX_VALUE; 5522 } 5523 5524 int retryCount = 0; 5525 WindowState appWin = null; 5526 5527 do { 5528 if (retryCount++ > 0) { 5529 try { 5530 Thread.sleep(100); 5531 } catch (InterruptedException e) { 5532 } 5533 } 5534 synchronized(mWindowMap) { 5535 final DisplayContent displayContent = getDisplayContentLocked(displayId); 5536 if (displayContent == null) { 5537 return null; 5538 } 5539 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 5540 dw = displayInfo.logicalWidth; 5541 dh = displayInfo.logicalHeight; 5542 5543 int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) 5544 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 5545 aboveAppLayer += TYPE_LAYER_MULTIPLIER; 5546 5547 boolean isImeTarget = mInputMethodTarget != null 5548 && mInputMethodTarget.mAppToken != null 5549 && mInputMethodTarget.mAppToken.appToken != null 5550 && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken; 5551 5552 // Figure out the part of the screen that is actually the app. 5553 boolean including = false; 5554 appWin = null; 5555 final WindowList windows = displayContent.getWindowList(); 5556 final Rect stackBounds = new Rect(); 5557 for (int i = windows.size() - 1; i >= 0; i--) { 5558 WindowState ws = windows.get(i); 5559 if (!ws.mHasSurface) { 5560 continue; 5561 } 5562 if (ws.mLayer >= aboveAppLayer) { 5563 continue; 5564 } 5565 // When we will skip windows: when we are not including 5566 // ones behind a window we didn't skip, and we are actually 5567 // taking a screenshot of a specific app. 5568 if (!including && appToken != null) { 5569 // Also, we can possibly skip this window if it is not 5570 // an IME target or the application for the screenshot 5571 // is not the current IME target. 5572 if (!ws.mIsImWindow || !isImeTarget) { 5573 // And finally, this window is of no interest if it 5574 // is not associated with the screenshot app. 5575 if (ws.mAppToken == null || ws.mAppToken.token != appToken) { 5576 continue; 5577 } 5578 appWin = ws; 5579 stackBounds.set(ws.getStackBounds()); 5580 } 5581 } 5582 5583 // We keep on including windows until we go past a full-screen 5584 // window. 5585 boolean fullscreen = ws.isFullscreen(dw, dh); 5586 including = !ws.mIsImWindow && !fullscreen; 5587 5588 final WindowStateAnimator winAnim = ws.mWinAnimator; 5589 if (maxLayer < winAnim.mSurfaceLayer) { 5590 maxLayer = winAnim.mSurfaceLayer; 5591 } 5592 if (minLayer > winAnim.mSurfaceLayer) { 5593 minLayer = winAnim.mSurfaceLayer; 5594 } 5595 5596 // Don't include wallpaper in bounds calculation 5597 if (!ws.mIsWallpaper) { 5598 final Rect wf = ws.mFrame; 5599 final Rect cr = ws.mContentInsets; 5600 int left = wf.left + cr.left; 5601 int top = wf.top + cr.top; 5602 int right = wf.right - cr.right; 5603 int bottom = wf.bottom - cr.bottom; 5604 frame.union(left, top, right, bottom); 5605 frame.intersect(stackBounds); 5606 } 5607 5608 if (ws.mAppToken != null && ws.mAppToken.token == appToken && 5609 ws.isDisplayedLw()) { 5610 screenshotReady = true; 5611 } 5612 5613 if (fullscreen) { 5614 // No point in continuing down through windows. 5615 break; 5616 } 5617 } 5618 5619 if (appToken != null && appWin == null) { 5620 // Can't find a window to snapshot. 5621 if (DEBUG_SCREENSHOT) Slog.i(TAG, 5622 "Screenshot: Couldn't find a surface matching " + appToken); 5623 return null; 5624 } 5625 if (!screenshotReady) { 5626 // Delay and hope that window gets drawn. 5627 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken 5628 + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState); 5629 continue; 5630 } 5631 5632 // Constrain frame to the screen size. 5633 frame.intersect(0, 0, dw, dh); 5634 5635 if (frame.isEmpty() || maxLayer == 0) { 5636 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 5637 + ": returning null frame=" + frame.toShortString() + " maxLayer=" 5638 + maxLayer); 5639 return null; 5640 } 5641 5642 // The screenshot API does not apply the current screen rotation. 5643 rot = getDefaultDisplayContentLocked().getDisplay().getRotation(); 5644 int fw = frame.width(); 5645 int fh = frame.height(); 5646 5647 // Constrain thumbnail to smaller of screen width or height. Assumes aspect 5648 // of thumbnail is the same as the screen (in landscape) or square. 5649 scale = Math.max(width / (float) fw, height / (float) fh); 5650 /* 5651 float targetWidthScale = width / (float) fw; 5652 float targetHeightScale = height / (float) fh; 5653 if (fw <= fh) { 5654 scale = targetWidthScale; 5655 // If aspect of thumbnail is the same as the screen (in landscape), 5656 // select the slightly larger value so we fill the entire bitmap 5657 if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) { 5658 scale = targetHeightScale; 5659 } 5660 } else { 5661 scale = targetHeightScale; 5662 // If aspect of thumbnail is the same as the screen (in landscape), 5663 // select the slightly larger value so we fill the entire bitmap 5664 if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) { 5665 scale = targetWidthScale; 5666 } 5667 } 5668 */ 5669 5670 // The screen shot will contain the entire screen. 5671 dw = (int)(dw*scale); 5672 dh = (int)(dh*scale); 5673 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 5674 int tmp = dw; 5675 dw = dh; 5676 dh = tmp; 5677 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; 5678 } 5679 if (DEBUG_SCREENSHOT) { 5680 Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 5681 + maxLayer + " appToken=" + appToken); 5682 for (int i = 0; i < windows.size(); i++) { 5683 WindowState win = windows.get(i); 5684 Slog.i(TAG, win + ": " + win.mLayer 5685 + " animLayer=" + win.mWinAnimator.mAnimLayer 5686 + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer); 5687 } 5688 } 5689 rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer); 5690 } 5691 } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES); 5692 if (retryCount > MAX_SCREENSHOT_RETRIES) Slog.i(TAG, "Screenshot max retries " + 5693 retryCount + " of " + appToken + " appWin=" + (appWin == null ? 5694 "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState))); 5695 5696 if (rawss == null) { 5697 Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh 5698 + ") to layer " + maxLayer); 5699 return null; 5700 } 5701 5702 Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig()); 5703 frame.scale(scale); 5704 Matrix matrix = new Matrix(); 5705 ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix); 5706 // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left 5707 matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top)); 5708 Canvas canvas = new Canvas(bm); 5709 canvas.drawColor(0xFF000000); 5710 canvas.drawBitmap(rawss, matrix, null); 5711 canvas.setBitmap(null); 5712 5713 if (true || DEBUG_SCREENSHOT) { 5714 // TEST IF IT's ALL BLACK 5715 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 5716 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 5717 boolean allBlack = true; 5718 final int firstColor = buffer[0]; 5719 for (int i = 0; i < buffer.length; i++) { 5720 if (buffer[i] != firstColor) { 5721 allBlack = false; 5722 break; 5723 } 5724 } 5725 if (allBlack) { 5726 Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" + 5727 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 5728 (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") + 5729 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 5730 } 5731 } 5732 5733 rawss.recycle(); 5734 return bm; 5735 } 5736 5737 /** 5738 * Freeze rotation changes. (Enable "rotation lock".) 5739 * Persists across reboots. 5740 * @param rotation The desired rotation to freeze to, or -1 to use the 5741 * current rotation. 5742 */ 5743 @Override 5744 public void freezeRotation(int rotation) { 5745 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5746 "freezeRotation()")) { 5747 throw new SecurityException("Requires SET_ORIENTATION permission"); 5748 } 5749 if (rotation < -1 || rotation > Surface.ROTATION_270) { 5750 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 5751 + "rotation constant."); 5752 } 5753 5754 if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); 5755 5756 long origId = Binder.clearCallingIdentity(); 5757 try { 5758 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, 5759 rotation == -1 ? mRotation : rotation); 5760 } finally { 5761 Binder.restoreCallingIdentity(origId); 5762 } 5763 5764 updateRotationUnchecked(false, false); 5765 } 5766 5767 /** 5768 * Thaw rotation changes. (Disable "rotation lock".) 5769 * Persists across reboots. 5770 */ 5771 @Override 5772 public void thawRotation() { 5773 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5774 "thawRotation()")) { 5775 throw new SecurityException("Requires SET_ORIENTATION permission"); 5776 } 5777 5778 if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); 5779 5780 long origId = Binder.clearCallingIdentity(); 5781 try { 5782 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 5783 777); // rot not used 5784 } finally { 5785 Binder.restoreCallingIdentity(origId); 5786 } 5787 5788 updateRotationUnchecked(false, false); 5789 } 5790 5791 /** 5792 * Recalculate the current rotation. 5793 * 5794 * Called by the window manager policy whenever the state of the system changes 5795 * such that the current rotation might need to be updated, such as when the 5796 * device is docked or rotated into a new posture. 5797 */ 5798 @Override 5799 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 5800 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 5801 } 5802 5803 /** 5804 * Temporarily pauses rotation changes until resumed. 5805 * 5806 * This can be used to prevent rotation changes from occurring while the user is 5807 * performing certain operations, such as drag and drop. 5808 * 5809 * This call nests and must be matched by an equal number of calls to 5810 * {@link #resumeRotationLocked}. 5811 */ 5812 void pauseRotationLocked() { 5813 mDeferredRotationPauseCount += 1; 5814 } 5815 5816 /** 5817 * Resumes normal rotation changes after being paused. 5818 */ 5819 void resumeRotationLocked() { 5820 if (mDeferredRotationPauseCount > 0) { 5821 mDeferredRotationPauseCount -= 1; 5822 if (mDeferredRotationPauseCount == 0) { 5823 boolean changed = updateRotationUncheckedLocked(false); 5824 if (changed) { 5825 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 5826 } 5827 } 5828 } 5829 } 5830 5831 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 5832 if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" 5833 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); 5834 5835 long origId = Binder.clearCallingIdentity(); 5836 boolean changed; 5837 synchronized(mWindowMap) { 5838 changed = updateRotationUncheckedLocked(false); 5839 if (!changed || forceRelayout) { 5840 getDefaultDisplayContentLocked().layoutNeeded = true; 5841 performLayoutAndPlaceSurfacesLocked(); 5842 } 5843 } 5844 5845 if (changed || alwaysSendConfiguration) { 5846 sendNewConfiguration(); 5847 } 5848 5849 Binder.restoreCallingIdentity(origId); 5850 } 5851 5852 // TODO(multidisplay): Rotate any display? 5853 /** 5854 * Updates the current rotation. 5855 * 5856 * Returns true if the rotation has been changed. In this case YOU 5857 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. 5858 */ 5859 public boolean updateRotationUncheckedLocked(boolean inTransaction) { 5860 if (mDeferredRotationPauseCount > 0) { 5861 // Rotation updates have been paused temporarily. Defer the update until 5862 // updates have been resumed. 5863 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused."); 5864 return false; 5865 } 5866 5867 ScreenRotationAnimation screenRotationAnimation = 5868 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 5869 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 5870 // Rotation updates cannot be performed while the previous rotation change 5871 // animation is still in progress. Skip this update. We will try updating 5872 // again after the animation is finished and the display is unfrozen. 5873 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress."); 5874 return false; 5875 } 5876 5877 if (!mDisplayEnabled) { 5878 // No point choosing a rotation if the display is not enabled. 5879 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled."); 5880 return false; 5881 } 5882 5883 // TODO: Implement forced rotation changes. 5884 // Set mAltOrientation to indicate that the application is receiving 5885 // an orientation that has different metrics than it expected. 5886 // eg. Portrait instead of Landscape. 5887 5888 int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation); 5889 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 5890 mForcedAppOrientation, rotation); 5891 5892 if (DEBUG_ORIENTATION) { 5893 Slog.v(TAG, "Application requested orientation " 5894 + mForcedAppOrientation + ", got rotation " + rotation 5895 + " which has " + (altOrientation ? "incompatible" : "compatible") 5896 + " metrics"); 5897 } 5898 5899 if (mRotation == rotation && mAltOrientation == altOrientation) { 5900 // No change. 5901 return false; 5902 } 5903 5904 if (DEBUG_ORIENTATION) { 5905 Slog.v(TAG, 5906 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") 5907 + " from " + mRotation + (mAltOrientation ? " (alt)" : "") 5908 + ", forceApp=" + mForcedAppOrientation); 5909 } 5910 5911 mRotation = rotation; 5912 mAltOrientation = altOrientation; 5913 mPolicy.setRotationLw(mRotation); 5914 5915 mWindowsFreezingScreen = true; 5916 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 5917 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION); 5918 mWaitingForConfig = true; 5919 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 5920 displayContent.layoutNeeded = true; 5921 final int[] anim = new int[2]; 5922 if (displayContent.isDimming()) { 5923 anim[0] = anim[1] = 0; 5924 } else { 5925 mPolicy.selectRotationAnimationLw(anim); 5926 } 5927 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]); 5928 // startFreezingDisplayLocked can reset the ScreenRotationAnimation. 5929 screenRotationAnimation = 5930 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 5931 5932 // We need to update our screen size information to match the new 5933 // rotation. Note that this is redundant with the later call to 5934 // sendNewConfiguration() that must be called after this function 5935 // returns... however we need to do the screen size part of that 5936 // before then so we have the correct size to use when initializing 5937 // the rotation animation for the new rotation. 5938 computeScreenConfigurationLocked(null); 5939 5940 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 5941 if (!inTransaction) { 5942 if (SHOW_TRANSACTIONS) { 5943 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked"); 5944 } 5945 SurfaceControl.openTransaction(); 5946 } 5947 try { 5948 // NOTE: We disable the rotation in the emulator because 5949 // it doesn't support hardware OpenGL emulation yet. 5950 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 5951 && screenRotationAnimation.hasScreenshot()) { 5952 if (screenRotationAnimation.setRotationInTransaction( 5953 rotation, mFxSession, 5954 MAX_ANIMATION_DURATION, mTransitionAnimationScale, 5955 displayInfo.logicalWidth, displayInfo.logicalHeight)) { 5956 scheduleAnimationLocked(); 5957 } 5958 } 5959 5960 mDisplayManagerService.performTraversalInTransactionFromWindowManager(); 5961 } finally { 5962 if (!inTransaction) { 5963 SurfaceControl.closeTransaction(); 5964 if (SHOW_LIGHT_TRANSACTIONS) { 5965 Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked"); 5966 } 5967 } 5968 } 5969 5970 final WindowList windows = displayContent.getWindowList(); 5971 for (int i = windows.size() - 1; i >= 0; i--) { 5972 WindowState w = windows.get(i); 5973 if (w.mHasSurface) { 5974 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w); 5975 w.mOrientationChanging = true; 5976 mInnerFields.mOrientationChangeComplete = false; 5977 } 5978 w.mLastFreezeDuration = 0; 5979 } 5980 5981 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 5982 try { 5983 mRotationWatchers.get(i).onRotationChanged(rotation); 5984 } catch (RemoteException e) { 5985 } 5986 } 5987 5988 //TODO (multidisplay): Magnification is supported only for the default display. 5989 if (mDisplayMagnifier != null 5990 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 5991 mDisplayMagnifier.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation); 5992 } 5993 5994 return true; 5995 } 5996 5997 @Override 5998 public int getRotation() { 5999 return mRotation; 6000 } 6001 6002 @Override 6003 public boolean isRotationFrozen() { 6004 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED; 6005 } 6006 6007 @Override 6008 public int watchRotation(IRotationWatcher watcher) { 6009 final IBinder watcherBinder = watcher.asBinder(); 6010 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 6011 @Override 6012 public void binderDied() { 6013 synchronized (mWindowMap) { 6014 for (int i=0; i<mRotationWatchers.size(); i++) { 6015 if (watcherBinder == mRotationWatchers.get(i).asBinder()) { 6016 IRotationWatcher removed = mRotationWatchers.remove(i); 6017 if (removed != null) { 6018 removed.asBinder().unlinkToDeath(this, 0); 6019 } 6020 i--; 6021 } 6022 } 6023 } 6024 } 6025 }; 6026 6027 synchronized (mWindowMap) { 6028 try { 6029 watcher.asBinder().linkToDeath(dr, 0); 6030 mRotationWatchers.add(watcher); 6031 } catch (RemoteException e) { 6032 // Client died, no cleanup needed. 6033 } 6034 6035 return mRotation; 6036 } 6037 } 6038 6039 @Override 6040 public void removeRotationWatcher(IRotationWatcher watcher) { 6041 final IBinder watcherBinder = watcher.asBinder(); 6042 synchronized (mWindowMap) { 6043 for (int i=0; i<mRotationWatchers.size(); i++) { 6044 if (watcherBinder == mRotationWatchers.get(i).asBinder()) { 6045 mRotationWatchers.remove(i); 6046 i--; 6047 } 6048 } 6049 } 6050 } 6051 6052 /** 6053 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 6054 * theme attribute) on devices that feature a physical options menu key attempt to position 6055 * their menu panel window along the edge of the screen nearest the physical menu key. 6056 * This lowers the travel distance between invoking the menu panel and selecting 6057 * a menu option. 6058 * 6059 * This method helps control where that menu is placed. Its current implementation makes 6060 * assumptions about the menu key and its relationship to the screen based on whether 6061 * the device's natural orientation is portrait (width < height) or landscape. 6062 * 6063 * The menu key is assumed to be located along the bottom edge of natural-portrait 6064 * devices and along the right edge of natural-landscape devices. If these assumptions 6065 * do not hold for the target device, this method should be changed to reflect that. 6066 * 6067 * @return A {@link Gravity} value for placing the options menu window 6068 */ 6069 @Override 6070 public int getPreferredOptionsPanelGravity() { 6071 synchronized (mWindowMap) { 6072 final int rotation = getRotation(); 6073 6074 // TODO(multidisplay): Assume that such devices physical keys are on the main screen. 6075 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6076 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) { 6077 // On devices with a natural orientation of portrait 6078 switch (rotation) { 6079 default: 6080 case Surface.ROTATION_0: 6081 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6082 case Surface.ROTATION_90: 6083 return Gravity.RIGHT | Gravity.BOTTOM; 6084 case Surface.ROTATION_180: 6085 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6086 case Surface.ROTATION_270: 6087 return Gravity.START | Gravity.BOTTOM; 6088 } 6089 } 6090 6091 // On devices with a natural orientation of landscape 6092 switch (rotation) { 6093 default: 6094 case Surface.ROTATION_0: 6095 return Gravity.RIGHT | Gravity.BOTTOM; 6096 case Surface.ROTATION_90: 6097 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6098 case Surface.ROTATION_180: 6099 return Gravity.START | Gravity.BOTTOM; 6100 case Surface.ROTATION_270: 6101 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6102 } 6103 } 6104 } 6105 6106 /** 6107 * Starts the view server on the specified port. 6108 * 6109 * @param port The port to listener to. 6110 * 6111 * @return True if the server was successfully started, false otherwise. 6112 * 6113 * @see com.android.server.wm.ViewServer 6114 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 6115 */ 6116 @Override 6117 public boolean startViewServer(int port) { 6118 if (isSystemSecure()) { 6119 return false; 6120 } 6121 6122 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 6123 return false; 6124 } 6125 6126 if (port < 1024) { 6127 return false; 6128 } 6129 6130 if (mViewServer != null) { 6131 if (!mViewServer.isRunning()) { 6132 try { 6133 return mViewServer.start(); 6134 } catch (IOException e) { 6135 Slog.w(TAG, "View server did not start"); 6136 } 6137 } 6138 return false; 6139 } 6140 6141 try { 6142 mViewServer = new ViewServer(this, port); 6143 return mViewServer.start(); 6144 } catch (IOException e) { 6145 Slog.w(TAG, "View server did not start"); 6146 } 6147 return false; 6148 } 6149 6150 private boolean isSystemSecure() { 6151 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 6152 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 6153 } 6154 6155 /** 6156 * Stops the view server if it exists. 6157 * 6158 * @return True if the server stopped, false if it wasn't started or 6159 * couldn't be stopped. 6160 * 6161 * @see com.android.server.wm.ViewServer 6162 */ 6163 @Override 6164 public boolean stopViewServer() { 6165 if (isSystemSecure()) { 6166 return false; 6167 } 6168 6169 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 6170 return false; 6171 } 6172 6173 if (mViewServer != null) { 6174 return mViewServer.stop(); 6175 } 6176 return false; 6177 } 6178 6179 /** 6180 * Indicates whether the view server is running. 6181 * 6182 * @return True if the server is running, false otherwise. 6183 * 6184 * @see com.android.server.wm.ViewServer 6185 */ 6186 @Override 6187 public boolean isViewServerRunning() { 6188 if (isSystemSecure()) { 6189 return false; 6190 } 6191 6192 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 6193 return false; 6194 } 6195 6196 return mViewServer != null && mViewServer.isRunning(); 6197 } 6198 6199 /** 6200 * Lists all availble windows in the system. The listing is written in the 6201 * specified Socket's output stream with the following syntax: 6202 * windowHashCodeInHexadecimal windowName 6203 * Each line of the ouput represents a different window. 6204 * 6205 * @param client The remote client to send the listing to. 6206 * @return False if an error occured, true otherwise. 6207 */ 6208 boolean viewServerListWindows(Socket client) { 6209 if (isSystemSecure()) { 6210 return false; 6211 } 6212 6213 boolean result = true; 6214 6215 WindowList windows = new WindowList(); 6216 synchronized (mWindowMap) { 6217 //noinspection unchecked 6218 final int numDisplays = mDisplayContents.size(); 6219 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6220 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 6221 windows.addAll(displayContent.getWindowList()); 6222 } 6223 } 6224 6225 BufferedWriter out = null; 6226 6227 // Any uncaught exception will crash the system process 6228 try { 6229 OutputStream clientStream = client.getOutputStream(); 6230 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6231 6232 final int count = windows.size(); 6233 for (int i = 0; i < count; i++) { 6234 final WindowState w = windows.get(i); 6235 out.write(Integer.toHexString(System.identityHashCode(w))); 6236 out.write(' '); 6237 out.append(w.mAttrs.getTitle()); 6238 out.write('\n'); 6239 } 6240 6241 out.write("DONE.\n"); 6242 out.flush(); 6243 } catch (Exception e) { 6244 result = false; 6245 } finally { 6246 if (out != null) { 6247 try { 6248 out.close(); 6249 } catch (IOException e) { 6250 result = false; 6251 } 6252 } 6253 } 6254 6255 return result; 6256 } 6257 6258 // TODO(multidisplay): Extend to multiple displays. 6259 /** 6260 * Returns the focused window in the following format: 6261 * windowHashCodeInHexadecimal windowName 6262 * 6263 * @param client The remote client to send the listing to. 6264 * @return False if an error occurred, true otherwise. 6265 */ 6266 boolean viewServerGetFocusedWindow(Socket client) { 6267 if (isSystemSecure()) { 6268 return false; 6269 } 6270 6271 boolean result = true; 6272 6273 WindowState focusedWindow = getFocusedWindow(); 6274 6275 BufferedWriter out = null; 6276 6277 // Any uncaught exception will crash the system process 6278 try { 6279 OutputStream clientStream = client.getOutputStream(); 6280 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6281 6282 if(focusedWindow != null) { 6283 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 6284 out.write(' '); 6285 out.append(focusedWindow.mAttrs.getTitle()); 6286 } 6287 out.write('\n'); 6288 out.flush(); 6289 } catch (Exception e) { 6290 result = false; 6291 } finally { 6292 if (out != null) { 6293 try { 6294 out.close(); 6295 } catch (IOException e) { 6296 result = false; 6297 } 6298 } 6299 } 6300 6301 return result; 6302 } 6303 6304 /** 6305 * Sends a command to a target window. The result of the command, if any, will be 6306 * written in the output stream of the specified socket. 6307 * 6308 * The parameters must follow this syntax: 6309 * windowHashcode extra 6310 * 6311 * Where XX is the length in characeters of the windowTitle. 6312 * 6313 * The first parameter is the target window. The window with the specified hashcode 6314 * will be the target. If no target can be found, nothing happens. The extra parameters 6315 * will be delivered to the target window and as parameters to the command itself. 6316 * 6317 * @param client The remote client to sent the result, if any, to. 6318 * @param command The command to execute. 6319 * @param parameters The command parameters. 6320 * 6321 * @return True if the command was successfully delivered, false otherwise. This does 6322 * not indicate whether the command itself was successful. 6323 */ 6324 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 6325 if (isSystemSecure()) { 6326 return false; 6327 } 6328 6329 boolean success = true; 6330 Parcel data = null; 6331 Parcel reply = null; 6332 6333 BufferedWriter out = null; 6334 6335 // Any uncaught exception will crash the system process 6336 try { 6337 // Find the hashcode of the window 6338 int index = parameters.indexOf(' '); 6339 if (index == -1) { 6340 index = parameters.length(); 6341 } 6342 final String code = parameters.substring(0, index); 6343 int hashCode = (int) Long.parseLong(code, 16); 6344 6345 // Extract the command's parameter after the window description 6346 if (index < parameters.length()) { 6347 parameters = parameters.substring(index + 1); 6348 } else { 6349 parameters = ""; 6350 } 6351 6352 final WindowState window = findWindow(hashCode); 6353 if (window == null) { 6354 return false; 6355 } 6356 6357 data = Parcel.obtain(); 6358 data.writeInterfaceToken("android.view.IWindow"); 6359 data.writeString(command); 6360 data.writeString(parameters); 6361 data.writeInt(1); 6362 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 6363 6364 reply = Parcel.obtain(); 6365 6366 final IBinder binder = window.mClient.asBinder(); 6367 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 6368 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 6369 6370 reply.readException(); 6371 6372 if (!client.isOutputShutdown()) { 6373 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 6374 out.write("DONE\n"); 6375 out.flush(); 6376 } 6377 6378 } catch (Exception e) { 6379 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); 6380 success = false; 6381 } finally { 6382 if (data != null) { 6383 data.recycle(); 6384 } 6385 if (reply != null) { 6386 reply.recycle(); 6387 } 6388 if (out != null) { 6389 try { 6390 out.close(); 6391 } catch (IOException e) { 6392 6393 } 6394 } 6395 } 6396 6397 return success; 6398 } 6399 6400 public void addWindowChangeListener(WindowChangeListener listener) { 6401 synchronized(mWindowMap) { 6402 mWindowChangeListeners.add(listener); 6403 } 6404 } 6405 6406 public void removeWindowChangeListener(WindowChangeListener listener) { 6407 synchronized(mWindowMap) { 6408 mWindowChangeListeners.remove(listener); 6409 } 6410 } 6411 6412 private void notifyWindowsChanged() { 6413 WindowChangeListener[] windowChangeListeners; 6414 synchronized(mWindowMap) { 6415 if(mWindowChangeListeners.isEmpty()) { 6416 return; 6417 } 6418 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6419 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6420 } 6421 int N = windowChangeListeners.length; 6422 for(int i = 0; i < N; i++) { 6423 windowChangeListeners[i].windowsChanged(); 6424 } 6425 } 6426 6427 private void notifyFocusChanged() { 6428 WindowChangeListener[] windowChangeListeners; 6429 synchronized(mWindowMap) { 6430 if(mWindowChangeListeners.isEmpty()) { 6431 return; 6432 } 6433 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6434 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6435 } 6436 int N = windowChangeListeners.length; 6437 for(int i = 0; i < N; i++) { 6438 windowChangeListeners[i].focusChanged(); 6439 } 6440 } 6441 6442 private WindowState findWindow(int hashCode) { 6443 if (hashCode == -1) { 6444 // TODO(multidisplay): Extend to multiple displays. 6445 return getFocusedWindow(); 6446 } 6447 6448 synchronized (mWindowMap) { 6449 final int numDisplays = mDisplayContents.size(); 6450 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6451 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 6452 final int numWindows = windows.size(); 6453 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 6454 final WindowState w = windows.get(winNdx); 6455 if (System.identityHashCode(w) == hashCode) { 6456 return w; 6457 } 6458 } 6459 } 6460 } 6461 6462 return null; 6463 } 6464 6465 /* 6466 * Instruct the Activity Manager to fetch the current configuration and broadcast 6467 * that to config-changed listeners if appropriate. 6468 */ 6469 void sendNewConfiguration() { 6470 try { 6471 mActivityManager.updateConfiguration(null); 6472 } catch (RemoteException e) { 6473 } 6474 } 6475 6476 public Configuration computeNewConfiguration() { 6477 synchronized (mWindowMap) { 6478 Configuration config = computeNewConfigurationLocked(); 6479 if (config == null && mWaitingForConfig) { 6480 // Nothing changed but we are waiting for something... stop that! 6481 mWaitingForConfig = false; 6482 mLastFinishedFreezeSource = "new-config"; 6483 performLayoutAndPlaceSurfacesLocked(); 6484 } 6485 return config; 6486 } 6487 } 6488 6489 Configuration computeNewConfigurationLocked() { 6490 Configuration config = new Configuration(); 6491 config.fontScale = 0; 6492 if (!computeScreenConfigurationLocked(config)) { 6493 return null; 6494 } 6495 return config; 6496 } 6497 6498 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) { 6499 // TODO: Multidisplay: for now only use with default display. 6500 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation); 6501 if (width < displayInfo.smallestNominalAppWidth) { 6502 displayInfo.smallestNominalAppWidth = width; 6503 } 6504 if (width > displayInfo.largestNominalAppWidth) { 6505 displayInfo.largestNominalAppWidth = width; 6506 } 6507 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation); 6508 if (height < displayInfo.smallestNominalAppHeight) { 6509 displayInfo.smallestNominalAppHeight = height; 6510 } 6511 if (height > displayInfo.largestNominalAppHeight) { 6512 displayInfo.largestNominalAppHeight = height; 6513 } 6514 } 6515 6516 private int reduceConfigLayout(int curLayout, int rotation, float density, 6517 int dw, int dh) { 6518 // TODO: Multidisplay: for now only use with default display. 6519 // Get the app screen size at this rotation. 6520 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6521 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6522 6523 // Compute the screen layout size class for this rotation. 6524 int longSize = w; 6525 int shortSize = h; 6526 if (longSize < shortSize) { 6527 int tmp = longSize; 6528 longSize = shortSize; 6529 shortSize = tmp; 6530 } 6531 longSize = (int)(longSize/density); 6532 shortSize = (int)(shortSize/density); 6533 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 6534 } 6535 6536 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 6537 int dw, int dh, float density, Configuration outConfig) { 6538 // TODO: Multidisplay: for now only use with default display. 6539 6540 // We need to determine the smallest width that will occur under normal 6541 // operation. To this, start with the base screen size and compute the 6542 // width under the different possible rotations. We need to un-rotate 6543 // the current screen dimensions before doing this. 6544 int unrotDw, unrotDh; 6545 if (rotated) { 6546 unrotDw = dh; 6547 unrotDh = dw; 6548 } else { 6549 unrotDw = dw; 6550 unrotDh = dh; 6551 } 6552 displayInfo.smallestNominalAppWidth = 1<<30; 6553 displayInfo.smallestNominalAppHeight = 1<<30; 6554 displayInfo.largestNominalAppWidth = 0; 6555 displayInfo.largestNominalAppHeight = 0; 6556 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh); 6557 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw); 6558 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh); 6559 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw); 6560 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 6561 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh); 6562 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw); 6563 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); 6564 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); 6565 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 6566 outConfig.screenLayout = sl; 6567 } 6568 6569 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, 6570 int dw, int dh) { 6571 // TODO: Multidisplay: for now only use with default display. 6572 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6573 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6574 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 6575 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 6576 if (curSize == 0 || size < curSize) { 6577 curSize = size; 6578 } 6579 return curSize; 6580 } 6581 6582 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) { 6583 // TODO: Multidisplay: for now only use with default display. 6584 mTmpDisplayMetrics.setTo(dm); 6585 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 6586 final int unrotDw, unrotDh; 6587 if (rotated) { 6588 unrotDw = dh; 6589 unrotDh = dw; 6590 } else { 6591 unrotDw = dw; 6592 unrotDh = dh; 6593 } 6594 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh); 6595 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw); 6596 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh); 6597 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw); 6598 return sw; 6599 } 6600 6601 boolean computeScreenConfigurationLocked(Configuration config) { 6602 if (!mDisplayReady) { 6603 return false; 6604 } 6605 6606 // TODO(multidisplay): For now, apply Configuration to main screen only. 6607 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6608 6609 // Use the effective "visual" dimensions based on current rotation 6610 final boolean rotated = (mRotation == Surface.ROTATION_90 6611 || mRotation == Surface.ROTATION_270); 6612 final int realdw = rotated ? 6613 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; 6614 final int realdh = rotated ? 6615 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; 6616 int dw = realdw; 6617 int dh = realdh; 6618 6619 if (mAltOrientation) { 6620 if (realdw > realdh) { 6621 // Turn landscape into portrait. 6622 int maxw = (int)(realdh/1.3f); 6623 if (maxw < realdw) { 6624 dw = maxw; 6625 } 6626 } else { 6627 // Turn portrait into landscape. 6628 int maxh = (int)(realdw/1.3f); 6629 if (maxh < realdh) { 6630 dh = maxh; 6631 } 6632 } 6633 } 6634 6635 if (config != null) { 6636 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : 6637 Configuration.ORIENTATION_LANDSCAPE; 6638 } 6639 6640 // Update application display metrics. 6641 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); 6642 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); 6643 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6644 synchronized(displayContent.mDisplaySizeLock) { 6645 displayInfo.rotation = mRotation; 6646 displayInfo.logicalWidth = dw; 6647 displayInfo.logicalHeight = dh; 6648 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; 6649 displayInfo.appWidth = appWidth; 6650 displayInfo.appHeight = appHeight; 6651 displayInfo.getLogicalMetrics(mRealDisplayMetrics, 6652 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 6653 displayInfo.getAppMetrics(mDisplayMetrics); 6654 mDisplayManagerService.setDisplayInfoOverrideFromWindowManager( 6655 displayContent.getDisplayId(), displayInfo); 6656 } 6657 if (false) { 6658 Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); 6659 } 6660 6661 final DisplayMetrics dm = mDisplayMetrics; 6662 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, 6663 mCompatDisplayMetrics); 6664 6665 if (config != null) { 6666 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) 6667 / dm.density); 6668 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) 6669 / dm.density); 6670 computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config); 6671 6672 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 6673 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 6674 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); 6675 config.densityDpi = displayContent.mBaseDisplayDensity; 6676 6677 // Update the configuration based on available input devices, lid switch, 6678 // and platform configuration. 6679 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6680 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6681 config.navigation = Configuration.NAVIGATION_NONAV; 6682 6683 int keyboardPresence = 0; 6684 int navigationPresence = 0; 6685 final InputDevice[] devices = mInputManager.getInputDevices(); 6686 final int len = devices.length; 6687 for (int i = 0; i < len; i++) { 6688 InputDevice device = devices[i]; 6689 if (!device.isVirtual()) { 6690 final int sources = device.getSources(); 6691 final int presenceFlag = device.isExternal() ? 6692 WindowManagerPolicy.PRESENCE_EXTERNAL : 6693 WindowManagerPolicy.PRESENCE_INTERNAL; 6694 6695 if (mIsTouchDevice) { 6696 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 6697 InputDevice.SOURCE_TOUCHSCREEN) { 6698 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 6699 } 6700 } else { 6701 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6702 } 6703 6704 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 6705 config.navigation = Configuration.NAVIGATION_TRACKBALL; 6706 navigationPresence |= presenceFlag; 6707 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 6708 && config.navigation == Configuration.NAVIGATION_NONAV) { 6709 config.navigation = Configuration.NAVIGATION_DPAD; 6710 navigationPresence |= presenceFlag; 6711 } 6712 6713 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 6714 config.keyboard = Configuration.KEYBOARD_QWERTY; 6715 keyboardPresence |= presenceFlag; 6716 } 6717 } 6718 } 6719 6720 // Determine whether a hard keyboard is available and enabled. 6721 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 6722 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 6723 mHardKeyboardAvailable = hardKeyboardAvailable; 6724 mHardKeyboardEnabled = hardKeyboardAvailable; 6725 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6726 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6727 } 6728 if (!mHardKeyboardEnabled) { 6729 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6730 } 6731 6732 // Let the policy update hidden states. 6733 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 6734 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 6735 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 6736 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 6737 } 6738 6739 return true; 6740 } 6741 6742 public boolean isHardKeyboardAvailable() { 6743 synchronized (mWindowMap) { 6744 return mHardKeyboardAvailable; 6745 } 6746 } 6747 6748 public boolean isHardKeyboardEnabled() { 6749 synchronized (mWindowMap) { 6750 return mHardKeyboardEnabled; 6751 } 6752 } 6753 6754 public void setHardKeyboardEnabled(boolean enabled) { 6755 synchronized (mWindowMap) { 6756 if (mHardKeyboardEnabled != enabled) { 6757 mHardKeyboardEnabled = enabled; 6758 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6759 } 6760 } 6761 } 6762 6763 public void setOnHardKeyboardStatusChangeListener( 6764 OnHardKeyboardStatusChangeListener listener) { 6765 synchronized (mWindowMap) { 6766 mHardKeyboardStatusChangeListener = listener; 6767 } 6768 } 6769 6770 void notifyHardKeyboardStatusChange() { 6771 final boolean available, enabled; 6772 final OnHardKeyboardStatusChangeListener listener; 6773 synchronized (mWindowMap) { 6774 listener = mHardKeyboardStatusChangeListener; 6775 available = mHardKeyboardAvailable; 6776 enabled = mHardKeyboardEnabled; 6777 } 6778 if (listener != null) { 6779 listener.onHardKeyboardStatusChange(available, enabled); 6780 } 6781 } 6782 6783 // ------------------------------------------------------------- 6784 // Drag and drop 6785 // ------------------------------------------------------------- 6786 6787 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 6788 int flags, int width, int height, Surface outSurface) { 6789 if (DEBUG_DRAG) { 6790 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 6791 + " flags=" + Integer.toHexString(flags) + " win=" + window 6792 + " asbinder=" + window.asBinder()); 6793 } 6794 6795 final int callerPid = Binder.getCallingPid(); 6796 final long origId = Binder.clearCallingIdentity(); 6797 IBinder token = null; 6798 6799 try { 6800 synchronized (mWindowMap) { 6801 try { 6802 if (mDragState == null) { 6803 // TODO(multi-display): support other displays 6804 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6805 final Display display = displayContent.getDisplay(); 6806 SurfaceControl surface = new SurfaceControl(session, "drag surface", 6807 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 6808 surface.setLayerStack(display.getLayerStack()); 6809 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 6810 + surface + ": CREATE"); 6811 outSurface.copyFrom(surface); 6812 final IBinder winBinder = window.asBinder(); 6813 token = new Binder(); 6814 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 6815 token = mDragState.mToken = new Binder(); 6816 6817 // 5 second timeout for this window to actually begin the drag 6818 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 6819 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 6820 mH.sendMessageDelayed(msg, 5000); 6821 } else { 6822 Slog.w(TAG, "Drag already in progress"); 6823 } 6824 } catch (OutOfResourcesException e) { 6825 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 6826 if (mDragState != null) { 6827 mDragState.reset(); 6828 mDragState = null; 6829 } 6830 } 6831 } 6832 } finally { 6833 Binder.restoreCallingIdentity(origId); 6834 } 6835 6836 return token; 6837 } 6838 6839 // ------------------------------------------------------------- 6840 // Input Events and Focus Management 6841 // ------------------------------------------------------------- 6842 6843 final InputMonitor mInputMonitor = new InputMonitor(this); 6844 private boolean mEventDispatchingEnabled; 6845 6846 @Override 6847 public void pauseKeyDispatching(IBinder _token) { 6848 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6849 "pauseKeyDispatching()")) { 6850 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6851 } 6852 6853 synchronized (mWindowMap) { 6854 WindowToken token = mTokenMap.get(_token); 6855 if (token != null) { 6856 mInputMonitor.pauseDispatchingLw(token); 6857 } 6858 } 6859 } 6860 6861 @Override 6862 public void resumeKeyDispatching(IBinder _token) { 6863 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6864 "resumeKeyDispatching()")) { 6865 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6866 } 6867 6868 synchronized (mWindowMap) { 6869 WindowToken token = mTokenMap.get(_token); 6870 if (token != null) { 6871 mInputMonitor.resumeDispatchingLw(token); 6872 } 6873 } 6874 } 6875 6876 @Override 6877 public void setEventDispatching(boolean enabled) { 6878 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6879 "setEventDispatching()")) { 6880 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6881 } 6882 6883 synchronized (mWindowMap) { 6884 mEventDispatchingEnabled = enabled; 6885 if (mDisplayEnabled) { 6886 mInputMonitor.setEventDispatchingLw(enabled); 6887 } 6888 sendScreenStatusToClientsLocked(); 6889 } 6890 } 6891 6892 @Override 6893 public IBinder getFocusedWindowToken() { 6894 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 6895 "getFocusedWindowToken()")) { 6896 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission."); 6897 } 6898 synchronized (mWindowMap) { 6899 WindowState windowState = getFocusedWindowLocked(); 6900 if (windowState != null) { 6901 return windowState.mClient.asBinder(); 6902 } 6903 return null; 6904 } 6905 } 6906 6907 private WindowState getFocusedWindow() { 6908 synchronized (mWindowMap) { 6909 return getFocusedWindowLocked(); 6910 } 6911 } 6912 6913 private WindowState getFocusedWindowLocked() { 6914 return mCurrentFocus; 6915 } 6916 6917 public boolean detectSafeMode() { 6918 if (!mInputMonitor.waitForInputDevicesReady( 6919 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 6920 Slog.w(TAG, "Devices still not ready after waiting " 6921 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 6922 + " milliseconds before attempting to detect safe mode."); 6923 } 6924 6925 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 6926 KeyEvent.KEYCODE_MENU); 6927 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 6928 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 6929 KeyEvent.KEYCODE_DPAD_CENTER); 6930 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 6931 InputManagerService.BTN_MOUSE); 6932 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 6933 KeyEvent.KEYCODE_VOLUME_DOWN); 6934 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 6935 || volumeDownState > 0; 6936 try { 6937 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 6938 mSafeMode = true; 6939 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 6940 } 6941 } catch (IllegalArgumentException e) { 6942 } 6943 if (mSafeMode) { 6944 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 6945 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 6946 } else { 6947 Log.i(TAG, "SAFE MODE not enabled"); 6948 } 6949 mPolicy.setSafeMode(mSafeMode); 6950 return mSafeMode; 6951 } 6952 6953 public void displayReady() { 6954 displayReady(Display.DEFAULT_DISPLAY); 6955 6956 synchronized(mWindowMap) { 6957 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6958 readForcedDisplaySizeAndDensityLocked(displayContent); 6959 mDisplayReady = true; 6960 } 6961 6962 try { 6963 mActivityManager.updateConfiguration(null); 6964 } catch (RemoteException e) { 6965 } 6966 6967 synchronized(mWindowMap) { 6968 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 6969 PackageManager.FEATURE_TOUCHSCREEN); 6970 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 6971 } 6972 6973 try { 6974 mActivityManager.updateConfiguration(null); 6975 } catch (RemoteException e) { 6976 } 6977 } 6978 6979 private void displayReady(int displayId) { 6980 synchronized(mWindowMap) { 6981 final DisplayContent displayContent = getDisplayContentLocked(displayId); 6982 if (displayContent != null) { 6983 mAnimator.addDisplayLocked(displayId); 6984 synchronized(displayContent.mDisplaySizeLock) { 6985 // Bootstrap the default logical display from the display manager. 6986 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6987 DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId); 6988 if (newDisplayInfo != null) { 6989 displayInfo.copyFrom(newDisplayInfo); 6990 } 6991 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; 6992 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; 6993 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; 6994 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; 6995 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; 6996 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; 6997 displayContent.mBaseDisplayRect.set(0, 0, 6998 displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight); 6999 } 7000 } 7001 } 7002 } 7003 7004 public void systemReady() { 7005 mPolicy.systemReady(); 7006 } 7007 7008 // TODO(multidisplay): Call isScreenOn for each display. 7009 private void sendScreenStatusToClientsLocked() { 7010 final boolean on = mPowerManager.isScreenOn(); 7011 final int numDisplays = mDisplayContents.size(); 7012 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 7013 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 7014 final int numWindows = windows.size(); 7015 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 7016 try { 7017 windows.get(winNdx).mClient.dispatchScreenState(on); 7018 } catch (RemoteException e) { 7019 // Ignored 7020 } 7021 } 7022 } 7023 } 7024 7025 // ------------------------------------------------------------- 7026 // Async Handler 7027 // ------------------------------------------------------------- 7028 7029 final class H extends Handler { 7030 public static final int REPORT_FOCUS_CHANGE = 2; 7031 public static final int REPORT_LOSING_FOCUS = 3; 7032 public static final int DO_TRAVERSAL = 4; 7033 public static final int ADD_STARTING = 5; 7034 public static final int REMOVE_STARTING = 6; 7035 public static final int FINISHED_STARTING = 7; 7036 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 7037 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 7038 public static final int WINDOW_FREEZE_TIMEOUT = 11; 7039 7040 public static final int APP_TRANSITION_TIMEOUT = 13; 7041 public static final int PERSIST_ANIMATION_SCALE = 14; 7042 public static final int FORCE_GC = 15; 7043 public static final int ENABLE_SCREEN = 16; 7044 public static final int APP_FREEZE_TIMEOUT = 17; 7045 public static final int SEND_NEW_CONFIGURATION = 18; 7046 public static final int REPORT_WINDOWS_CHANGE = 19; 7047 public static final int DRAG_START_TIMEOUT = 20; 7048 public static final int DRAG_END_TIMEOUT = 21; 7049 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 7050 public static final int BOOT_TIMEOUT = 23; 7051 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 7052 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 7053 public static final int DO_ANIMATION_CALLBACK = 26; 7054 7055 public static final int DO_DISPLAY_ADDED = 27; 7056 public static final int DO_DISPLAY_REMOVED = 28; 7057 public static final int DO_DISPLAY_CHANGED = 29; 7058 7059 public static final int CLIENT_FREEZE_TIMEOUT = 30; 7060 public static final int TAP_OUTSIDE_STACK = 31; 7061 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 7062 7063 public static final int REMOVE_STARTING_TIMEOUT = 33; 7064 7065 @Override 7066 public void handleMessage(Message msg) { 7067 if (DEBUG_WINDOW_TRACE) { 7068 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 7069 } 7070 switch (msg.what) { 7071 case REPORT_FOCUS_CHANGE: { 7072 WindowState lastFocus; 7073 WindowState newFocus; 7074 7075 synchronized(mWindowMap) { 7076 lastFocus = mLastFocus; 7077 newFocus = mCurrentFocus; 7078 if (lastFocus == newFocus) { 7079 // Focus is not changing, so nothing to do. 7080 return; 7081 } 7082 mLastFocus = newFocus; 7083 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus + 7084 " to " + newFocus); 7085 if (newFocus != null && lastFocus != null 7086 && !newFocus.isDisplayedLw()) { 7087 //Slog.i(TAG, "Delaying loss of focus..."); 7088 mLosingFocus.add(lastFocus); 7089 lastFocus = null; 7090 } 7091 } 7092 7093 //System.out.println("Changing focus from " + lastFocus 7094 // + " to " + newFocus); 7095 if (newFocus != null) { 7096 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus); 7097 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 7098 notifyFocusChanged(); 7099 } 7100 7101 if (lastFocus != null) { 7102 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus); 7103 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 7104 } 7105 } break; 7106 7107 case REPORT_LOSING_FOCUS: { 7108 ArrayList<WindowState> losers; 7109 7110 synchronized(mWindowMap) { 7111 losers = mLosingFocus; 7112 mLosingFocus = new ArrayList<WindowState>(); 7113 } 7114 7115 final int N = losers.size(); 7116 for (int i=0; i<N; i++) { 7117 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " + 7118 losers.get(i)); 7119 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 7120 } 7121 } break; 7122 7123 case DO_TRAVERSAL: { 7124 synchronized(mWindowMap) { 7125 mTraversalScheduled = false; 7126 performLayoutAndPlaceSurfacesLocked(); 7127 } 7128 } break; 7129 7130 case ADD_STARTING: { 7131 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7132 final StartingData sd = wtoken.startingData; 7133 7134 if (sd == null) { 7135 // Animation has been canceled... do nothing. 7136 return; 7137 } 7138 7139 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 7140 + wtoken + ": pkg=" + sd.pkg); 7141 7142 View view = null; 7143 try { 7144 view = mPolicy.addStartingWindow( 7145 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 7146 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags); 7147 } catch (Exception e) { 7148 Slog.w(TAG, "Exception when adding starting window", e); 7149 } 7150 7151 if (view != null) { 7152 boolean abort = false; 7153 7154 synchronized(mWindowMap) { 7155 if (wtoken.removed || wtoken.startingData == null) { 7156 // If the window was successfully added, then 7157 // we need to remove it. 7158 if (wtoken.startingWindow != null) { 7159 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7160 "Aborted starting " + wtoken 7161 + ": removed=" + wtoken.removed 7162 + " startingData=" + wtoken.startingData); 7163 removeStartingWindowTimeout(wtoken); 7164 wtoken.startingWindow = null; 7165 wtoken.startingData = null; 7166 abort = true; 7167 } 7168 } else { 7169 wtoken.startingView = view; 7170 } 7171 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7172 "Added starting " + wtoken 7173 + ": startingWindow=" 7174 + wtoken.startingWindow + " startingView=" 7175 + wtoken.startingView); 7176 } 7177 7178 if (abort) { 7179 try { 7180 mPolicy.removeStartingWindow(wtoken.token, view); 7181 } catch (Exception e) { 7182 Slog.w(TAG, "Exception when removing starting window", e); 7183 } 7184 } 7185 } 7186 } break; 7187 7188 case REMOVE_STARTING_TIMEOUT: { 7189 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7190 Slog.e(TAG, "Starting window " + wtoken + " timed out"); 7191 // Fall through. 7192 } 7193 case REMOVE_STARTING: { 7194 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7195 IBinder token = null; 7196 View view = null; 7197 synchronized (mWindowMap) { 7198 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7199 + wtoken + ": startingWindow=" 7200 + wtoken.startingWindow + " startingView=" 7201 + wtoken.startingView); 7202 if (wtoken.startingWindow != null) { 7203 view = wtoken.startingView; 7204 token = wtoken.token; 7205 wtoken.startingData = null; 7206 wtoken.startingView = null; 7207 wtoken.startingWindow = null; 7208 wtoken.startingDisplayed = false; 7209 } 7210 } 7211 if (view != null) { 7212 try { 7213 mPolicy.removeStartingWindow(token, view); 7214 } catch (Exception e) { 7215 Slog.w(TAG, "Exception when removing starting window", e); 7216 } 7217 } 7218 } break; 7219 7220 case FINISHED_STARTING: { 7221 IBinder token = null; 7222 View view = null; 7223 while (true) { 7224 synchronized (mWindowMap) { 7225 final int N = mFinishedStarting.size(); 7226 if (N <= 0) { 7227 break; 7228 } 7229 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7230 7231 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7232 "Finished starting " + wtoken 7233 + ": startingWindow=" + wtoken.startingWindow 7234 + " startingView=" + wtoken.startingView); 7235 7236 if (wtoken.startingWindow == null) { 7237 continue; 7238 } 7239 7240 view = wtoken.startingView; 7241 token = wtoken.token; 7242 wtoken.startingData = null; 7243 wtoken.startingView = null; 7244 wtoken.startingWindow = null; 7245 wtoken.startingDisplayed = false; 7246 } 7247 7248 try { 7249 mPolicy.removeStartingWindow(token, view); 7250 } catch (Exception e) { 7251 Slog.w(TAG, "Exception when removing starting window", e); 7252 } 7253 } 7254 } break; 7255 7256 case REPORT_APPLICATION_TOKEN_DRAWN: { 7257 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7258 7259 try { 7260 if (DEBUG_VISIBILITY) Slog.v( 7261 TAG, "Reporting drawn in " + wtoken); 7262 wtoken.appToken.windowsDrawn(); 7263 } catch (RemoteException ex) { 7264 } 7265 } break; 7266 7267 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7268 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7269 7270 boolean nowVisible = msg.arg1 != 0; 7271 boolean nowGone = msg.arg2 != 0; 7272 7273 try { 7274 if (DEBUG_VISIBILITY) Slog.v( 7275 TAG, "Reporting visible in " + wtoken 7276 + " visible=" + nowVisible 7277 + " gone=" + nowGone); 7278 if (nowVisible) { 7279 wtoken.appToken.windowsVisible(); 7280 } else { 7281 wtoken.appToken.windowsGone(); 7282 } 7283 } catch (RemoteException ex) { 7284 } 7285 } break; 7286 7287 case WINDOW_FREEZE_TIMEOUT: { 7288 // TODO(multidisplay): Can non-default displays rotate? 7289 synchronized (mWindowMap) { 7290 Slog.w(TAG, "Window freeze timeout expired."); 7291 final WindowList windows = getDefaultWindowListLocked(); 7292 int i = windows.size(); 7293 while (i > 0) { 7294 i--; 7295 WindowState w = windows.get(i); 7296 if (w.mOrientationChanging) { 7297 w.mOrientationChanging = false; 7298 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 7299 - mDisplayFreezeTime); 7300 Slog.w(TAG, "Force clearing orientation change: " + w); 7301 } 7302 } 7303 performLayoutAndPlaceSurfacesLocked(); 7304 } 7305 break; 7306 } 7307 7308 case APP_TRANSITION_TIMEOUT: { 7309 synchronized (mWindowMap) { 7310 if (mAppTransition.isTransitionSet()) { 7311 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT"); 7312 mAppTransition.setTimeout(); 7313 performLayoutAndPlaceSurfacesLocked(); 7314 } 7315 } 7316 break; 7317 } 7318 7319 case PERSIST_ANIMATION_SCALE: { 7320 Settings.Global.putFloat(mContext.getContentResolver(), 7321 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); 7322 Settings.Global.putFloat(mContext.getContentResolver(), 7323 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); 7324 Settings.Global.putFloat(mContext.getContentResolver(), 7325 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale); 7326 break; 7327 } 7328 7329 case FORCE_GC: { 7330 synchronized (mWindowMap) { 7331 // Since we're holding both mWindowMap and mAnimator we don't need to 7332 // hold mAnimator.mLayoutToAnim. 7333 if (mAnimator.mAnimating || mAnimationScheduled) { 7334 // If we are animating, don't do the gc now but 7335 // delay a bit so we don't interrupt the animation. 7336 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 7337 return; 7338 } 7339 // If we are currently rotating the display, it will 7340 // schedule a new message when done. 7341 if (mDisplayFrozen) { 7342 return; 7343 } 7344 } 7345 Runtime.getRuntime().gc(); 7346 break; 7347 } 7348 7349 case ENABLE_SCREEN: { 7350 performEnableScreen(); 7351 break; 7352 } 7353 7354 case APP_FREEZE_TIMEOUT: { 7355 synchronized (mWindowMap) { 7356 Slog.w(TAG, "App freeze timeout expired."); 7357 DisplayContent displayContent = getDefaultDisplayContentLocked(); 7358 final ArrayList<Task> tasks = displayContent.getTasks(); 7359 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 7360 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 7361 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 7362 AppWindowToken tok = tokens.get(tokenNdx); 7363 if (tok.mAppAnimator.freezingScreen) { 7364 Slog.w(TAG, "Force clearing freeze: " + tok); 7365 unsetAppFreezingScreenLocked(tok, true, true); 7366 } 7367 } 7368 } 7369 } 7370 break; 7371 } 7372 7373 case CLIENT_FREEZE_TIMEOUT: { 7374 synchronized (mWindowMap) { 7375 if (mClientFreezingScreen) { 7376 mClientFreezingScreen = false; 7377 mLastFinishedFreezeSource = "client-timeout"; 7378 stopFreezingDisplayLocked(); 7379 } 7380 } 7381 break; 7382 } 7383 7384 case SEND_NEW_CONFIGURATION: { 7385 removeMessages(SEND_NEW_CONFIGURATION); 7386 sendNewConfiguration(); 7387 break; 7388 } 7389 7390 case REPORT_WINDOWS_CHANGE: { 7391 if (mWindowsChanged) { 7392 synchronized (mWindowMap) { 7393 mWindowsChanged = false; 7394 } 7395 notifyWindowsChanged(); 7396 } 7397 break; 7398 } 7399 7400 case DRAG_START_TIMEOUT: { 7401 IBinder win = (IBinder)msg.obj; 7402 if (DEBUG_DRAG) { 7403 Slog.w(TAG, "Timeout starting drag by win " + win); 7404 } 7405 synchronized (mWindowMap) { 7406 // !!! TODO: ANR the app that has failed to start the drag in time 7407 if (mDragState != null) { 7408 mDragState.unregister(); 7409 mInputMonitor.updateInputWindowsLw(true /*force*/); 7410 mDragState.reset(); 7411 mDragState = null; 7412 } 7413 } 7414 break; 7415 } 7416 7417 case DRAG_END_TIMEOUT: { 7418 IBinder win = (IBinder)msg.obj; 7419 if (DEBUG_DRAG) { 7420 Slog.w(TAG, "Timeout ending drag to win " + win); 7421 } 7422 synchronized (mWindowMap) { 7423 // !!! TODO: ANR the drag-receiving app 7424 if (mDragState != null) { 7425 mDragState.mDragResult = false; 7426 mDragState.endDragLw(); 7427 } 7428 } 7429 break; 7430 } 7431 7432 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7433 notifyHardKeyboardStatusChange(); 7434 break; 7435 } 7436 7437 case BOOT_TIMEOUT: { 7438 performBootTimeout(); 7439 break; 7440 } 7441 7442 case WAITING_FOR_DRAWN_TIMEOUT: { 7443 Pair<WindowState, IRemoteCallback> pair; 7444 synchronized (mWindowMap) { 7445 pair = (Pair<WindowState, IRemoteCallback>)msg.obj; 7446 Slog.w(TAG, "Timeout waiting for drawn: " + pair.first); 7447 if (!mWaitingForDrawn.remove(pair)) { 7448 return; 7449 } 7450 } 7451 try { 7452 pair.second.sendResult(null); 7453 } catch (RemoteException e) { 7454 } 7455 break; 7456 } 7457 7458 case SHOW_STRICT_MODE_VIOLATION: { 7459 showStrictModeViolation(msg.arg1, msg.arg2); 7460 break; 7461 } 7462 7463 case DO_ANIMATION_CALLBACK: { 7464 try { 7465 ((IRemoteCallback)msg.obj).sendResult(null); 7466 } catch (RemoteException e) { 7467 } 7468 break; 7469 } 7470 7471 case DO_DISPLAY_ADDED: 7472 synchronized (mWindowMap) { 7473 handleDisplayAddedLocked(msg.arg1); 7474 } 7475 break; 7476 7477 case DO_DISPLAY_REMOVED: 7478 synchronized (mWindowMap) { 7479 handleDisplayRemovedLocked(msg.arg1); 7480 } 7481 break; 7482 7483 case DO_DISPLAY_CHANGED: 7484 synchronized (mWindowMap) { 7485 handleDisplayChangedLocked(msg.arg1); 7486 } 7487 break; 7488 7489 case TAP_OUTSIDE_STACK: { 7490 int stackId; 7491 synchronized (mWindowMap) { 7492 stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2); 7493 } 7494 if (stackId >= 0) { 7495 try { 7496 mActivityManager.setFocusedStack(stackId); 7497 } catch (RemoteException e) { 7498 } 7499 } 7500 } 7501 break; 7502 case NOTIFY_ACTIVITY_DRAWN: 7503 try { 7504 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 7505 } catch (RemoteException e) { 7506 } 7507 break; 7508 } 7509 if (DEBUG_WINDOW_TRACE) { 7510 Slog.v(TAG, "handleMessage: exit"); 7511 } 7512 } 7513 } 7514 7515 // ------------------------------------------------------------- 7516 // IWindowManager API 7517 // ------------------------------------------------------------- 7518 7519 @Override 7520 public IWindowSession openSession(IInputMethodClient client, 7521 IInputContext inputContext) { 7522 if (client == null) throw new IllegalArgumentException("null client"); 7523 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7524 Session session = new Session(this, client, inputContext); 7525 return session; 7526 } 7527 7528 @Override 7529 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7530 synchronized (mWindowMap) { 7531 // The focus for the client is the window immediately below 7532 // where we would place the input method window. 7533 int idx = findDesiredInputMethodWindowIndexLocked(false); 7534 if (idx > 0) { 7535 // TODO(multidisplay): IMEs are only supported on the default display. 7536 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 7537 if (DEBUG_INPUT_METHOD) { 7538 Slog.i(TAG, "Desired input method target: " + imFocus); 7539 Slog.i(TAG, "Current focus: " + mCurrentFocus); 7540 Slog.i(TAG, "Last focus: " + mLastFocus); 7541 } 7542 if (imFocus != null) { 7543 // This may be a starting window, in which case we still want 7544 // to count it as okay. 7545 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7546 && imFocus.mAppToken != null) { 7547 // The client has definitely started, so it really should 7548 // have a window in this app token. Let's look for it. 7549 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7550 WindowState w = imFocus.mAppToken.windows.get(i); 7551 if (w != imFocus) { 7552 Log.i(TAG, "Switching to real app window: " + w); 7553 imFocus = w; 7554 break; 7555 } 7556 } 7557 } 7558 if (DEBUG_INPUT_METHOD) { 7559 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7560 if (imFocus.mSession.mClient != null) { 7561 Slog.i(TAG, "IM target client binder: " 7562 + imFocus.mSession.mClient.asBinder()); 7563 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 7564 } 7565 } 7566 if (imFocus.mSession.mClient != null && 7567 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7568 return true; 7569 } 7570 } 7571 } 7572 7573 // Okay, how about this... what is the current focus? 7574 // It seems in some cases we may not have moved the IM 7575 // target window, such as when it was in a pop-up window, 7576 // so let's also look at the current focus. (An example: 7577 // go to Gmail, start searching so the keyboard goes up, 7578 // press home. Sometimes the IME won't go down.) 7579 // Would be nice to fix this more correctly, but it's 7580 // way at the end of a release, and this should be good enough. 7581 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 7582 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7583 return true; 7584 } 7585 } 7586 return false; 7587 } 7588 7589 @Override 7590 public void getInitialDisplaySize(int displayId, Point size) { 7591 synchronized (mWindowMap) { 7592 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7593 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7594 synchronized(displayContent.mDisplaySizeLock) { 7595 size.x = displayContent.mInitialDisplayWidth; 7596 size.y = displayContent.mInitialDisplayHeight; 7597 } 7598 } 7599 } 7600 } 7601 7602 @Override 7603 public void getBaseDisplaySize(int displayId, Point size) { 7604 synchronized (mWindowMap) { 7605 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7606 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7607 synchronized(displayContent.mDisplaySizeLock) { 7608 size.x = displayContent.mBaseDisplayWidth; 7609 size.y = displayContent.mBaseDisplayHeight; 7610 } 7611 } 7612 } 7613 } 7614 7615 @Override 7616 public void setForcedDisplaySize(int displayId, int width, int height) { 7617 if (mContext.checkCallingOrSelfPermission( 7618 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7619 PackageManager.PERMISSION_GRANTED) { 7620 throw new SecurityException("Must hold permission " + 7621 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7622 } 7623 if (displayId != Display.DEFAULT_DISPLAY) { 7624 throw new IllegalArgumentException("Can only set the default display"); 7625 } 7626 synchronized(mWindowMap) { 7627 // Set some sort of reasonable bounds on the size of the display that we 7628 // will try to emulate. 7629 final int MIN_WIDTH = 200; 7630 final int MIN_HEIGHT = 200; 7631 final int MAX_SCALE = 2; 7632 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7633 if (displayContent != null) { 7634 width = Math.min(Math.max(width, MIN_WIDTH), 7635 displayContent.mInitialDisplayWidth * MAX_SCALE); 7636 height = Math.min(Math.max(height, MIN_HEIGHT), 7637 displayContent.mInitialDisplayHeight * MAX_SCALE); 7638 setForcedDisplaySizeLocked(displayContent, width, height); 7639 Settings.Global.putString(mContext.getContentResolver(), 7640 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 7641 } 7642 } 7643 } 7644 7645 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 7646 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 7647 Settings.Global.DISPLAY_SIZE_FORCED); 7648 if (sizeStr == null || sizeStr.length() == 0) { 7649 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 7650 } 7651 if (sizeStr != null && sizeStr.length() > 0) { 7652 final int pos = sizeStr.indexOf(','); 7653 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 7654 int width, height; 7655 try { 7656 width = Integer.parseInt(sizeStr.substring(0, pos)); 7657 height = Integer.parseInt(sizeStr.substring(pos+1)); 7658 synchronized(displayContent.mDisplaySizeLock) { 7659 if (displayContent.mBaseDisplayWidth != width 7660 || displayContent.mBaseDisplayHeight != height) { 7661 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 7662 displayContent.mBaseDisplayWidth = width; 7663 displayContent.mBaseDisplayHeight = height; 7664 } 7665 } 7666 } catch (NumberFormatException ex) { 7667 } 7668 } 7669 } 7670 String densityStr = Settings.Global.getString(mContext.getContentResolver(), 7671 Settings.Global.DISPLAY_DENSITY_FORCED); 7672 if (densityStr == null || densityStr.length() == 0) { 7673 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 7674 } 7675 if (densityStr != null && densityStr.length() > 0) { 7676 int density; 7677 try { 7678 density = Integer.parseInt(densityStr); 7679 synchronized(displayContent.mDisplaySizeLock) { 7680 if (displayContent.mBaseDisplayDensity != density) { 7681 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 7682 displayContent.mBaseDisplayDensity = density; 7683 } 7684 } 7685 } catch (NumberFormatException ex) { 7686 } 7687 } 7688 } 7689 7690 // displayContent must not be null 7691 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 7692 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7693 7694 synchronized(displayContent.mDisplaySizeLock) { 7695 displayContent.mBaseDisplayWidth = width; 7696 displayContent.mBaseDisplayHeight = height; 7697 } 7698 reconfigureDisplayLocked(displayContent); 7699 } 7700 7701 @Override 7702 public void clearForcedDisplaySize(int displayId) { 7703 if (mContext.checkCallingOrSelfPermission( 7704 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7705 PackageManager.PERMISSION_GRANTED) { 7706 throw new SecurityException("Must hold permission " + 7707 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7708 } 7709 if (displayId != Display.DEFAULT_DISPLAY) { 7710 throw new IllegalArgumentException("Can only set the default display"); 7711 } 7712 synchronized(mWindowMap) { 7713 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7714 if (displayContent != null) { 7715 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 7716 displayContent.mInitialDisplayHeight); 7717 Settings.Global.putString(mContext.getContentResolver(), 7718 Settings.Global.DISPLAY_SIZE_FORCED, ""); 7719 } 7720 } 7721 } 7722 7723 @Override 7724 public int getInitialDisplayDensity(int displayId) { 7725 synchronized (mWindowMap) { 7726 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7727 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7728 synchronized(displayContent.mDisplaySizeLock) { 7729 return displayContent.mInitialDisplayDensity; 7730 } 7731 } 7732 } 7733 return -1; 7734 } 7735 7736 @Override 7737 public int getBaseDisplayDensity(int displayId) { 7738 synchronized (mWindowMap) { 7739 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7740 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7741 synchronized(displayContent.mDisplaySizeLock) { 7742 return displayContent.mBaseDisplayDensity; 7743 } 7744 } 7745 } 7746 return -1; 7747 } 7748 7749 @Override 7750 public void setForcedDisplayDensity(int displayId, int density) { 7751 if (mContext.checkCallingOrSelfPermission( 7752 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7753 PackageManager.PERMISSION_GRANTED) { 7754 throw new SecurityException("Must hold permission " + 7755 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7756 } 7757 if (displayId != Display.DEFAULT_DISPLAY) { 7758 throw new IllegalArgumentException("Can only set the default display"); 7759 } 7760 synchronized(mWindowMap) { 7761 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7762 if (displayContent != null) { 7763 setForcedDisplayDensityLocked(displayContent, density); 7764 Settings.Global.putString(mContext.getContentResolver(), 7765 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 7766 } 7767 } 7768 } 7769 7770 // displayContent must not be null 7771 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 7772 Slog.i(TAG, "Using new display density: " + density); 7773 7774 synchronized(displayContent.mDisplaySizeLock) { 7775 displayContent.mBaseDisplayDensity = density; 7776 } 7777 reconfigureDisplayLocked(displayContent); 7778 } 7779 7780 @Override 7781 public void clearForcedDisplayDensity(int displayId) { 7782 if (mContext.checkCallingOrSelfPermission( 7783 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7784 PackageManager.PERMISSION_GRANTED) { 7785 throw new SecurityException("Must hold permission " + 7786 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7787 } 7788 if (displayId != Display.DEFAULT_DISPLAY) { 7789 throw new IllegalArgumentException("Can only set the default display"); 7790 } 7791 synchronized(mWindowMap) { 7792 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7793 if (displayContent != null) { 7794 setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity); 7795 Settings.Global.putString(mContext.getContentResolver(), 7796 Settings.Global.DISPLAY_DENSITY_FORCED, ""); 7797 } 7798 } 7799 } 7800 7801 // displayContent must not be null 7802 private void reconfigureDisplayLocked(DisplayContent displayContent) { 7803 // TODO: Multidisplay: for now only use with default display. 7804 configureDisplayPolicyLocked(displayContent); 7805 displayContent.layoutNeeded = true; 7806 7807 boolean configChanged = updateOrientationFromAppTokensLocked(false); 7808 mTempConfiguration.setToDefaults(); 7809 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 7810 if (computeScreenConfigurationLocked(mTempConfiguration)) { 7811 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 7812 configChanged = true; 7813 } 7814 } 7815 7816 if (configChanged) { 7817 mWaitingForConfig = true; 7818 startFreezingDisplayLocked(false, 0, 0); 7819 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 7820 } 7821 7822 performLayoutAndPlaceSurfacesLocked(); 7823 } 7824 7825 private void configureDisplayPolicyLocked(DisplayContent displayContent) { 7826 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 7827 displayContent.mBaseDisplayWidth, 7828 displayContent.mBaseDisplayHeight, 7829 displayContent.mBaseDisplayDensity); 7830 7831 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7832 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 7833 displayInfo.overscanLeft, displayInfo.overscanTop, 7834 displayInfo.overscanRight, displayInfo.overscanBottom); 7835 } 7836 7837 @Override 7838 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 7839 if (mContext.checkCallingOrSelfPermission( 7840 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7841 PackageManager.PERMISSION_GRANTED) { 7842 throw new SecurityException("Must hold permission " + 7843 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7844 } 7845 synchronized(mWindowMap) { 7846 DisplayContent displayContent = getDisplayContentLocked(displayId); 7847 if (displayContent != null) { 7848 setOverscanLocked(displayContent, left, top, right, bottom); 7849 } 7850 } 7851 } 7852 7853 private void setOverscanLocked(DisplayContent displayContent, 7854 int left, int top, int right, int bottom) { 7855 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7856 synchronized (displayContent.mDisplaySizeLock) { 7857 displayInfo.overscanLeft = left; 7858 displayInfo.overscanTop = top; 7859 displayInfo.overscanRight = right; 7860 displayInfo.overscanBottom = bottom; 7861 } 7862 7863 mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom); 7864 mDisplaySettings.writeSettingsLocked(); 7865 7866 reconfigureDisplayLocked(displayContent); 7867 } 7868 7869 // ------------------------------------------------------------- 7870 // Internals 7871 // ------------------------------------------------------------- 7872 7873 final WindowState windowForClientLocked(Session session, IWindow client, 7874 boolean throwOnError) { 7875 return windowForClientLocked(session, client.asBinder(), throwOnError); 7876 } 7877 7878 final WindowState windowForClientLocked(Session session, IBinder client, 7879 boolean throwOnError) { 7880 WindowState win = mWindowMap.get(client); 7881 if (localLOGV) Slog.v( 7882 TAG, "Looking up client " + client + ": " + win); 7883 if (win == null) { 7884 RuntimeException ex = new IllegalArgumentException( 7885 "Requested window " + client + " does not exist"); 7886 if (throwOnError) { 7887 throw ex; 7888 } 7889 Slog.w(TAG, "Failed looking up window", ex); 7890 return null; 7891 } 7892 if (session != null && win.mSession != session) { 7893 RuntimeException ex = new IllegalArgumentException( 7894 "Requested window " + client + " is in session " + 7895 win.mSession + ", not " + session); 7896 if (throwOnError) { 7897 throw ex; 7898 } 7899 Slog.w(TAG, "Failed looking up window", ex); 7900 return null; 7901 } 7902 7903 return win; 7904 } 7905 7906 final void rebuildAppWindowListLocked() { 7907 // TODO: Multidisplay, when ActivityStacks and tasks exist on more than one display. 7908 rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); 7909 } 7910 7911 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 7912 final WindowList windows = displayContent.getWindowList(); 7913 int NW = windows.size(); 7914 int i; 7915 int lastBelow = -1; 7916 int numRemoved = 0; 7917 7918 if (mRebuildTmp.length < NW) { 7919 mRebuildTmp = new WindowState[NW+10]; 7920 } 7921 7922 // First remove all existing app windows. 7923 i=0; 7924 while (i < NW) { 7925 WindowState w = windows.get(i); 7926 if (w.mAppToken != null) { 7927 WindowState win = windows.remove(i); 7928 win.mRebuilding = true; 7929 mRebuildTmp[numRemoved] = win; 7930 mWindowsChanged = true; 7931 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win); 7932 NW--; 7933 numRemoved++; 7934 continue; 7935 } else if (lastBelow == i-1) { 7936 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 7937 lastBelow = i; 7938 } 7939 } 7940 i++; 7941 } 7942 7943 // Keep whatever windows were below the app windows still below, 7944 // by skipping them. 7945 lastBelow++; 7946 i = lastBelow; 7947 7948 // First add all of the exiting app tokens... these are no longer 7949 // in the main app list, but still have windows shown. We put them 7950 // in the back because now that the animation is over we no longer 7951 // will care about them. 7952 AppTokenList exitingAppTokens = displayContent.mExitingAppTokens; 7953 int NT = exitingAppTokens.size(); 7954 for (int j=0; j<NT; j++) { 7955 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 7956 } 7957 7958 // And add in the still active app tokens in Z order. 7959 final ArrayList<Task> tasks = displayContent.getTasks(); 7960 final int numTasks = tasks.size(); 7961 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 7962 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 7963 final int numTokens = tokens.size(); 7964 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 7965 final AppWindowToken wtoken = tokens.get(tokenNdx); 7966 i = reAddAppWindowsLocked(displayContent, i, wtoken); 7967 } 7968 } 7969 7970 i -= lastBelow; 7971 if (i != numRemoved) { 7972 Slog.w(TAG, "Rebuild removed " + numRemoved + " windows but added " + i, 7973 new RuntimeException("here").fillInStackTrace()); 7974 for (i=0; i<numRemoved; i++) { 7975 WindowState ws = mRebuildTmp[i]; 7976 if (ws.mRebuilding) { 7977 StringWriter sw = new StringWriter(); 7978 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 7979 ws.dump(pw, "", true); 7980 pw.flush(); 7981 Slog.w(TAG, "This window was lost: " + ws); 7982 Slog.w(TAG, sw.toString()); 7983 ws.mWinAnimator.destroySurfaceLocked(); 7984 } 7985 } 7986 Slog.w(TAG, "Current app token list:"); 7987 dumpAppTokensLocked(); 7988 Slog.w(TAG, "Final window list:"); 7989 dumpWindowsLocked(); 7990 } 7991 } 7992 7993 private final void assignLayersLocked(WindowList windows) { 7994 int N = windows.size(); 7995 int curBaseLayer = 0; 7996 int curLayer = 0; 7997 int i; 7998 7999 if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows, 8000 new RuntimeException("here").fillInStackTrace()); 8001 8002 boolean anyLayerChanged = false; 8003 8004 for (i=0; i<N; i++) { 8005 final WindowState w = windows.get(i); 8006 final WindowStateAnimator winAnimator = w.mWinAnimator; 8007 boolean layerChanged = false; 8008 int oldLayer = w.mLayer; 8009 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 8010 || (i > 0 && w.mIsWallpaper)) { 8011 curLayer += WINDOW_LAYER_MULTIPLIER; 8012 w.mLayer = curLayer; 8013 } else { 8014 curBaseLayer = curLayer = w.mBaseLayer; 8015 w.mLayer = curLayer; 8016 } 8017 if (w.mLayer != oldLayer) { 8018 layerChanged = true; 8019 anyLayerChanged = true; 8020 } 8021 final AppWindowToken wtoken = w.mAppToken; 8022 oldLayer = winAnimator.mAnimLayer; 8023 if (w.mTargetAppToken != null) { 8024 winAnimator.mAnimLayer = 8025 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 8026 } else if (wtoken != null) { 8027 winAnimator.mAnimLayer = 8028 w.mLayer + wtoken.mAppAnimator.animLayerAdjustment; 8029 } else { 8030 winAnimator.mAnimLayer = w.mLayer; 8031 } 8032 if (w.mIsImWindow) { 8033 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 8034 } else if (w.mIsWallpaper) { 8035 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 8036 } 8037 if (winAnimator.mAnimLayer != oldLayer) { 8038 layerChanged = true; 8039 anyLayerChanged = true; 8040 } 8041 if (layerChanged && w.getStack().isDimming(winAnimator)) { 8042 // Force an animation pass just to update the mDimLayer layer. 8043 scheduleAnimationLocked(); 8044 } 8045 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 8046 + "mBase=" + w.mBaseLayer 8047 + " mLayer=" + w.mLayer 8048 + (wtoken == null ? 8049 "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment) 8050 + " =mAnimLayer=" + winAnimator.mAnimLayer); 8051 //System.out.println( 8052 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 8053 } 8054 8055 //TODO (multidisplay): Magnification is supported only for the default display. 8056 if (mDisplayMagnifier != null && anyLayerChanged 8057 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) { 8058 mDisplayMagnifier.onWindowLayersChangedLocked(); 8059 } 8060 } 8061 8062 private final void performLayoutAndPlaceSurfacesLocked() { 8063 int loopCount = 6; 8064 do { 8065 mTraversalScheduled = false; 8066 performLayoutAndPlaceSurfacesLockedLoop(); 8067 mH.removeMessages(H.DO_TRAVERSAL); 8068 loopCount--; 8069 } while (mTraversalScheduled && loopCount > 0); 8070 mInnerFields.mWallpaperActionPending = false; 8071 } 8072 8073 private boolean mInLayout = false; 8074 private final void performLayoutAndPlaceSurfacesLockedLoop() { 8075 if (mInLayout) { 8076 if (DEBUG) { 8077 throw new RuntimeException("Recursive call!"); 8078 } 8079 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 8080 + Debug.getCallers(3)); 8081 return; 8082 } 8083 8084 if (mWaitingForConfig) { 8085 // Our configuration has changed (most likely rotation), but we 8086 // don't yet have the complete configuration to report to 8087 // applications. Don't do any window layout until we have it. 8088 return; 8089 } 8090 8091 if (!mDisplayReady) { 8092 // Not yet initialized, nothing to do. 8093 return; 8094 } 8095 8096 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 8097 mInLayout = true; 8098 boolean recoveringMemory = false; 8099 8100 try { 8101 if (mForceRemoves != null) { 8102 recoveringMemory = true; 8103 // Wait a little bit for things to settle down, and off we go. 8104 for (int i=0; i<mForceRemoves.size(); i++) { 8105 WindowState ws = mForceRemoves.get(i); 8106 Slog.i(TAG, "Force removing: " + ws); 8107 removeWindowInnerLocked(ws.mSession, ws); 8108 } 8109 mForceRemoves = null; 8110 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 8111 Object tmp = new Object(); 8112 synchronized (tmp) { 8113 try { 8114 tmp.wait(250); 8115 } catch (InterruptedException e) { 8116 } 8117 } 8118 } 8119 } catch (RuntimeException e) { 8120 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 8121 } 8122 8123 try { 8124 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 8125 8126 mInLayout = false; 8127 8128 if (needsLayout()) { 8129 if (++mLayoutRepeatCount < 6) { 8130 requestTraversalLocked(); 8131 } else { 8132 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 8133 mLayoutRepeatCount = 0; 8134 } 8135 } else { 8136 mLayoutRepeatCount = 0; 8137 } 8138 8139 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 8140 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 8141 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE); 8142 } 8143 } catch (RuntimeException e) { 8144 mInLayout = false; 8145 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 8146 } 8147 8148 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 8149 } 8150 8151 private final void performLayoutLockedInner(final DisplayContent displayContent, 8152 boolean initial, boolean updateInputWindows) { 8153 if (!displayContent.layoutNeeded) { 8154 return; 8155 } 8156 displayContent.layoutNeeded = false; 8157 WindowList windows = displayContent.getWindowList(); 8158 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 8159 8160 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8161 final int dw = displayInfo.logicalWidth; 8162 final int dh = displayInfo.logicalHeight; 8163 8164 final int NFW = mFakeWindows.size(); 8165 for (int i=0; i<NFW; i++) { 8166 mFakeWindows.get(i).layout(dw, dh); 8167 } 8168 8169 final int N = windows.size(); 8170 int i; 8171 8172 if (DEBUG_LAYOUT) { 8173 Slog.v(TAG, "-------------------------------------"); 8174 Slog.v(TAG, "performLayout: needed=" 8175 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 8176 } 8177 8178 WindowStateAnimator universeBackground = null; 8179 8180 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); 8181 if (isDefaultDisplay) { 8182 // Not needed on non-default displays. 8183 mSystemDecorLayer = mPolicy.getSystemDecorLayerLw(); 8184 mScreenRect.set(0, 0, dw, dh); 8185 } 8186 8187 mPolicy.getContentRectLw(mTmpContentRect); 8188 displayContent.setStackBoxSize(mTmpContentRect); 8189 8190 int seq = mLayoutSeq+1; 8191 if (seq < 0) seq = 0; 8192 mLayoutSeq = seq; 8193 8194 boolean behindDream = false; 8195 8196 // First perform layout of any root windows (not attached 8197 // to another window). 8198 int topAttached = -1; 8199 for (i = N-1; i >= 0; i--) { 8200 final WindowState win = windows.get(i); 8201 8202 // Don't do layout of a window if it is not visible, or 8203 // soon won't be visible, to avoid wasting time and funky 8204 // changes while a window is animating away. 8205 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) 8206 || win.isGoneForLayoutLw(); 8207 8208 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 8209 Slog.v(TAG, "1ST PASS " + win 8210 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 8211 + " mLayoutAttached=" + win.mLayoutAttached 8212 + " screen changed=" + win.isConfigChanged()); 8213 final AppWindowToken atoken = win.mAppToken; 8214 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 8215 + win.mViewVisibility + " mRelayoutCalled=" 8216 + win.mRelayoutCalled + " hidden=" 8217 + win.mRootToken.hidden + " hiddenRequested=" 8218 + (atoken != null && atoken.hiddenRequested) 8219 + " mAttachedHidden=" + win.mAttachedHidden); 8220 else Slog.v(TAG, " VIS: mViewVisibility=" 8221 + win.mViewVisibility + " mRelayoutCalled=" 8222 + win.mRelayoutCalled + " hidden=" 8223 + win.mRootToken.hidden + " hiddenRequested=" 8224 + (atoken != null && atoken.hiddenRequested) 8225 + " mAttachedHidden=" + win.mAttachedHidden); 8226 } 8227 8228 // If this view is GONE, then skip it -- keep the current 8229 // frame, and let the caller know so they can ignore it 8230 // if they want. (We do the normal layout for INVISIBLE 8231 // windows, since that means "perform layout as normal, 8232 // just don't display"). 8233 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 8234 || (win.mAttrs.type == TYPE_KEYGUARD && win.isConfigChanged()) 8235 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8236 if (!win.mLayoutAttached) { 8237 if (initial) { 8238 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8239 win.mContentChanged = false; 8240 } 8241 if (win.mAttrs.type == TYPE_DREAM) { 8242 // Don't layout windows behind a dream, so that if it 8243 // does stuff like hide the status bar we won't get a 8244 // bad transition when it goes away. 8245 behindDream = true; 8246 } 8247 win.mLayoutNeeded = false; 8248 win.prelayout(); 8249 mPolicy.layoutWindowLw(win, win.mAttrs, null); 8250 win.mLayoutSeq = seq; 8251 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8252 + win.mFrame + " mContainingFrame=" 8253 + win.mContainingFrame + " mDisplayFrame=" 8254 + win.mDisplayFrame); 8255 } else { 8256 if (topAttached < 0) topAttached = i; 8257 } 8258 } 8259 if (win.mViewVisibility == View.VISIBLE 8260 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 8261 && universeBackground == null) { 8262 universeBackground = win.mWinAnimator; 8263 } 8264 } 8265 8266 if (mAnimator.mUniverseBackground != universeBackground) { 8267 mFocusMayChange = true; 8268 mAnimator.mUniverseBackground = universeBackground; 8269 } 8270 8271 boolean attachedBehindDream = false; 8272 8273 // Now perform layout of attached windows, which usually 8274 // depend on the position of the window they are attached to. 8275 // XXX does not deal with windows that are attached to windows 8276 // that are themselves attached. 8277 for (i = topAttached; i >= 0; i--) { 8278 final WindowState win = windows.get(i); 8279 8280 if (win.mLayoutAttached) { 8281 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 8282 + " mHaveFrame=" + win.mHaveFrame 8283 + " mViewVisibility=" + win.mViewVisibility 8284 + " mRelayoutCalled=" + win.mRelayoutCalled); 8285 // If this view is GONE, then skip it -- keep the current 8286 // frame, and let the caller know so they can ignore it 8287 // if they want. (We do the normal layout for INVISIBLE 8288 // windows, since that means "perform layout as normal, 8289 // just don't display"). 8290 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) { 8291 continue; 8292 } 8293 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8294 || !win.mHaveFrame || win.mLayoutNeeded) { 8295 if (initial) { 8296 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8297 win.mContentChanged = false; 8298 } 8299 win.mLayoutNeeded = false; 8300 win.prelayout(); 8301 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 8302 win.mLayoutSeq = seq; 8303 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8304 + win.mFrame + " mContainingFrame=" 8305 + win.mContainingFrame + " mDisplayFrame=" 8306 + win.mDisplayFrame); 8307 } 8308 } else if (win.mAttrs.type == TYPE_DREAM) { 8309 // Don't layout windows behind a dream, so that if it 8310 // does stuff like hide the status bar we won't get a 8311 // bad transition when it goes away. 8312 attachedBehindDream = behindDream; 8313 } 8314 } 8315 8316 // Window frames may have changed. Tell the input dispatcher about it. 8317 mInputMonitor.setUpdateInputWindowsNeededLw(); 8318 if (updateInputWindows) { 8319 mInputMonitor.updateInputWindowsLw(false /*force*/); 8320 } 8321 8322 mPolicy.finishLayoutLw(); 8323 } 8324 8325 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8326 // If the screen is currently frozen or off, then keep 8327 // it frozen/off until this window draws at its new 8328 // orientation. 8329 if (!okToDisplay()) { 8330 if (DEBUG_ORIENTATION) Slog.v(TAG, 8331 "Changing surface while display frozen: " + w); 8332 w.mOrientationChanging = true; 8333 w.mLastFreezeDuration = 0; 8334 mInnerFields.mOrientationChangeComplete = false; 8335 if (!mWindowsFreezingScreen) { 8336 mWindowsFreezingScreen = true; 8337 // XXX should probably keep timeout from 8338 // when we first froze the display. 8339 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8340 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 8341 WINDOW_FREEZE_TIMEOUT_DURATION); 8342 } 8343 } 8344 } 8345 8346 /** 8347 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8348 * @param windows List of windows on default display. 8349 * @return bitmap indicating if another pass through layout must be made. 8350 */ 8351 public int handleAppTransitionReadyLocked(WindowList windows) { 8352 int changes = 0; 8353 int i; 8354 int NN = mOpeningApps.size(); 8355 boolean goodToGo = true; 8356 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8357 "Checking " + NN + " opening apps (frozen=" 8358 + mDisplayFrozen + " timeout=" 8359 + mAppTransition.isTimeout() + ")..."); 8360 if (!mDisplayFrozen && !mAppTransition.isTimeout()) { 8361 // If the display isn't frozen, wait to do anything until 8362 // all of the apps are ready. Otherwise just go because 8363 // we'll unfreeze the display when everyone is ready. 8364 for (i=0; i<NN && goodToGo; i++) { 8365 AppWindowToken wtoken = mOpeningApps.get(i); 8366 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8367 "Check opening app=" + wtoken + ": allDrawn=" 8368 + wtoken.allDrawn + " startingDisplayed=" 8369 + wtoken.startingDisplayed + " startingMoved=" 8370 + wtoken.startingMoved); 8371 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8372 && !wtoken.startingMoved) { 8373 goodToGo = false; 8374 } 8375 } 8376 } 8377 if (goodToGo) { 8378 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8379 int transit = mAppTransition.getAppTransition(); 8380 if (mSkipAppTransitionAnimation) { 8381 transit = AppTransition.TRANSIT_UNSET; 8382 } 8383 mAppTransition.goodToGo(); 8384 mStartingIconInTransition = false; 8385 mSkipAppTransitionAnimation = false; 8386 8387 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8388 8389 rebuildAppWindowListLocked(); 8390 8391 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8392 WindowState oldWallpaper = 8393 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8394 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8395 ? null : mWallpaperTarget; 8396 8397 mInnerFields.mWallpaperMayChange = false; 8398 8399 // The top-most window will supply the layout params, 8400 // and we will determine it below. 8401 LayoutParams animLp = null; 8402 int bestAnimLayer = -1; 8403 boolean fullscreenAnim = false; 8404 8405 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8406 "New wallpaper target=" + mWallpaperTarget 8407 + ", oldWallpaper=" + oldWallpaper 8408 + ", lower target=" + mLowerWallpaperTarget 8409 + ", upper target=" + mUpperWallpaperTarget); 8410 8411 boolean openingAppHasWallpaper = false; 8412 boolean closingAppHasWallpaper = false; 8413 final AppWindowToken lowerWallpaperAppToken; 8414 final AppWindowToken upperWallpaperAppToken; 8415 if (mLowerWallpaperTarget == null) { 8416 lowerWallpaperAppToken = upperWallpaperAppToken = null; 8417 } else { 8418 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken; 8419 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken; 8420 } 8421 8422 // Do a first pass through the tokens for two 8423 // things: 8424 // (1) Determine if both the closing and opening 8425 // app token sets are wallpaper targets, in which 8426 // case special animations are needed 8427 // (since the wallpaper needs to stay static 8428 // behind them). 8429 // (2) Find the layout params of the top-most 8430 // application window in the tokens, which is 8431 // what will control the animation theme. 8432 final int NC = mClosingApps.size(); 8433 NN = NC + mOpeningApps.size(); 8434 for (i=0; i<NN; i++) { 8435 final AppWindowToken wtoken; 8436 if (i < NC) { 8437 wtoken = mClosingApps.get(i); 8438 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8439 closingAppHasWallpaper = true; 8440 } 8441 } else { 8442 wtoken = mOpeningApps.get(i - NC); 8443 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8444 openingAppHasWallpaper = true; 8445 } 8446 } 8447 8448 if (wtoken.appFullscreen) { 8449 WindowState ws = wtoken.findMainWindow(); 8450 if (ws != null) { 8451 animLp = ws.mAttrs; 8452 bestAnimLayer = ws.mLayer; 8453 fullscreenAnim = true; 8454 } 8455 } else if (!fullscreenAnim) { 8456 WindowState ws = wtoken.findMainWindow(); 8457 if (ws != null) { 8458 if (ws.mLayer > bestAnimLayer) { 8459 animLp = ws.mAttrs; 8460 bestAnimLayer = ws.mLayer; 8461 } 8462 } 8463 } 8464 } 8465 8466 if (closingAppHasWallpaper && openingAppHasWallpaper) { 8467 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!"); 8468 switch (transit) { 8469 case AppTransition.TRANSIT_ACTIVITY_OPEN: 8470 case AppTransition.TRANSIT_TASK_OPEN: 8471 case AppTransition.TRANSIT_TASK_TO_FRONT: 8472 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN; 8473 break; 8474 case AppTransition.TRANSIT_ACTIVITY_CLOSE: 8475 case AppTransition.TRANSIT_TASK_CLOSE: 8476 case AppTransition.TRANSIT_TASK_TO_BACK: 8477 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; 8478 break; 8479 } 8480 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); 8481 } else if ((oldWallpaper != null) && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 8482 // We are transitioning from an activity with 8483 // a wallpaper to one without. 8484 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; 8485 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8486 "New transit away from wallpaper: " + transit); 8487 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) { 8488 // We are transitioning from an activity without 8489 // a wallpaper to now showing the wallpaper 8490 transit = AppTransition.TRANSIT_WALLPAPER_OPEN; 8491 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8492 "New transit into wallpaper: " + transit); 8493 } 8494 8495 // If all closing windows are obscured, then there is 8496 // no need to do an animation. This is the case, for 8497 // example, when this transition is being done behind 8498 // the lock screen. 8499 if (!mPolicy.allowAppAnimationsLw()) { 8500 animLp = null; 8501 } 8502 8503 AppWindowToken topOpeningApp = null; 8504 int topOpeningLayer = 0; 8505 8506 NN = mOpeningApps.size(); 8507 for (i=0; i<NN; i++) { 8508 AppWindowToken wtoken = mOpeningApps.get(i); 8509 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 8510 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 8511 appAnimator.clearThumbnail(); 8512 wtoken.inPendingTransaction = false; 8513 appAnimator.animation = null; 8514 setTokenVisibilityLocked(wtoken, animLp, true, transit, false); 8515 wtoken.updateReportedVisibilityLocked(); 8516 wtoken.waitingToShow = false; 8517 8518 appAnimator.mAllAppWinAnimators.clear(); 8519 final int N = wtoken.allAppWindows.size(); 8520 for (int j = 0; j < N; j++) { 8521 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 8522 } 8523 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 8524 8525 if (animLp != null) { 8526 int layer = -1; 8527 for (int j=0; j<wtoken.windows.size(); j++) { 8528 WindowState win = wtoken.windows.get(j); 8529 if (win.mWinAnimator.mAnimLayer > layer) { 8530 layer = win.mWinAnimator.mAnimLayer; 8531 } 8532 } 8533 if (topOpeningApp == null || layer > topOpeningLayer) { 8534 topOpeningApp = wtoken; 8535 topOpeningLayer = layer; 8536 } 8537 } 8538 } 8539 NN = mClosingApps.size(); 8540 for (i=0; i<NN; i++) { 8541 AppWindowToken wtoken = mClosingApps.get(i); 8542 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8543 "Now closing app " + wtoken); 8544 wtoken.mAppAnimator.clearThumbnail(); 8545 wtoken.inPendingTransaction = false; 8546 wtoken.mAppAnimator.animation = null; 8547 setTokenVisibilityLocked(wtoken, animLp, false, 8548 transit, false); 8549 wtoken.updateReportedVisibilityLocked(); 8550 wtoken.waitingToHide = false; 8551 // Force the allDrawn flag, because we want to start 8552 // this guy's animations regardless of whether it's 8553 // gotten drawn. 8554 wtoken.allDrawn = true; 8555 wtoken.deferClearAllDrawn = false; 8556 } 8557 8558 AppWindowAnimator appAnimator = 8559 topOpeningApp == null ? null : topOpeningApp.mAppAnimator; 8560 Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail(); 8561 if (nextAppTransitionThumbnail != null && appAnimator != null 8562 && appAnimator.animation != null) { 8563 // This thumbnail animation is very special, we need to have 8564 // an extra surface with the thumbnail included with the animation. 8565 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(), 8566 nextAppTransitionThumbnail.getHeight()); 8567 try { 8568 // TODO(multi-display): support other displays 8569 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8570 final Display display = displayContent.getDisplay(); 8571 SurfaceControl surfaceControl = new SurfaceControl(mFxSession, 8572 "thumbnail anim", 8573 dirty.width(), dirty.height(), 8574 PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 8575 surfaceControl.setLayerStack(display.getLayerStack()); 8576 appAnimator.thumbnail = surfaceControl; 8577 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE"); 8578 Surface drawSurface = new Surface(); 8579 drawSurface.copyFrom(surfaceControl); 8580 Canvas c = drawSurface.lockCanvas(dirty); 8581 c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null); 8582 drawSurface.unlockCanvasAndPost(c); 8583 drawSurface.release(); 8584 appAnimator.thumbnailLayer = topOpeningLayer; 8585 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 8586 Animation anim = mAppTransition.createThumbnailAnimationLocked( 8587 transit, true, true, displayInfo.appWidth, displayInfo.appHeight); 8588 appAnimator.thumbnailAnimation = anim; 8589 anim.restrictDuration(MAX_ANIMATION_DURATION); 8590 anim.scaleCurrentDuration(mTransitionAnimationScale); 8591 Point p = new Point(); 8592 mAppTransition.getStartingPoint(p); 8593 appAnimator.thumbnailX = p.x; 8594 appAnimator.thumbnailY = p.y; 8595 } catch (OutOfResourcesException e) { 8596 Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width() 8597 + " h=" + dirty.height(), e); 8598 appAnimator.clearThumbnail(); 8599 } 8600 } 8601 8602 mAppTransition.postAnimationCallback(); 8603 mAppTransition.clear(); 8604 8605 mOpeningApps.clear(); 8606 mClosingApps.clear(); 8607 8608 // This has changed the visibility of windows, so perform 8609 // a new layout to get them all up-to-date. 8610 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT 8611 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 8612 getDefaultDisplayContentLocked().layoutNeeded = true; 8613 8614 // TODO(multidisplay): IMEs are only supported on the default display. 8615 if (windows == getDefaultWindowListLocked() 8616 && !moveInputMethodWindowsIfNeededLocked(true)) { 8617 assignLayersLocked(windows); 8618 } 8619 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/); 8620 mFocusMayChange = false; 8621 } 8622 8623 return changes; 8624 } 8625 8626 /** 8627 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8628 * @return bitmap indicating if another pass through layout must be made. 8629 */ 8630 private int handleAnimatingStoppedAndTransitionLocked() { 8631 int changes = 0; 8632 8633 mAppTransition.setIdle(); 8634 // Restore window app tokens to the ActivityManager views 8635 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8636 final ArrayList<Task> tasks = displayContent.getTasks(); 8637 final int numTasks = tasks.size(); 8638 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 8639 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8640 final int numTokens = tokens.size(); 8641 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 8642 final AppWindowToken wtoken = tokens.get(tokenNdx); 8643 wtoken.sendingToBottom = false; 8644 } 8645 } 8646 rebuildAppWindowListLocked(); 8647 8648 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8649 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 8650 "Wallpaper layer changed: assigning layers + relayout"); 8651 moveInputMethodWindowsIfNeededLocked(true); 8652 mInnerFields.mWallpaperMayChange = true; 8653 // Since the window list has been rebuilt, focus might 8654 // have to be recomputed since the actual order of windows 8655 // might have changed again. 8656 mFocusMayChange = true; 8657 8658 return changes; 8659 } 8660 8661 private void updateResizingWindows(final WindowState w) { 8662 final WindowStateAnimator winAnimator = w.mWinAnimator; 8663 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { 8664 w.mOverscanInsetsChanged |= 8665 !w.mLastOverscanInsets.equals(w.mOverscanInsets); 8666 w.mContentInsetsChanged |= 8667 !w.mLastContentInsets.equals(w.mContentInsets); 8668 w.mVisibleInsetsChanged |= 8669 !w.mLastVisibleInsets.equals(w.mVisibleInsets); 8670 boolean configChanged = w.isConfigChanged(); 8671 if (DEBUG_CONFIGURATION && configChanged) { 8672 Slog.v(TAG, "Win " + w + " config changed: " 8673 + mCurConfiguration); 8674 } 8675 if (localLOGV) Slog.v(TAG, "Resizing " + w 8676 + ": configChanged=" + configChanged 8677 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8678 w.mLastFrame.set(w.mFrame); 8679 if (w.mContentInsetsChanged 8680 || w.mVisibleInsetsChanged 8681 || winAnimator.mSurfaceResized 8682 || configChanged) { 8683 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8684 Slog.v(TAG, "Resize reasons for w=" + w + ": " 8685 + " contentInsetsChanged=" + w.mContentInsetsChanged 8686 + " " + w.mContentInsets.toShortString() 8687 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8688 + " " + w.mVisibleInsets.toShortString() 8689 + " surfaceResized=" + winAnimator.mSurfaceResized 8690 + " configChanged=" + configChanged); 8691 } 8692 8693 w.mLastOverscanInsets.set(w.mOverscanInsets); 8694 w.mLastContentInsets.set(w.mContentInsets); 8695 w.mLastVisibleInsets.set(w.mVisibleInsets); 8696 makeWindowFreezingScreenIfNeededLocked(w); 8697 // If the orientation is changing, then we need to 8698 // hold off on unfreezing the display until this 8699 // window has been redrawn; to do that, we need 8700 // to go through the process of getting informed 8701 // by the application when it has finished drawing. 8702 if (w.mOrientationChanging) { 8703 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 8704 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 8705 + w + ", surface " + winAnimator.mSurfaceControl); 8706 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 8707 if (w.mAppToken != null) { 8708 w.mAppToken.allDrawn = false; 8709 w.mAppToken.deferClearAllDrawn = false; 8710 } 8711 } 8712 if (!mResizingWindows.contains(w)) { 8713 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8714 "Resizing window " + w + " to " + winAnimator.mSurfaceW 8715 + "x" + winAnimator.mSurfaceH); 8716 mResizingWindows.add(w); 8717 } 8718 } else if (w.mOrientationChanging) { 8719 if (w.isDrawnLw()) { 8720 if (DEBUG_ORIENTATION) Slog.v(TAG, 8721 "Orientation not waiting for draw in " 8722 + w + ", surface " + winAnimator.mSurfaceControl); 8723 w.mOrientationChanging = false; 8724 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 8725 - mDisplayFreezeTime); 8726 } 8727 } 8728 } 8729 } 8730 8731 /** 8732 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8733 * 8734 * @param w WindowState this method is applied to. 8735 * @param currentTime The time which animations use for calculating transitions. 8736 * @param innerDw Width of app window. 8737 * @param innerDh Height of app window. 8738 */ 8739 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 8740 final int innerDw, final int innerDh) { 8741 final WindowManager.LayoutParams attrs = w.mAttrs; 8742 final int attrFlags = attrs.flags; 8743 final boolean canBeSeen = w.isDisplayedLw(); 8744 8745 if (w.mHasSurface) { 8746 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8747 mInnerFields.mHoldScreen = w.mSession; 8748 } 8749 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 8750 && mInnerFields.mScreenBrightness < 0) { 8751 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 8752 } 8753 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 8754 && mInnerFields.mButtonBrightness < 0) { 8755 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 8756 } 8757 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0 8758 && mInnerFields.mUserActivityTimeout < 0) { 8759 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout; 8760 } 8761 8762 final int type = attrs.type; 8763 if (canBeSeen 8764 && (type == TYPE_SYSTEM_DIALOG 8765 || type == TYPE_RECENTS_OVERLAY 8766 || type == TYPE_KEYGUARD 8767 || type == TYPE_SYSTEM_ERROR)) { 8768 mInnerFields.mSyswin = true; 8769 } 8770 8771 if (canBeSeen) { 8772 if (type == TYPE_DREAM || type == TYPE_KEYGUARD) { 8773 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_MIRROR; 8774 } else if (mInnerFields.mDisplayHasContent 8775 == LayoutFields.DISPLAY_CONTENT_UNKNOWN) { 8776 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNIQUE; 8777 } 8778 } 8779 } 8780 8781 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8782 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8783 // This window completely covers everything behind it, 8784 // so we want to leave all of them as undimmed (for 8785 // performance reasons). 8786 mInnerFields.mObscured = true; 8787 } 8788 } 8789 8790 private void handleFlagDimBehind(WindowState w, int innerDw, int innerDh) { 8791 final WindowManager.LayoutParams attrs = w.mAttrs; 8792 if ((attrs.flags & FLAG_DIM_BEHIND) != 0 8793 && w.isDisplayedLw() 8794 && !w.mExiting) { 8795 final WindowStateAnimator winAnimator = w.mWinAnimator; 8796 final TaskStack stack = w.getStack(); 8797 stack.setDimmingTag(); 8798 if (!stack.isDimming(winAnimator)) { 8799 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming."); 8800 stack.startDimmingIfNeeded(winAnimator); 8801 } 8802 } 8803 } 8804 8805 private void updateAllDrawnLocked(DisplayContent displayContent) { 8806 // See if any windows have been drawn, so they (and others 8807 // associated with them) can now be shown. 8808 final ArrayList<Task> tasks = displayContent.getTasks(); 8809 final int numTasks = tasks.size(); 8810 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 8811 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8812 final int numTokens = tokens.size(); 8813 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 8814 final AppWindowToken wtoken = tokens.get(tokenNdx); 8815 if (!wtoken.allDrawn) { 8816 int numInteresting = wtoken.numInterestingWindows; 8817 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 8818 if (DEBUG_VISIBILITY) Slog.v(TAG, 8819 "allDrawn: " + wtoken 8820 + " interesting=" + numInteresting 8821 + " drawn=" + wtoken.numDrawnWindows); 8822 wtoken.allDrawn = true; 8823 mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget(); 8824 } 8825 } 8826 } 8827 } 8828 } 8829 8830 // "Something has changed! Let's make it correct now." 8831 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 8832 if (DEBUG_WINDOW_TRACE) { 8833 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 8834 + Debug.getCallers(3)); 8835 } 8836 8837 final long currentTime = SystemClock.uptimeMillis(); 8838 8839 int i; 8840 8841 if (mFocusMayChange) { 8842 mFocusMayChange = false; 8843 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 8844 false /*updateInputWindows*/); 8845 } 8846 8847 // Initialize state of exiting tokens. 8848 final int numDisplays = mDisplayContents.size(); 8849 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 8850 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 8851 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) { 8852 displayContent.mExitingTokens.get(i).hasVisible = false; 8853 } 8854 8855 // Initialize state of exiting applications. 8856 for (i=displayContent.mExitingAppTokens.size()-1; i>=0; i--) { 8857 displayContent.mExitingAppTokens.get(i).hasVisible = false; 8858 } 8859 } 8860 8861 mInnerFields.mHoldScreen = null; 8862 mInnerFields.mScreenBrightness = -1; 8863 mInnerFields.mButtonBrightness = -1; 8864 mInnerFields.mUserActivityTimeout = -1; 8865 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN; 8866 8867 mTransactionSequence++; 8868 8869 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked(); 8870 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 8871 final int defaultDw = defaultInfo.logicalWidth; 8872 final int defaultDh = defaultInfo.logicalHeight; 8873 8874 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 8875 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 8876 SurfaceControl.openTransaction(); 8877 try { 8878 8879 if (mWatermark != null) { 8880 mWatermark.positionSurface(defaultDw, defaultDh); 8881 } 8882 if (mStrictModeFlash != null) { 8883 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 8884 } 8885 8886 boolean focusDisplayed = false; 8887 8888 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 8889 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 8890 boolean updateAllDrawn = false; 8891 WindowList windows = displayContent.getWindowList(); 8892 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8893 final int displayId = displayContent.getDisplayId(); 8894 final int dw = displayInfo.logicalWidth; 8895 final int dh = displayInfo.logicalHeight; 8896 final int innerDw = displayInfo.appWidth; 8897 final int innerDh = displayInfo.appHeight; 8898 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 8899 8900 // Reset for each display unless we are forcing mirroring. 8901 if (mInnerFields.mDisplayHasContent != LayoutFields.DISPLAY_CONTENT_MIRROR) { 8902 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN; 8903 } 8904 8905 int repeats = 0; 8906 do { 8907 repeats++; 8908 if (repeats > 6) { 8909 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 8910 displayContent.layoutNeeded = false; 8911 break; 8912 } 8913 8914 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 8915 displayContent.pendingLayoutChanges); 8916 8917 if ((displayContent.pendingLayoutChanges & 8918 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 && 8919 (adjustWallpaperWindowsLocked() & 8920 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 8921 assignLayersLocked(windows); 8922 displayContent.layoutNeeded = true; 8923 } 8924 8925 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 8926 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 8927 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 8928 if (updateOrientationFromAppTokensLocked(true)) { 8929 displayContent.layoutNeeded = true; 8930 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8931 } 8932 } 8933 8934 if ((displayContent.pendingLayoutChanges 8935 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 8936 displayContent.layoutNeeded = true; 8937 } 8938 8939 // FIRST LOOP: Perform a layout, if needed. 8940 if (repeats < 4) { 8941 performLayoutLockedInner(displayContent, repeats == 1, 8942 false /*updateInputWindows*/); 8943 } else { 8944 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 8945 } 8946 8947 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 8948 // it is animating. 8949 displayContent.pendingLayoutChanges = 0; 8950 8951 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 8952 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 8953 8954 if (isDefaultDisplay) { 8955 mPolicy.beginPostLayoutPolicyLw(dw, dh); 8956 for (i = windows.size() - 1; i >= 0; i--) { 8957 WindowState w = windows.get(i); 8958 if (w.mHasSurface) { 8959 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); 8960 } 8961 } 8962 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 8963 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 8964 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges); 8965 } 8966 } while (displayContent.pendingLayoutChanges != 0); 8967 8968 mInnerFields.mObscured = false; 8969 mInnerFields.mSyswin = false; 8970 displayContent.resetDimming(); 8971 8972 // Only used if default window 8973 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 8974 8975 final int N = windows.size(); 8976 for (i=N-1; i>=0; i--) { 8977 WindowState w = windows.get(i); 8978 8979 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 8980 8981 // Update effect. 8982 w.mObscured = mInnerFields.mObscured; 8983 if (!mInnerFields.mObscured) { 8984 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 8985 } 8986 8987 if (!w.getStack().testDimmingTag()) { 8988 handleFlagDimBehind(w, innerDw, innerDh); 8989 } 8990 8991 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 8992 && w.isVisibleLw()) { 8993 // This is the wallpaper target and its obscured state 8994 // changed... make sure the current wallaper's visibility 8995 // has been updated accordingly. 8996 updateWallpaperVisibilityLocked(); 8997 } 8998 8999 final WindowStateAnimator winAnimator = w.mWinAnimator; 9000 9001 // If the window has moved due to its containing 9002 // content frame changing, then we'd like to animate 9003 // it. 9004 if (w.mHasSurface && w.shouldAnimateMove()) { 9005 // Frame has moved, containing content frame 9006 // has also moved, and we're not currently animating... 9007 // let's do something. 9008 Animation a = AnimationUtils.loadAnimation(mContext, 9009 com.android.internal.R.anim.window_move_from_decor); 9010 winAnimator.setAnimation(a); 9011 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 9012 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 9013 try { 9014 w.mClient.moved(w.mFrame.left, w.mFrame.top); 9015 } catch (RemoteException e) { 9016 } 9017 } 9018 9019 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 9020 w.mContentChanged = false; 9021 9022 // Moved from updateWindowsAndWallpaperLocked(). 9023 if (w.mHasSurface) { 9024 // Take care of the window being ready to display. 9025 final boolean committed = 9026 winAnimator.commitFinishDrawingLocked(currentTime); 9027 if (isDefaultDisplay && committed) { 9028 if (w.mAttrs.type == TYPE_DREAM) { 9029 // HACK: When a dream is shown, it may at that 9030 // point hide the lock screen. So we need to 9031 // redo the layout to let the phone window manager 9032 // make this happen. 9033 displayContent.pendingLayoutChanges |= 9034 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9035 if (DEBUG_LAYOUT_REPEATS) { 9036 debugLayoutRepeats( 9037 "dream and commitFinishDrawingLocked true", 9038 displayContent.pendingLayoutChanges); 9039 } 9040 } 9041 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 9042 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 9043 "First draw done in potential wallpaper target " + w); 9044 mInnerFields.mWallpaperMayChange = true; 9045 displayContent.pendingLayoutChanges |= 9046 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9047 if (DEBUG_LAYOUT_REPEATS) { 9048 debugLayoutRepeats( 9049 "wallpaper and commitFinishDrawingLocked true", 9050 displayContent.pendingLayoutChanges); 9051 } 9052 } 9053 } 9054 9055 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 9056 9057 final AppWindowToken atoken = w.mAppToken; 9058 if (DEBUG_STARTING_WINDOW && atoken != null 9059 && w == atoken.startingWindow) { 9060 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 9061 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 9062 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 9063 } 9064 if (atoken != null 9065 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 9066 if (atoken.lastTransactionSequence != mTransactionSequence) { 9067 atoken.lastTransactionSequence = mTransactionSequence; 9068 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 9069 atoken.startingDisplayed = false; 9070 } 9071 if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 9072 && !w.mExiting && !w.mDestroying) { 9073 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 9074 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 9075 + ", isAnimating=" + winAnimator.isAnimating()); 9076 if (!w.isDrawnLw()) { 9077 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl 9078 + " pv=" + w.mPolicyVisibility 9079 + " mDrawState=" + winAnimator.mDrawState 9080 + " ah=" + w.mAttachedHidden 9081 + " th=" + atoken.hiddenRequested 9082 + " a=" + winAnimator.mAnimating); 9083 } 9084 } 9085 if (w != atoken.startingWindow) { 9086 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 9087 atoken.numInterestingWindows++; 9088 if (w.isDrawnLw()) { 9089 atoken.numDrawnWindows++; 9090 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 9091 "tokenMayBeDrawn: " + atoken 9092 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 9093 + " mAppFreezing=" + w.mAppFreezing); 9094 updateAllDrawn = true; 9095 } 9096 } 9097 } else if (w.isDrawnLw()) { 9098 atoken.startingDisplayed = true; 9099 } 9100 } 9101 } 9102 } 9103 9104 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 9105 && w.isDisplayedLw()) { 9106 focusDisplayed = true; 9107 } 9108 9109 updateResizingWindows(w); 9110 } 9111 9112 final boolean hasUniqueContent; 9113 switch (mInnerFields.mDisplayHasContent) { 9114 case LayoutFields.DISPLAY_CONTENT_MIRROR: 9115 hasUniqueContent = isDefaultDisplay; 9116 break; 9117 case LayoutFields.DISPLAY_CONTENT_UNIQUE: 9118 hasUniqueContent = true; 9119 break; 9120 case LayoutFields.DISPLAY_CONTENT_UNKNOWN: 9121 default: 9122 hasUniqueContent = false; 9123 break; 9124 } 9125 mDisplayManagerService.setDisplayHasContent(displayId, hasUniqueContent, 9126 true /* inTraversal, must call performTraversalInTrans... below */); 9127 9128 getDisplayContentLocked(displayId).stopDimmingIfNeeded(); 9129 9130 if (updateAllDrawn) { 9131 updateAllDrawnLocked(displayContent); 9132 } 9133 } 9134 9135 if (focusDisplayed) { 9136 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 9137 } 9138 9139 // Give the display manager a chance to adjust properties 9140 // like display rotation if it needs to. 9141 mDisplayManagerService.performTraversalInTransactionFromWindowManager(); 9142 9143 } catch (RuntimeException e) { 9144 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 9145 } finally { 9146 SurfaceControl.closeTransaction(); 9147 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9148 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 9149 } 9150 9151 final WindowList defaultWindows = defaultDisplay.getWindowList(); 9152 9153 // If we are ready to perform an app transition, check through 9154 // all of the app tokens to be shown and see if they are ready 9155 // to go. 9156 if (mAppTransition.isReady()) { 9157 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 9158 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 9159 defaultDisplay.pendingLayoutChanges); 9160 } 9161 9162 if (!mAnimator.mAnimating && mAppTransition.isRunning()) { 9163 // We have finished the animation of an app transition. To do 9164 // this, we have delayed a lot of operations like showing and 9165 // hiding apps, moving apps in Z-order, etc. The app token list 9166 // reflects the correct Z-order, but the window list may now 9167 // be out of sync with it. So here we will just rebuild the 9168 // entire app window list. Fun! 9169 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 9170 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 9171 defaultDisplay.pendingLayoutChanges); 9172 } 9173 9174 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 9175 && !mAppTransition.isReady()) { 9176 // At this point, there was a window with a wallpaper that 9177 // was force hiding other windows behind it, but now it 9178 // is going away. This may be simple -- just animate 9179 // away the wallpaper and its window -- or it may be 9180 // hard -- the wallpaper now needs to be shown behind 9181 // something that was hidden. 9182 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9183 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 9184 defaultDisplay.pendingLayoutChanges); 9185 } 9186 mInnerFields.mWallpaperForceHidingChanged = false; 9187 9188 if (mInnerFields.mWallpaperMayChange) { 9189 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting"); 9190 defaultDisplay.pendingLayoutChanges |= 9191 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9192 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange", 9193 defaultDisplay.pendingLayoutChanges); 9194 } 9195 9196 if (mFocusMayChange) { 9197 mFocusMayChange = false; 9198 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 9199 false /*updateInputWindows*/)) { 9200 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 9201 } 9202 } 9203 9204 if (needsLayout()) { 9205 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9206 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 9207 defaultDisplay.pendingLayoutChanges); 9208 } 9209 9210 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 9211 WindowState win = mResizingWindows.get(i); 9212 if (win.mAppFreezing) { 9213 // Don't remove this window until rotation has completed. 9214 continue; 9215 } 9216 final WindowStateAnimator winAnimator = win.mWinAnimator; 9217 try { 9218 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 9219 "Reporting new frame to " + win + ": " + win.mCompatFrame); 9220 int diff = 0; 9221 boolean configChanged = win.isConfigChanged(); 9222 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) 9223 && configChanged) { 9224 Slog.i(TAG, "Sending new config to window " + win + ": " 9225 + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH 9226 + " / " + mCurConfiguration + " / 0x" 9227 + Integer.toHexString(diff)); 9228 } 9229 win.setConfiguration(mCurConfiguration); 9230 if (DEBUG_ORIENTATION && 9231 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i( 9232 TAG, "Resizing " + win + " WITH DRAW PENDING"); 9233 final IWindow client = win.mClient; 9234 final Rect frame = win.mFrame; 9235 final Rect overscanInsets = win.mLastOverscanInsets; 9236 final Rect contentInsets = win.mLastContentInsets; 9237 final Rect visibleInsets = win.mLastVisibleInsets; 9238 final boolean reportDraw 9239 = winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING; 9240 final Configuration newConfig = configChanged ? win.mConfiguration : null; 9241 if (win.mClient instanceof IWindow.Stub) { 9242 // To prevent deadlock simulate one-way call if win.mClient is a local object. 9243 mH.post(new Runnable() { 9244 @Override 9245 public void run() { 9246 try { 9247 client.resized(frame, overscanInsets, contentInsets, 9248 visibleInsets, reportDraw, newConfig); 9249 } catch (RemoteException e) { 9250 // Not a remote call, RemoteException won't be raised. 9251 } 9252 } 9253 }); 9254 } else { 9255 client.resized(frame, overscanInsets, contentInsets, visibleInsets, reportDraw, 9256 newConfig); 9257 } 9258 win.mOverscanInsetsChanged = false; 9259 win.mContentInsetsChanged = false; 9260 win.mVisibleInsetsChanged = false; 9261 winAnimator.mSurfaceResized = false; 9262 } catch (RemoteException e) { 9263 win.mOrientationChanging = false; 9264 win.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 9265 - mDisplayFreezeTime); 9266 } 9267 mResizingWindows.remove(i); 9268 } 9269 9270 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 9271 "With display frozen, orientationChangeComplete=" 9272 + mInnerFields.mOrientationChangeComplete); 9273 if (mInnerFields.mOrientationChangeComplete) { 9274 if (mWindowsFreezingScreen) { 9275 mWindowsFreezingScreen = false; 9276 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource; 9277 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9278 } 9279 stopFreezingDisplayLocked(); 9280 } 9281 9282 // Destroy the surface of any windows that are no longer visible. 9283 boolean wallpaperDestroyed = false; 9284 i = mDestroySurface.size(); 9285 if (i > 0) { 9286 do { 9287 i--; 9288 WindowState win = mDestroySurface.get(i); 9289 win.mDestroying = false; 9290 if (mInputMethodWindow == win) { 9291 mInputMethodWindow = null; 9292 } 9293 if (win == mWallpaperTarget) { 9294 wallpaperDestroyed = true; 9295 } 9296 win.mWinAnimator.destroySurfaceLocked(); 9297 } while (i > 0); 9298 mDestroySurface.clear(); 9299 } 9300 9301 // Time to remove any exiting tokens? 9302 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9303 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9304 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens; 9305 for (i = exitingTokens.size() - 1; i >= 0; i--) { 9306 WindowToken token = exitingTokens.get(i); 9307 if (!token.hasVisible) { 9308 exitingTokens.remove(i); 9309 if (token.windowType == TYPE_WALLPAPER) { 9310 mWallpaperTokens.remove(token); 9311 } 9312 } 9313 } 9314 9315 // Time to remove any exiting applications? 9316 AppTokenList exitingAppTokens = displayContent.mExitingAppTokens; 9317 for (i = exitingAppTokens.size() - 1; i >= 0; i--) { 9318 AppWindowToken token = exitingAppTokens.get(i); 9319 if (!token.hasVisible && !mClosingApps.contains(token)) { 9320 // Make sure there is no animation running on this token, 9321 // so any windows associated with it will be removed as 9322 // soon as their animations are complete 9323 token.mAppAnimator.clearAnimation(); 9324 token.mAppAnimator.animating = false; 9325 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 9326 "performLayout: App token exiting now removed" + token); 9327 final Task task = mTaskIdToTask.get(token.groupId); 9328 if (task != null && task.removeAppToken(token)) { 9329 mTaskIdToTask.delete(token.groupId); 9330 } 9331 exitingAppTokens.remove(i); 9332 } 9333 } 9334 } 9335 9336 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 9337 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 9338 try { 9339 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 9340 } catch (RemoteException e) { 9341 } 9342 } 9343 mRelayoutWhileAnimating.clear(); 9344 } 9345 9346 if (wallpaperDestroyed) { 9347 defaultDisplay.pendingLayoutChanges |= 9348 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9349 defaultDisplay.layoutNeeded = true; 9350 } 9351 9352 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9353 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9354 if (displayContent.pendingLayoutChanges != 0) { 9355 displayContent.layoutNeeded = true; 9356 } 9357 } 9358 9359 // Finally update all input windows now that the window changes have stabilized. 9360 mInputMonitor.updateInputWindowsLw(true /*force*/); 9361 9362 setHoldScreenLocked(mInnerFields.mHoldScreen); 9363 if (!mDisplayFrozen) { 9364 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 9365 mPowerManager.setScreenBrightnessOverrideFromWindowManager(-1); 9366 } else { 9367 mPowerManager.setScreenBrightnessOverrideFromWindowManager( 9368 toBrightnessOverride(mInnerFields.mScreenBrightness)); 9369 } 9370 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 9371 mPowerManager.setButtonBrightnessOverrideFromWindowManager(-1); 9372 } else { 9373 mPowerManager.setButtonBrightnessOverrideFromWindowManager( 9374 toBrightnessOverride(mInnerFields.mButtonBrightness)); 9375 } 9376 mPowerManager.setUserActivityTimeoutOverrideFromWindowManager( 9377 mInnerFields.mUserActivityTimeout); 9378 } 9379 9380 if (mTurnOnScreen) { 9381 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 9382 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 9383 mTurnOnScreen = false; 9384 } 9385 9386 if (mInnerFields.mUpdateRotation) { 9387 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9388 if (updateRotationUncheckedLocked(false)) { 9389 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9390 } else { 9391 mInnerFields.mUpdateRotation = false; 9392 } 9393 } 9394 9395 if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded 9396 && !mInnerFields.mUpdateRotation) { 9397 checkDrawnWindowsLocked(); 9398 } 9399 9400 final int N = mPendingRemove.size(); 9401 if (N > 0) { 9402 if (mPendingRemoveTmp.length < N) { 9403 mPendingRemoveTmp = new WindowState[N+10]; 9404 } 9405 mPendingRemove.toArray(mPendingRemoveTmp); 9406 mPendingRemove.clear(); 9407 DisplayContentList displayList = new DisplayContentList(); 9408 for (i = 0; i < N; i++) { 9409 WindowState w = mPendingRemoveTmp[i]; 9410 removeWindowInnerLocked(w.mSession, w); 9411 if (!displayList.contains(w.mDisplayContent)) { 9412 displayList.add(w.mDisplayContent); 9413 } 9414 } 9415 9416 for (DisplayContent displayContent : displayList) { 9417 assignLayersLocked(displayContent.getWindowList()); 9418 displayContent.layoutNeeded = true; 9419 } 9420 } 9421 9422 setFocusedStackFrame(); 9423 9424 // Check to see if we are now in a state where the screen should 9425 // be enabled, because the window obscured flags have changed. 9426 enableScreenIfNeededLocked(); 9427 9428 scheduleAnimationLocked(); 9429 9430 if (DEBUG_WINDOW_TRACE) { 9431 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" 9432 + mAnimator.mAnimating); 9433 } 9434 } 9435 9436 private int toBrightnessOverride(float value) { 9437 return (int)(value * PowerManager.BRIGHTNESS_ON); 9438 } 9439 9440 void checkDrawnWindowsLocked() { 9441 if (mWaitingForDrawn.size() > 0) { 9442 for (int j=mWaitingForDrawn.size()-1; j>=0; j--) { 9443 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j); 9444 WindowState win = pair.first; 9445 //Slog.i(TAG, "Waiting for drawn " + win + ": removed=" 9446 // + win.mRemoved + " visible=" + win.isVisibleLw() 9447 // + " shown=" + win.mSurfaceShown); 9448 if (win.mRemoved || !win.isVisibleLw()) { 9449 // Window has been removed or made invisible; no draw 9450 // will now happen, so stop waiting. 9451 Slog.w(TAG, "Aborted waiting for drawn: " + pair.first); 9452 try { 9453 pair.second.sendResult(null); 9454 } catch (RemoteException e) { 9455 } 9456 mWaitingForDrawn.remove(pair); 9457 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9458 } else if (win.mWinAnimator.mSurfaceShown) { 9459 // Window is now drawn (and shown). 9460 try { 9461 pair.second.sendResult(null); 9462 } catch (RemoteException e) { 9463 } 9464 mWaitingForDrawn.remove(pair); 9465 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9466 } 9467 } 9468 } 9469 } 9470 9471 @Override 9472 public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) { 9473 if (token != null && callback != null) { 9474 synchronized (mWindowMap) { 9475 WindowState win = windowForClientLocked(null, token, true); 9476 if (win != null) { 9477 Pair<WindowState, IRemoteCallback> pair = 9478 new Pair<WindowState, IRemoteCallback>(win, callback); 9479 Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9480 mH.sendMessageDelayed(m, 2000); 9481 mWaitingForDrawn.add(pair); 9482 checkDrawnWindowsLocked(); 9483 return true; 9484 } 9485 } 9486 } 9487 return false; 9488 } 9489 9490 void setHoldScreenLocked(final Session newHoldScreen) { 9491 final boolean hold = newHoldScreen != null; 9492 9493 if (hold && mHoldingScreenOn != newHoldScreen) { 9494 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 9495 } 9496 mHoldingScreenOn = newHoldScreen; 9497 9498 final boolean state = mHoldingScreenWakeLock.isHeld(); 9499 if (hold != state) { 9500 if (hold) { 9501 mHoldingScreenWakeLock.acquire(); 9502 mPolicy.keepScreenOnStartedLw(); 9503 } else { 9504 mPolicy.keepScreenOnStoppedLw(); 9505 mHoldingScreenWakeLock.release(); 9506 } 9507 } 9508 } 9509 9510 @Override 9511 public void requestTraversal() { 9512 synchronized (mWindowMap) { 9513 requestTraversalLocked(); 9514 } 9515 } 9516 9517 void requestTraversalLocked() { 9518 if (!mTraversalScheduled) { 9519 mTraversalScheduled = true; 9520 mH.sendEmptyMessage(H.DO_TRAVERSAL); 9521 } 9522 } 9523 9524 /** Note that Locked in this case is on mLayoutToAnim */ 9525 void scheduleAnimationLocked() { 9526 if (!mAnimationScheduled) { 9527 mAnimationScheduled = true; 9528 mChoreographer.postCallback( 9529 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 9530 } 9531 } 9532 9533 private boolean needsLayout() { 9534 final int numDisplays = mDisplayContents.size(); 9535 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9536 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9537 if (displayContent.layoutNeeded) { 9538 return true; 9539 } 9540 } 9541 return false; 9542 } 9543 9544 boolean copyAnimToLayoutParamsLocked() { 9545 boolean doRequest = false; 9546 9547 final int bulkUpdateParams = mAnimator.mBulkUpdateParams; 9548 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 9549 mInnerFields.mUpdateRotation = true; 9550 doRequest = true; 9551 } 9552 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 9553 mInnerFields.mWallpaperMayChange = true; 9554 doRequest = true; 9555 } 9556 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 9557 mInnerFields.mWallpaperForceHidingChanged = true; 9558 doRequest = true; 9559 } 9560 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 9561 mInnerFields.mOrientationChangeComplete = false; 9562 } else { 9563 mInnerFields.mOrientationChangeComplete = true; 9564 mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource; 9565 if (mWindowsFreezingScreen) { 9566 doRequest = true; 9567 } 9568 } 9569 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 9570 mTurnOnScreen = true; 9571 } 9572 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) { 9573 mInnerFields.mWallpaperActionPending = true; 9574 } 9575 9576 return doRequest; 9577 } 9578 9579 /** If a window that has an animation specifying a colored background and the current wallpaper 9580 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 9581 * suddenly disappear. */ 9582 int adjustAnimationBackground(WindowStateAnimator winAnimator) { 9583 WindowList windows = winAnimator.mWin.getWindowList(); 9584 for (int i = windows.size() - 1; i >= 0; --i) { 9585 WindowState testWin = windows.get(i); 9586 if (testWin.mIsWallpaper && testWin.isVisibleNow()) { 9587 return testWin.mWinAnimator.mAnimLayer; 9588 } 9589 } 9590 return winAnimator.mAnimLayer; 9591 } 9592 9593 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9594 boolean secure) { 9595 final SurfaceControl surface = winAnimator.mSurfaceControl; 9596 boolean leakedSurface = false; 9597 boolean killedApps = false; 9598 9599 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9600 winAnimator.mSession.mPid, operation); 9601 9602 if (mForceRemoves == null) { 9603 mForceRemoves = new ArrayList<WindowState>(); 9604 } 9605 9606 long callingIdentity = Binder.clearCallingIdentity(); 9607 try { 9608 // There was some problem... first, do a sanity check of the 9609 // window list to make sure we haven't left any dangling surfaces 9610 // around. 9611 9612 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 9613 final int numDisplays = mDisplayContents.size(); 9614 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9615 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9616 final int numWindows = windows.size(); 9617 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9618 final WindowState ws = windows.get(winNdx); 9619 WindowStateAnimator wsa = ws.mWinAnimator; 9620 if (wsa.mSurfaceControl != null) { 9621 if (!mSessions.contains(wsa.mSession)) { 9622 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 9623 + ws + " surface=" + wsa.mSurfaceControl 9624 + " token=" + ws.mToken 9625 + " pid=" + ws.mSession.mPid 9626 + " uid=" + ws.mSession.mUid); 9627 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9628 wsa.mSurfaceControl.destroy(); 9629 wsa.mSurfaceShown = false; 9630 wsa.mSurfaceControl = null; 9631 ws.mHasSurface = false; 9632 mForceRemoves.add(ws); 9633 leakedSurface = true; 9634 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9635 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 9636 + ws + " surface=" + wsa.mSurfaceControl 9637 + " token=" + ws.mAppToken); 9638 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9639 wsa.mSurfaceControl.destroy(); 9640 wsa.mSurfaceShown = false; 9641 wsa.mSurfaceControl = null; 9642 ws.mHasSurface = false; 9643 leakedSurface = true; 9644 } 9645 } 9646 } 9647 } 9648 9649 if (!leakedSurface) { 9650 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 9651 SparseIntArray pidCandidates = new SparseIntArray(); 9652 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9653 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9654 final int numWindows = windows.size(); 9655 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9656 final WindowState ws = windows.get(winNdx); 9657 if (mForceRemoves.contains(ws)) { 9658 continue; 9659 } 9660 WindowStateAnimator wsa = ws.mWinAnimator; 9661 if (wsa.mSurfaceControl != null) { 9662 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9663 } 9664 } 9665 if (pidCandidates.size() > 0) { 9666 int[] pids = new int[pidCandidates.size()]; 9667 for (int i=0; i<pids.length; i++) { 9668 pids[i] = pidCandidates.keyAt(i); 9669 } 9670 try { 9671 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9672 killedApps = true; 9673 } 9674 } catch (RemoteException e) { 9675 } 9676 } 9677 } 9678 } 9679 9680 if (leakedSurface || killedApps) { 9681 // We managed to reclaim some memory, so get rid of the trouble 9682 // surface and ask the app to request another one. 9683 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 9684 if (surface != null) { 9685 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9686 "RECOVER DESTROY", null); 9687 surface.destroy(); 9688 winAnimator.mSurfaceShown = false; 9689 winAnimator.mSurfaceControl = null; 9690 winAnimator.mWin.mHasSurface = false; 9691 scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken); 9692 } 9693 9694 try { 9695 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9696 } catch (RemoteException e) { 9697 } 9698 } 9699 } finally { 9700 Binder.restoreCallingIdentity(callingIdentity); 9701 } 9702 9703 return leakedSurface || killedApps; 9704 } 9705 9706 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9707 WindowState newFocus = computeFocusedWindowLocked(); 9708 if (mCurrentFocus != newFocus) { 9709 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9710 // This check makes sure that we don't already have the focus 9711 // change message pending. 9712 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9713 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9714 // TODO(multidisplay): Focused windows on default display only. 9715 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9716 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked( 9717 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 9718 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES); 9719 if (imWindowChanged) { 9720 displayContent.layoutNeeded = true; 9721 newFocus = computeFocusedWindowLocked(); 9722 } 9723 9724 if (true || DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " + 9725 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 9726 final WindowState oldFocus = mCurrentFocus; 9727 mCurrentFocus = newFocus; 9728 mLosingFocus.remove(newFocus); 9729 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9730 9731 if (imWindowChanged && oldFocus != mInputMethodWindow) { 9732 // Focus of the input method window changed. Perform layout if needed. 9733 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9734 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9735 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9736 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9737 // Client will do the layout, but we need to assign layers 9738 // for handleNewWindowLocked() below. 9739 assignLayersLocked(displayContent.getWindowList()); 9740 } 9741 } 9742 9743 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9744 // The change in focus caused us to need to do a layout. Okay. 9745 displayContent.layoutNeeded = true; 9746 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9747 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9748 } 9749 } 9750 9751 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9752 // If we defer assigning layers, then the caller is responsible for 9753 // doing this part. 9754 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 9755 } 9756 9757 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9758 return true; 9759 } 9760 return false; 9761 } 9762 9763 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 9764 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9765 } 9766 9767 private WindowState computeFocusedWindowLocked() { 9768 if (mAnimator.mUniverseBackground != null 9769 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 9770 return mAnimator.mUniverseBackground.mWin; 9771 } 9772 9773 final int displayCount = mDisplayContents.size(); 9774 for (int i = 0; i < displayCount; i++) { 9775 final DisplayContent displayContent = mDisplayContents.valueAt(i); 9776 WindowState win = findFocusedWindowLocked(displayContent); 9777 if (win != null) { 9778 return win; 9779 } 9780 } 9781 return null; 9782 } 9783 9784 private WindowState findFocusedWindowLocked(DisplayContent displayContent) { 9785 final WindowList windows = displayContent.getWindowList(); 9786 for (int i = windows.size() - 1; i >= 0; i--) { 9787 final WindowState win = windows.get(i); 9788 9789 if (localLOGV || DEBUG_FOCUS) Slog.v( 9790 TAG, "Looking for focus: " + i 9791 + " = " + win 9792 + ", flags=" + win.mAttrs.flags 9793 + ", canReceive=" + win.canReceiveKeys()); 9794 9795 AppWindowToken wtoken = win.mAppToken; 9796 9797 // If this window's application has been removed, just skip it. 9798 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 9799 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because " 9800 + (wtoken.removed ? "removed" : "sendingToBottom")); 9801 continue; 9802 } 9803 9804 if (!win.canReceiveKeys()) { 9805 continue; 9806 } 9807 9808 // Descend through all of the app tokens and find the first that either matches 9809 // win.mAppToken (return win) or mFocusedApp (return null). 9810 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && 9811 mFocusedApp != null) { 9812 ArrayList<Task> tasks = displayContent.getTasks(); 9813 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9814 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9815 int tokenNdx = tokens.size() - 1; 9816 for ( ; tokenNdx >= 0; --tokenNdx) { 9817 final AppWindowToken token = tokens.get(tokenNdx); 9818 if (wtoken == token) { 9819 break; 9820 } 9821 if (mFocusedApp == token) { 9822 // Whoops, we are below the focused app... no focus for you! 9823 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG, 9824 "findFocusedWindow: Reached focused app=" + mFocusedApp); 9825 return null; 9826 } 9827 } 9828 if (tokenNdx >= 0) { 9829 // Early exit from loop, must have found the matching token. 9830 break; 9831 } 9832 } 9833 } 9834 9835 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i + 9836 " = " + win); 9837 return win; 9838 } 9839 9840 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows."); 9841 return null; 9842 } 9843 9844 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 9845 if (mDisplayFrozen) { 9846 return; 9847 } 9848 9849 if (!mDisplayReady || !mPolicy.isScreenOnFully()) { 9850 // No need to freeze the screen before the system is ready or if 9851 // the screen is off. 9852 return; 9853 } 9854 9855 mScreenFrozenLock.acquire(); 9856 9857 mDisplayFrozen = true; 9858 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 9859 mLastFinishedFreezeSource = null; 9860 9861 mInputMonitor.freezeInputDispatchingLw(); 9862 9863 // Clear the last input window -- that is just used for 9864 // clean transitions between IMEs, and if we are freezing 9865 // the screen then the whole world is changing behind the scenes. 9866 mPolicy.setLastInputMethodWindowLw(null, null); 9867 9868 if (mAppTransition.isTransitionSet()) { 9869 mAppTransition.freeze(); 9870 } 9871 9872 if (PROFILE_ORIENTATION) { 9873 File file = new File("/data/system/frozen"); 9874 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 9875 } 9876 9877 if (CUSTOM_SCREEN_ROTATION) { 9878 mExitAnimId = exitAnim; 9879 mEnterAnimId = enterAnim; 9880 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9881 final int displayId = displayContent.getDisplayId(); 9882 ScreenRotationAnimation screenRotationAnimation = 9883 mAnimator.getScreenRotationAnimationLocked(displayId); 9884 if (screenRotationAnimation != null) { 9885 screenRotationAnimation.kill(); 9886 } 9887 9888 // TODO(multidisplay): rotation on main screen only. 9889 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 9890 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced()); 9891 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 9892 } 9893 } 9894 9895 private void stopFreezingDisplayLocked() { 9896 if (!mDisplayFrozen) { 9897 return; 9898 } 9899 9900 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen 9901 || mClientFreezingScreen) { 9902 if (DEBUG_ORIENTATION) Slog.d(TAG, 9903 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 9904 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 9905 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 9906 + ", mClientFreezingScreen=" + mClientFreezingScreen); 9907 return; 9908 } 9909 9910 mDisplayFrozen = false; 9911 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 9912 StringBuilder sb = new StringBuilder(128); 9913 sb.append("Screen frozen for "); 9914 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 9915 if (mLastFinishedFreezeSource != null) { 9916 sb.append(" due to "); 9917 sb.append(mLastFinishedFreezeSource); 9918 } 9919 Slog.i(TAG, sb.toString()); 9920 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 9921 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 9922 if (PROFILE_ORIENTATION) { 9923 Debug.stopMethodTracing(); 9924 } 9925 9926 boolean updateRotation = false; 9927 9928 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9929 final int displayId = displayContent.getDisplayId(); 9930 ScreenRotationAnimation screenRotationAnimation = 9931 mAnimator.getScreenRotationAnimationLocked(displayId); 9932 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 9933 && screenRotationAnimation.hasScreenshot()) { 9934 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 9935 // TODO(multidisplay): rotation on main screen only. 9936 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9937 // Get rotation animation again, with new top window 9938 boolean isDimming = displayContent.isDimming(); 9939 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 9940 mExitAnimId = mEnterAnimId = 0; 9941 } 9942 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 9943 mTransitionAnimationScale, displayInfo.logicalWidth, 9944 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 9945 scheduleAnimationLocked(); 9946 } else { 9947 screenRotationAnimation.kill(); 9948 screenRotationAnimation = null; 9949 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 9950 updateRotation = true; 9951 } 9952 } else { 9953 if (screenRotationAnimation != null) { 9954 screenRotationAnimation.kill(); 9955 screenRotationAnimation = null; 9956 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 9957 } 9958 updateRotation = true; 9959 } 9960 9961 mInputMonitor.thawInputDispatchingLw(); 9962 9963 boolean configChanged; 9964 9965 // While the display is frozen we don't re-compute the orientation 9966 // to avoid inconsistent states. However, something interesting 9967 // could have actually changed during that time so re-evaluate it 9968 // now to catch that. 9969 configChanged = updateOrientationFromAppTokensLocked(false); 9970 9971 // A little kludge: a lot could have happened while the 9972 // display was frozen, so now that we are coming back we 9973 // do a gc so that any remote references the system 9974 // processes holds on others can be released if they are 9975 // no longer needed. 9976 mH.removeMessages(H.FORCE_GC); 9977 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 9978 9979 mScreenFrozenLock.release(); 9980 9981 if (updateRotation) { 9982 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9983 configChanged |= updateRotationUncheckedLocked(false); 9984 } 9985 9986 if (configChanged) { 9987 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9988 } 9989 } 9990 9991 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 9992 DisplayMetrics dm) { 9993 if (index < tokens.length) { 9994 String str = tokens[index]; 9995 if (str != null && str.length() > 0) { 9996 try { 9997 int val = Integer.parseInt(str); 9998 return val; 9999 } catch (Exception e) { 10000 } 10001 } 10002 } 10003 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 10004 return defDps; 10005 } 10006 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 10007 return val; 10008 } 10009 10010 void createWatermarkInTransaction() { 10011 if (mWatermark != null) { 10012 return; 10013 } 10014 10015 File file = new File("/system/etc/setup.conf"); 10016 FileInputStream in = null; 10017 DataInputStream ind = null; 10018 try { 10019 in = new FileInputStream(file); 10020 ind = new DataInputStream(in); 10021 String line = ind.readLine(); 10022 if (line != null) { 10023 String[] toks = line.split("%"); 10024 if (toks != null && toks.length > 0) { 10025 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 10026 mRealDisplayMetrics, mFxSession, toks); 10027 } 10028 } 10029 } catch (FileNotFoundException e) { 10030 } catch (IOException e) { 10031 } finally { 10032 if (ind != null) { 10033 try { 10034 ind.close(); 10035 } catch (IOException e) { 10036 } 10037 } else if (in != null) { 10038 try { 10039 in.close(); 10040 } catch (IOException e) { 10041 } 10042 } 10043 } 10044 } 10045 10046 @Override 10047 public void statusBarVisibilityChanged(int visibility) { 10048 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10049 != PackageManager.PERMISSION_GRANTED) { 10050 throw new SecurityException("Caller does not hold permission " 10051 + android.Manifest.permission.STATUS_BAR); 10052 } 10053 10054 synchronized (mWindowMap) { 10055 mLastStatusBarVisibility = visibility; 10056 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 10057 updateStatusBarVisibilityLocked(visibility); 10058 } 10059 } 10060 10061 // TOOD(multidisplay): StatusBar on multiple screens? 10062 void updateStatusBarVisibilityLocked(int visibility) { 10063 mInputManager.setSystemUiVisibility(visibility); 10064 final WindowList windows = getDefaultWindowListLocked(); 10065 final int N = windows.size(); 10066 for (int i = 0; i < N; i++) { 10067 WindowState ws = windows.get(i); 10068 try { 10069 int curValue = ws.mSystemUiVisibility; 10070 int diff = curValue ^ visibility; 10071 // We are only interested in differences of one of the 10072 // clearable flags... 10073 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 10074 // ...if it has actually been cleared. 10075 diff &= ~visibility; 10076 int newValue = (curValue&~diff) | (visibility&diff); 10077 if (newValue != curValue) { 10078 ws.mSeq++; 10079 ws.mSystemUiVisibility = newValue; 10080 } 10081 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 10082 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 10083 visibility, newValue, diff); 10084 } 10085 } catch (RemoteException e) { 10086 // so sorry 10087 } 10088 } 10089 } 10090 10091 @Override 10092 public void reevaluateStatusBarVisibility() { 10093 synchronized (mWindowMap) { 10094 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 10095 updateStatusBarVisibilityLocked(visibility); 10096 performLayoutAndPlaceSurfacesLocked(); 10097 } 10098 } 10099 10100 @Override 10101 public FakeWindow addFakeWindow(Looper looper, 10102 InputEventReceiver.Factory inputEventReceiverFactory, 10103 String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags, 10104 boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) { 10105 synchronized (mWindowMap) { 10106 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 10107 name, windowType, 10108 layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys, 10109 hasFocus, touchFullscreen); 10110 int i=0; 10111 while (i<mFakeWindows.size()) { 10112 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 10113 break; 10114 } 10115 } 10116 mFakeWindows.add(i, fw); 10117 mInputMonitor.updateInputWindowsLw(true); 10118 return fw; 10119 } 10120 } 10121 10122 boolean removeFakeWindowLocked(FakeWindow window) { 10123 synchronized (mWindowMap) { 10124 if (mFakeWindows.remove(window)) { 10125 mInputMonitor.updateInputWindowsLw(true); 10126 return true; 10127 } 10128 return false; 10129 } 10130 } 10131 10132 // It is assumed that this method is called only by InputMethodManagerService. 10133 public void saveLastInputMethodWindowForTransition() { 10134 synchronized (mWindowMap) { 10135 // TODO(multidisplay): Pass in the displayID. 10136 DisplayContent displayContent = getDefaultDisplayContentLocked(); 10137 if (mInputMethodWindow != null) { 10138 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 10139 } 10140 } 10141 } 10142 10143 @Override 10144 public boolean hasNavigationBar() { 10145 return mPolicy.hasNavigationBar(); 10146 } 10147 10148 @Override 10149 public void lockNow(Bundle options) { 10150 mPolicy.lockNow(options); 10151 } 10152 10153 @Override 10154 public boolean isSafeModeEnabled() { 10155 return mSafeMode; 10156 } 10157 10158 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10159 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 10160 mPolicy.dump(" ", pw, args); 10161 } 10162 10163 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10164 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 10165 mAnimator.dumpLocked(pw, " ", dumpAll); 10166 } 10167 10168 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 10169 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 10170 if (mTokenMap.size() > 0) { 10171 pw.println(" All tokens:"); 10172 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10173 while (it.hasNext()) { 10174 WindowToken token = it.next(); 10175 pw.print(" "); pw.print(token); 10176 if (dumpAll) { 10177 pw.println(':'); 10178 token.dump(pw, " "); 10179 } else { 10180 pw.println(); 10181 } 10182 } 10183 } 10184 if (mWallpaperTokens.size() > 0) { 10185 pw.println(); 10186 pw.println(" Wallpaper tokens:"); 10187 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 10188 WindowToken token = mWallpaperTokens.get(i); 10189 pw.print(" Wallpaper #"); pw.print(i); 10190 pw.print(' '); pw.print(token); 10191 if (dumpAll) { 10192 pw.println(':'); 10193 token.dump(pw, " "); 10194 } else { 10195 pw.println(); 10196 } 10197 } 10198 } 10199 if (mFinishedStarting.size() > 0) { 10200 pw.println(); 10201 pw.println(" Finishing start of application tokens:"); 10202 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10203 WindowToken token = mFinishedStarting.get(i); 10204 pw.print(" Finished Starting #"); pw.print(i); 10205 pw.print(' '); pw.print(token); 10206 if (dumpAll) { 10207 pw.println(':'); 10208 token.dump(pw, " "); 10209 } else { 10210 pw.println(); 10211 } 10212 } 10213 } 10214 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 10215 pw.println(); 10216 if (mOpeningApps.size() > 0) { 10217 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10218 } 10219 if (mClosingApps.size() > 0) { 10220 pw.print(" mClosingApps="); pw.println(mClosingApps); 10221 } 10222 } 10223 } 10224 10225 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 10226 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 10227 if (mSessions.size() > 0) { 10228 Iterator<Session> it = mSessions.iterator(); 10229 while (it.hasNext()) { 10230 Session s = it.next(); 10231 pw.print(" Session "); pw.print(s); pw.println(':'); 10232 s.dump(pw, " "); 10233 } 10234 } 10235 } 10236 10237 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 10238 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 10239 if (mDisplayReady) { 10240 final int numDisplays = mDisplayContents.size(); 10241 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10242 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10243 displayContent.dump(" ", pw); 10244 } 10245 } else { 10246 pw.println(" NO DISPLAY"); 10247 } 10248 } 10249 10250 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 10251 ArrayList<WindowState> windows) { 10252 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 10253 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 10254 } 10255 10256 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 10257 ArrayList<WindowState> windows) { 10258 final int numDisplays = mDisplayContents.size(); 10259 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10260 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); 10261 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10262 final WindowState w = windowList.get(winNdx); 10263 if (windows == null || windows.contains(w)) { 10264 pw.print(" Window #"); pw.print(winNdx); pw.print(' '); 10265 pw.print(w); pw.println(":"); 10266 w.dump(pw, " ", dumpAll || windows != null); 10267 } 10268 } 10269 } 10270 if (mInputMethodDialogs.size() > 0) { 10271 pw.println(); 10272 pw.println(" Input method dialogs:"); 10273 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 10274 WindowState w = mInputMethodDialogs.get(i); 10275 if (windows == null || windows.contains(w)) { 10276 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 10277 } 10278 } 10279 } 10280 if (mPendingRemove.size() > 0) { 10281 pw.println(); 10282 pw.println(" Remove pending for:"); 10283 for (int i=mPendingRemove.size()-1; i>=0; i--) { 10284 WindowState w = mPendingRemove.get(i); 10285 if (windows == null || windows.contains(w)) { 10286 pw.print(" Remove #"); pw.print(i); pw.print(' '); 10287 pw.print(w); 10288 if (dumpAll) { 10289 pw.println(":"); 10290 w.dump(pw, " ", true); 10291 } else { 10292 pw.println(); 10293 } 10294 } 10295 } 10296 } 10297 if (mForceRemoves != null && mForceRemoves.size() > 0) { 10298 pw.println(); 10299 pw.println(" Windows force removing:"); 10300 for (int i=mForceRemoves.size()-1; i>=0; i--) { 10301 WindowState w = mForceRemoves.get(i); 10302 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10303 pw.print(w); 10304 if (dumpAll) { 10305 pw.println(":"); 10306 w.dump(pw, " ", true); 10307 } else { 10308 pw.println(); 10309 } 10310 } 10311 } 10312 if (mDestroySurface.size() > 0) { 10313 pw.println(); 10314 pw.println(" Windows waiting to destroy their surface:"); 10315 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10316 WindowState w = mDestroySurface.get(i); 10317 if (windows == null || windows.contains(w)) { 10318 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10319 pw.print(w); 10320 if (dumpAll) { 10321 pw.println(":"); 10322 w.dump(pw, " ", true); 10323 } else { 10324 pw.println(); 10325 } 10326 } 10327 } 10328 } 10329 if (mLosingFocus.size() > 0) { 10330 pw.println(); 10331 pw.println(" Windows losing focus:"); 10332 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10333 WindowState w = mLosingFocus.get(i); 10334 if (windows == null || windows.contains(w)) { 10335 pw.print(" Losing #"); pw.print(i); pw.print(' '); 10336 pw.print(w); 10337 if (dumpAll) { 10338 pw.println(":"); 10339 w.dump(pw, " ", true); 10340 } else { 10341 pw.println(); 10342 } 10343 } 10344 } 10345 } 10346 if (mResizingWindows.size() > 0) { 10347 pw.println(); 10348 pw.println(" Windows waiting to resize:"); 10349 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10350 WindowState w = mResizingWindows.get(i); 10351 if (windows == null || windows.contains(w)) { 10352 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 10353 pw.print(w); 10354 if (dumpAll) { 10355 pw.println(":"); 10356 w.dump(pw, " ", true); 10357 } else { 10358 pw.println(); 10359 } 10360 } 10361 } 10362 } 10363 if (mWaitingForDrawn.size() > 0) { 10364 pw.println(); 10365 pw.println(" Clients waiting for these windows to be drawn:"); 10366 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10367 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i); 10368 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first); 10369 pw.print(": "); pw.println(pair.second); 10370 } 10371 } 10372 pw.println(); 10373 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10374 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10375 if (mLastFocus != mCurrentFocus) { 10376 pw.print(" mLastFocus="); pw.println(mLastFocus); 10377 } 10378 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10379 if (mInputMethodTarget != null) { 10380 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10381 } 10382 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10383 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10384 pw.print(" mLastDisplayFreezeDuration="); 10385 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 10386 if ( mLastFinishedFreezeSource != null) { 10387 pw.print(" due to "); 10388 pw.print(mLastFinishedFreezeSource); 10389 } 10390 pw.println(); 10391 if (dumpAll) { 10392 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 10393 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 10394 if (mLastStatusBarVisibility != 0) { 10395 pw.print(" mLastStatusBarVisibility=0x"); 10396 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 10397 } 10398 if (mInputMethodWindow != null) { 10399 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10400 } 10401 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 10402 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) { 10403 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 10404 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 10405 } 10406 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 10407 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 10408 if (mInputMethodAnimLayerAdjustment != 0 || 10409 mWallpaperAnimLayerAdjustment != 0) { 10410 pw.print(" mInputMethodAnimLayerAdjustment="); 10411 pw.print(mInputMethodAnimLayerAdjustment); 10412 pw.print(" mWallpaperAnimLayerAdjustment="); 10413 pw.println(mWallpaperAnimLayerAdjustment); 10414 } 10415 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10416 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10417 if (needsLayout()) { 10418 pw.print(" layoutNeeded on displays="); 10419 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10420 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10421 if (displayContent.layoutNeeded) { 10422 pw.print(displayContent.getDisplayId()); 10423 } 10424 } 10425 pw.println(); 10426 } 10427 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 10428 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10429 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 10430 pw.print(" client="); pw.print(mClientFreezingScreen); 10431 pw.print(" apps="); pw.print(mAppsFreezingScreen); 10432 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 10433 pw.print(" mRotation="); pw.print(mRotation); 10434 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 10435 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 10436 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 10437 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 10438 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); 10439 pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale); 10440 pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale); 10441 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); 10442 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 10443 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 10444 pw.println(" mLayoutToAnim:"); 10445 mAppTransition.dump(pw); 10446 } 10447 } 10448 10449 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10450 int opti, boolean dumpAll) { 10451 WindowList windows = new WindowList(); 10452 if ("visible".equals(name)) { 10453 synchronized(mWindowMap) { 10454 final int numDisplays = mDisplayContents.size(); 10455 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10456 final WindowList windowList = 10457 mDisplayContents.valueAt(displayNdx).getWindowList(); 10458 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10459 final WindowState w = windowList.get(winNdx); 10460 if (w.mWinAnimator.mSurfaceShown) { 10461 windows.add(w); 10462 } 10463 } 10464 } 10465 } 10466 } else { 10467 int objectId = 0; 10468 // See if this is an object ID. 10469 try { 10470 objectId = Integer.parseInt(name, 16); 10471 name = null; 10472 } catch (RuntimeException e) { 10473 } 10474 synchronized(mWindowMap) { 10475 final int numDisplays = mDisplayContents.size(); 10476 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10477 final WindowList windowList = 10478 mDisplayContents.valueAt(displayNdx).getWindowList(); 10479 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10480 final WindowState w = windowList.get(winNdx); 10481 if (name != null) { 10482 if (w.mAttrs.getTitle().toString().contains(name)) { 10483 windows.add(w); 10484 } 10485 } else if (System.identityHashCode(w) == objectId) { 10486 windows.add(w); 10487 } 10488 } 10489 } 10490 } 10491 } 10492 10493 if (windows.size() <= 0) { 10494 return false; 10495 } 10496 10497 synchronized(mWindowMap) { 10498 dumpWindowsLocked(pw, dumpAll, windows); 10499 } 10500 return true; 10501 } 10502 10503 void dumpLastANRLocked(PrintWriter pw) { 10504 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10505 if (mLastANRState == null) { 10506 pw.println(" <no ANR has occurred since boot>"); 10507 } else { 10508 pw.println(mLastANRState); 10509 } 10510 } 10511 10512 /** 10513 * Saves information about the state of the window manager at 10514 * the time an ANR occurred before anything else in the system changes 10515 * in response. 10516 * 10517 * @param appWindowToken The application that ANR'd, may be null. 10518 * @param windowState The window that ANR'd, may be null. 10519 * @param reason The reason for the ANR, may be null. 10520 */ 10521 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, 10522 String reason) { 10523 StringWriter sw = new StringWriter(); 10524 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 10525 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10526 if (appWindowToken != null) { 10527 pw.println(" Application at fault: " + appWindowToken.stringName); 10528 } 10529 if (windowState != null) { 10530 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10531 } 10532 if (reason != null) { 10533 pw.println(" Reason: " + reason); 10534 } 10535 pw.println(); 10536 dumpWindowsNoHeaderLocked(pw, true, null); 10537 pw.close(); 10538 mLastANRState = sw.toString(); 10539 } 10540 10541 @Override 10542 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10543 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10544 != PackageManager.PERMISSION_GRANTED) { 10545 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10546 + Binder.getCallingPid() 10547 + ", uid=" + Binder.getCallingUid()); 10548 return; 10549 } 10550 10551 boolean dumpAll = false; 10552 10553 int opti = 0; 10554 while (opti < args.length) { 10555 String opt = args[opti]; 10556 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10557 break; 10558 } 10559 opti++; 10560 if ("-a".equals(opt)) { 10561 dumpAll = true; 10562 } else if ("-h".equals(opt)) { 10563 pw.println("Window manager dump options:"); 10564 pw.println(" [-a] [-h] [cmd] ..."); 10565 pw.println(" cmd may be one of:"); 10566 pw.println(" l[astanr]: last ANR information"); 10567 pw.println(" p[policy]: policy state"); 10568 pw.println(" a[animator]: animator state"); 10569 pw.println(" s[essions]: active sessions"); 10570 pw.println(" d[isplays]: active display contents"); 10571 pw.println(" t[okens]: token list"); 10572 pw.println(" w[indows]: window list"); 10573 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10574 pw.println(" be a partial substring in a window name, a"); 10575 pw.println(" Window hex object identifier, or"); 10576 pw.println(" \"all\" for all windows, or"); 10577 pw.println(" \"visible\" for the visible windows."); 10578 pw.println(" -a: include all available server state."); 10579 return; 10580 } else { 10581 pw.println("Unknown argument: " + opt + "; use -h for help"); 10582 } 10583 } 10584 10585 // Is the caller requesting to dump a particular piece of data? 10586 if (opti < args.length) { 10587 String cmd = args[opti]; 10588 opti++; 10589 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10590 synchronized(mWindowMap) { 10591 dumpLastANRLocked(pw); 10592 } 10593 return; 10594 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10595 synchronized(mWindowMap) { 10596 dumpPolicyLocked(pw, args, true); 10597 } 10598 return; 10599 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 10600 synchronized(mWindowMap) { 10601 dumpAnimatorLocked(pw, args, true); 10602 } 10603 return; 10604 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10605 synchronized(mWindowMap) { 10606 dumpSessionsLocked(pw, true); 10607 } 10608 return; 10609 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 10610 synchronized(mWindowMap) { 10611 dumpDisplayContentsLocked(pw, true); 10612 } 10613 return; 10614 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10615 synchronized(mWindowMap) { 10616 dumpTokensLocked(pw, true); 10617 } 10618 return; 10619 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10620 synchronized(mWindowMap) { 10621 dumpWindowsLocked(pw, true, null); 10622 } 10623 return; 10624 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10625 synchronized(mWindowMap) { 10626 dumpWindowsLocked(pw, true, null); 10627 } 10628 return; 10629 } else { 10630 // Dumping a single name? 10631 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10632 pw.println("Bad window command, or no windows match: " + cmd); 10633 pw.println("Use -h for help."); 10634 } 10635 return; 10636 } 10637 } 10638 10639 synchronized(mWindowMap) { 10640 pw.println(); 10641 if (dumpAll) { 10642 pw.println("-------------------------------------------------------------------------------"); 10643 } 10644 dumpLastANRLocked(pw); 10645 pw.println(); 10646 if (dumpAll) { 10647 pw.println("-------------------------------------------------------------------------------"); 10648 } 10649 dumpPolicyLocked(pw, args, dumpAll); 10650 pw.println(); 10651 if (dumpAll) { 10652 pw.println("-------------------------------------------------------------------------------"); 10653 } 10654 dumpAnimatorLocked(pw, args, dumpAll); 10655 pw.println(); 10656 if (dumpAll) { 10657 pw.println("-------------------------------------------------------------------------------"); 10658 } 10659 dumpSessionsLocked(pw, dumpAll); 10660 pw.println(); 10661 if (dumpAll) { 10662 pw.println("-------------------------------------------------------------------------------"); 10663 } 10664 dumpDisplayContentsLocked(pw, dumpAll); 10665 pw.println(); 10666 if (dumpAll) { 10667 pw.println("-------------------------------------------------------------------------------"); 10668 } 10669 dumpTokensLocked(pw, dumpAll); 10670 pw.println(); 10671 if (dumpAll) { 10672 pw.println("-------------------------------------------------------------------------------"); 10673 } 10674 dumpWindowsLocked(pw, dumpAll, null); 10675 } 10676 } 10677 10678 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10679 @Override 10680 public void monitor() { 10681 synchronized (mWindowMap) { } 10682 } 10683 10684 public interface OnHardKeyboardStatusChangeListener { 10685 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 10686 } 10687 10688 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 10689 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 10690 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 10691 Integer.toHexString(pendingLayoutChanges)); 10692 } 10693 } 10694 10695 private DisplayContent newDisplayContentLocked(final Display display) { 10696 DisplayContent displayContent = new DisplayContent(display, this); 10697 final int displayId = display.getDisplayId(); 10698 mDisplayContents.put(displayId, displayContent); 10699 10700 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10701 final Rect rect = new Rect(); 10702 mDisplaySettings.getOverscanLocked(displayInfo.name, rect); 10703 synchronized (displayContent.mDisplaySizeLock) { 10704 displayInfo.overscanLeft = rect.left; 10705 displayInfo.overscanTop = rect.top; 10706 displayInfo.overscanRight = rect.right; 10707 displayInfo.overscanBottom = rect.bottom; 10708 mDisplayManagerService.setDisplayInfoOverrideFromWindowManager( 10709 displayId, displayInfo); 10710 } 10711 configureDisplayPolicyLocked(displayContent); 10712 10713 // TODO: Create an input channel for each display with touch capability. 10714 if (displayId == Display.DEFAULT_DISPLAY) { 10715 displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent); 10716 registerPointerEventListener(displayContent.mTapDetector); 10717 } 10718 10719 return displayContent; 10720 } 10721 10722 public void createDisplayContentLocked(final Display display) { 10723 if (display == null) { 10724 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 10725 } 10726 getDisplayContentLocked(display.getDisplayId()); 10727 } 10728 10729 /** 10730 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 10731 * there is a Display for the displayId. 10732 * @param displayId The display the caller is interested in. 10733 * @return The DisplayContent associated with displayId or null if there is no Display for it. 10734 */ 10735 public DisplayContent getDisplayContentLocked(final int displayId) { 10736 DisplayContent displayContent = mDisplayContents.get(displayId); 10737 if (displayContent == null) { 10738 final Display display = mDisplayManager.getDisplay(displayId); 10739 if (display != null) { 10740 displayContent = newDisplayContentLocked(display); 10741 } 10742 } 10743 return displayContent; 10744 } 10745 10746 // There is an inherent assumption that this will never return null. 10747 public DisplayContent getDefaultDisplayContentLocked() { 10748 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 10749 } 10750 10751 public WindowList getDefaultWindowListLocked() { 10752 return getDefaultDisplayContentLocked().getWindowList(); 10753 } 10754 10755 public DisplayInfo getDefaultDisplayInfoLocked() { 10756 return getDefaultDisplayContentLocked().getDisplayInfo(); 10757 } 10758 10759 /** 10760 * Return the list of WindowStates associated on the passed display. 10761 * @param display The screen to return windows from. 10762 * @return The list of WindowStates on the screen, or null if the there is no screen. 10763 */ 10764 public WindowList getWindowListLocked(final Display display) { 10765 return getWindowListLocked(display.getDisplayId()); 10766 } 10767 10768 /** 10769 * Return the list of WindowStates associated on the passed display. 10770 * @param displayId The screen to return windows from. 10771 * @return The list of WindowStates on the screen, or null if the there is no screen. 10772 */ 10773 public WindowList getWindowListLocked(final int displayId) { 10774 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10775 return displayContent != null ? displayContent.getWindowList() : null; 10776 } 10777 10778 @Override 10779 public void onDisplayAdded(int displayId) { 10780 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 10781 } 10782 10783 private void handleDisplayAddedLocked(int displayId) { 10784 final Display display = mDisplayManager.getDisplay(displayId); 10785 if (display != null) { 10786 createDisplayContentLocked(display); 10787 displayReady(displayId); 10788 } 10789 } 10790 10791 @Override 10792 public void onDisplayRemoved(int displayId) { 10793 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 10794 } 10795 10796 private void handleDisplayRemovedLocked(int displayId) { 10797 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10798 if (displayContent != null) { 10799 mDisplayContents.delete(displayId); 10800 displayContent.close(); 10801 if (displayId == Display.DEFAULT_DISPLAY) { 10802 unregisterPointerEventListener(displayContent.mTapDetector); 10803 } 10804 WindowList windows = displayContent.getWindowList(); 10805 while (!windows.isEmpty()) { 10806 final WindowState win = windows.get(windows.size() - 1); 10807 removeWindowLocked(win.mSession, win); 10808 } 10809 } 10810 mAnimator.removeDisplayLocked(displayId); 10811 } 10812 10813 @Override 10814 public void onDisplayChanged(int displayId) { 10815 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 10816 } 10817 10818 private void handleDisplayChangedLocked(int displayId) { 10819 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10820 if (displayContent != null) { 10821 displayContent.updateDisplayInfo(); 10822 } 10823 } 10824 10825 @Override 10826 public Object getWindowManagerLock() { 10827 return mWindowMap; 10828 } 10829} 10830