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