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