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