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