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