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