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