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