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