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