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