WindowManagerService.java revision 343ad71d7cb4934751a91006677266bd73ed224c
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.SurfaceSession; 136import android.view.View; 137import android.view.ViewTreeObserver; 138import android.view.WindowManager; 139import android.view.WindowManagerGlobal; 140import android.view.WindowManagerPolicy; 141import android.view.WindowManager.LayoutParams; 142import android.view.WindowManagerPolicy.FakeWindow; 143import android.view.animation.Animation; 144import android.view.animation.AnimationUtils; 145import android.view.animation.Transformation; 146 147import java.io.BufferedWriter; 148import java.io.DataInputStream; 149import java.io.File; 150import java.io.FileDescriptor; 151import java.io.FileInputStream; 152import java.io.FileNotFoundException; 153import java.io.IOException; 154import java.io.OutputStream; 155import java.io.OutputStreamWriter; 156import java.io.PrintWriter; 157import java.io.StringWriter; 158import java.net.Socket; 159import java.text.DateFormat; 160import java.util.ArrayList; 161import java.util.Date; 162import java.util.HashMap; 163import java.util.HashSet; 164import java.util.Iterator; 165import java.util.List; 166import java.util.NoSuchElementException; 167 168/** {@hide} */ 169public class WindowManagerService extends IWindowManager.Stub 170 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs, 171 DisplayManagerService.WindowManagerFuncs, DisplayManager.DisplayListener { 172 static final String TAG = "WindowManager"; 173 static final boolean DEBUG = false; 174 static final boolean DEBUG_ADD_REMOVE = false; 175 static final boolean DEBUG_FOCUS = false; 176 static final boolean DEBUG_ANIM = false; 177 static final boolean DEBUG_LAYOUT = false; 178 static final boolean DEBUG_RESIZE = false; 179 static final boolean DEBUG_LAYERS = false; 180 static final boolean DEBUG_INPUT = false; 181 static final boolean DEBUG_INPUT_METHOD = false; 182 static final boolean DEBUG_VISIBILITY = false; 183 static final boolean DEBUG_WINDOW_MOVEMENT = false; 184 static final boolean DEBUG_TOKEN_MOVEMENT = true; 185 static final boolean DEBUG_ORIENTATION = false; 186 static final boolean DEBUG_APP_ORIENTATION = false; 187 static final boolean DEBUG_CONFIGURATION = false; 188 static final boolean DEBUG_APP_TRANSITIONS = false; 189 static final boolean DEBUG_STARTING_WINDOW = false; 190 static final boolean DEBUG_REORDER = false; 191 static final boolean DEBUG_WALLPAPER = false; 192 static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER; 193 static final boolean DEBUG_DRAG = false; 194 static final boolean DEBUG_SCREEN_ON = false; 195 static final boolean DEBUG_SCREENSHOT = false; 196 static final boolean DEBUG_BOOT = false; 197 static final boolean DEBUG_LAYOUT_REPEATS = true; 198 static final boolean DEBUG_SURFACE_TRACE = false; 199 static final boolean DEBUG_WINDOW_TRACE = false; 200 static final boolean DEBUG_TASK_MOVEMENT = false; 201 static final boolean SHOW_SURFACE_ALLOC = false; 202 static final boolean SHOW_TRANSACTIONS = false; 203 static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS; 204 static final boolean HIDE_STACK_CRAWLS = true; 205 static final int LAYOUT_REPEAT_THRESHOLD = 4; 206 207 static final boolean PROFILE_ORIENTATION = false; 208 static final boolean localLOGV = DEBUG; 209 210 final static boolean REVERSE_ITERATOR = true; 211 final static boolean FORWARD_ITERATOR = false; 212 213 /** How much to multiply the policy's type layer, to reserve room 214 * for multiple windows of the same type and Z-ordering adjustment 215 * with TYPE_LAYER_OFFSET. */ 216 static final int TYPE_LAYER_MULTIPLIER = 10000; 217 218 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above 219 * or below others in the same layer. */ 220 static final int TYPE_LAYER_OFFSET = 1000; 221 222 /** How much to increment the layer for each window, to reserve room 223 * for effect surfaces between them. 224 */ 225 static final int WINDOW_LAYER_MULTIPLIER = 5; 226 227 /** 228 * Dim surface layer is immediately below target window. 229 */ 230 static final int LAYER_OFFSET_DIM = 1; 231 232 /** 233 * Blur surface layer is immediately below dim layer. 234 */ 235 static final int LAYER_OFFSET_BLUR = 2; 236 237 /** 238 * Animation thumbnail is as far as possible below the window above 239 * the thumbnail (or in other words as far as possible above the window 240 * below it). 241 */ 242 static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER-1; 243 244 /** 245 * Layer at which to put the rotation freeze snapshot. 246 */ 247 static final int FREEZE_LAYER = (TYPE_LAYER_MULTIPLIER * 200) + 1; 248 249 /** 250 * Layer at which to put the mask for emulated screen sizes. 251 */ 252 static final int MASK_LAYER = TYPE_LAYER_MULTIPLIER * 200; 253 254 /** The maximum length we will accept for a loaded animation duration: 255 * this is 10 seconds. 256 */ 257 static final int MAX_ANIMATION_DURATION = 10*1000; 258 259 /** Amount of time (in milliseconds) to animate the fade-in-out transition for 260 * compatible windows. 261 */ 262 static final int DEFAULT_FADE_IN_OUT_DURATION = 400; 263 264 /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */ 265 static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000; 266 267 /** 268 * If true, the window manager will do its own custom freezing and general 269 * management of the screen during rotation. 270 */ 271 static final boolean CUSTOM_SCREEN_ROTATION = true; 272 273 // Maximum number of milliseconds to wait for input devices to be enumerated before 274 // proceding with safe mode detection. 275 private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000; 276 277 // Default input dispatching timeout in nanoseconds. 278 static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L; 279 280 static final int UPDATE_FOCUS_NORMAL = 0; 281 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1; 282 static final int UPDATE_FOCUS_PLACING_SURFACES = 2; 283 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3; 284 285 private static final String SYSTEM_SECURE = "ro.secure"; 286 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; 287 288 final private KeyguardDisableHandler mKeyguardDisableHandler; 289 290 private final boolean mHeadless; 291 292 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 293 @Override 294 public void onReceive(Context context, Intent intent) { 295 final String action = intent.getAction(); 296 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) { 297 mKeyguardDisableHandler.sendEmptyMessage( 298 KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED); 299 } 300 } 301 }; 302 303 // Current user when multi-user is enabled. Don't show windows of non-current user. 304 int mCurrentUserId; 305 306 final Context mContext; 307 308 final boolean mHaveInputMethods; 309 310 final boolean mAllowBootMessages; 311 312 final boolean mLimitedAlphaCompositing; 313 314 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager(); 315 316 final IActivityManager mActivityManager; 317 318 final IBatteryStats mBatteryStats; 319 320 final AppOpsManager mAppOps; 321 322 /** 323 * All currently active sessions with clients. 324 */ 325 final HashSet<Session> mSessions = new HashSet<Session>(); 326 327 /** 328 * Mapping from an IWindow IBinder to the server's Window object. 329 * This is also used as the lock for all of our state. 330 * NOTE: Never call into methods that lock ActivityManagerService while holding this object. 331 */ 332 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>(); 333 334 /** 335 * Mapping from a token IBinder to a WindowToken object. 336 */ 337 final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>(); 338 339 /** 340 * List of window tokens that have finished starting their application, 341 * and now need to have the policy remove their windows. 342 */ 343 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>(); 344 345 /** 346 * Fake windows added to the window manager. Note: ordered from top to 347 * bottom, opposite of mWindows. 348 */ 349 final ArrayList<FakeWindowImpl> mFakeWindows = new ArrayList<FakeWindowImpl>(); 350 351 /** 352 * Windows that are being resized. Used so we can tell the client about 353 * the resize after closing the transaction in which we resized the 354 * underlying surface. 355 */ 356 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>(); 357 358 /** 359 * Windows whose animations have ended and now must be removed. 360 */ 361 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>(); 362 363 /** 364 * Used when processing mPendingRemove to avoid working on the original array. 365 */ 366 WindowState[] mPendingRemoveTmp = new WindowState[20]; 367 368 /** 369 * Windows whose surface should be destroyed. 370 */ 371 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>(); 372 373 /** 374 * Windows that have lost input focus and are waiting for the new 375 * focus window to be displayed before they are told about this. 376 */ 377 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>(); 378 379 /** 380 * This is set when we have run out of memory, and will either be an empty 381 * list or contain windows that need to be force removed. 382 */ 383 ArrayList<WindowState> mForceRemoves; 384 385 /** 386 * Windows that clients are waiting to have drawn. 387 */ 388 ArrayList<Pair<WindowState, IRemoteCallback>> mWaitingForDrawn 389 = new ArrayList<Pair<WindowState, IRemoteCallback>>(); 390 391 /** 392 * Windows that have called relayout() while we were running animations, 393 * so we need to tell when the animation is done. 394 */ 395 final ArrayList<WindowState> mRelayoutWhileAnimating = new ArrayList<WindowState>(); 396 397 /** 398 * Used when rebuilding window list to keep track of windows that have 399 * been removed. 400 */ 401 WindowState[] mRebuildTmp = new WindowState[20]; 402 403 IInputMethodManager mInputMethodManager; 404 405 DisplayMagnifier mDisplayMagnifier; 406 407 final SurfaceSession mFxSession; 408 Watermark mWatermark; 409 StrictModeFlash mStrictModeFlash; 410 411 final float[] mTmpFloats = new float[9]; 412 413 boolean mDisplayReady; 414 boolean mSafeMode; 415 boolean mDisplayEnabled = false; 416 boolean mSystemBooted = false; 417 boolean mForceDisplayEnabled = false; 418 boolean mShowingBootMessages = false; 419 420 String mLastANRState; 421 422 /** All DisplayContents in the world, kept here */ 423 private SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>(); 424 private SparseArray<DisplayContent> mTaskIdToDisplayContents = 425 new SparseArray<DisplayContent>(); 426 427 private final AllWindowsIterator mTmpWindowsIterator = new AllWindowsIterator(); 428 429 int mRotation = 0; 430 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 431 boolean mAltOrientation = false; 432 ArrayList<IRotationWatcher> mRotationWatchers 433 = new ArrayList<IRotationWatcher>(); 434 int mDeferredRotationPauseCount; 435 436 final Rect mSystemDecorRect = new Rect(); 437 int mSystemDecorLayer = 0; 438 final Rect mScreenRect = new Rect(); 439 440 boolean mTraversalScheduled = false; 441 boolean mDisplayFrozen = false; 442 boolean mWaitingForConfig = false; 443 boolean mWindowsFreezingScreen = false; 444 boolean mClientFreezingScreen = false; 445 int mAppsFreezingScreen = 0; 446 int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 447 448 int mLayoutSeq = 0; 449 450 int mLastStatusBarVisibility = 0; 451 452 // State while inside of layoutAndPlaceSurfacesLocked(). 453 boolean mFocusMayChange; 454 455 Configuration mCurConfiguration = new Configuration(); 456 457 // This is held as long as we have the screen frozen, to give us time to 458 // perform a rotation animation when turning off shows the lock screen which 459 // changes the orientation. 460 private PowerManager.WakeLock mScreenFrozenLock; 461 462 final AppTransition mAppTransition; 463 boolean mStartingIconInTransition = false; 464 boolean mSkipAppTransitionAnimation = false; 465 466 final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>(); 467 final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>(); 468 469 boolean mIsTouchDevice; 470 471 final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 472 final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics(); 473 final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics(); 474 final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics(); 475 476 final H mH = new H(); 477 478 final Choreographer mChoreographer = Choreographer.getInstance(); 479 480 WindowState mCurrentFocus = null; 481 WindowState mLastFocus = null; 482 483 /** This just indicates the window the input method is on top of, not 484 * necessarily the window its input is going to. */ 485 WindowState mInputMethodTarget = null; 486 487 /** If true hold off on modifying the animation layer of mInputMethodTarget */ 488 boolean mInputMethodTargetWaitingAnim; 489 int mInputMethodAnimLayerAdjustment; 490 491 WindowState mInputMethodWindow = null; 492 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>(); 493 494 boolean mHardKeyboardAvailable; 495 boolean mHardKeyboardEnabled; 496 OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; 497 498 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>(); 499 500 // If non-null, this is the currently visible window that is associated 501 // with the wallpaper. 502 WindowState mWallpaperTarget = null; 503 // If non-null, we are in the middle of animating from one wallpaper target 504 // to another, and this is the lower one in Z-order. 505 WindowState mLowerWallpaperTarget = null; 506 // If non-null, we are in the middle of animating from one wallpaper target 507 // to another, and this is the higher one in Z-order. 508 WindowState mUpperWallpaperTarget = null; 509 int mWallpaperAnimLayerAdjustment; 510 float mLastWallpaperX = -1; 511 float mLastWallpaperY = -1; 512 float mLastWallpaperXStep = -1; 513 float mLastWallpaperYStep = -1; 514 // This is set when we are waiting for a wallpaper to tell us it is done 515 // changing its scroll position. 516 WindowState mWaitingOnWallpaper; 517 // The last time we had a timeout when waiting for a wallpaper. 518 long mLastWallpaperTimeoutTime; 519 // We give a wallpaper up to 150ms to finish scrolling. 520 static final long WALLPAPER_TIMEOUT = 150; 521 // Time we wait after a timeout before trying to wait again. 522 static final long WALLPAPER_TIMEOUT_RECOVERY = 10000; 523 524 AppWindowToken mFocusedApp = null; 525 526 PowerManagerService mPowerManager; 527 528 float mWindowAnimationScale = 1.0f; 529 float mTransitionAnimationScale = 1.0f; 530 float mAnimatorDurationScale = 1.0f; 531 532 final InputManagerService mInputManager; 533 final DisplayManagerService mDisplayManagerService; 534 final DisplayManager mDisplayManager; 535 536 // Who is holding the screen on. 537 Session mHoldingScreenOn; 538 PowerManager.WakeLock mHoldingScreenWakeLock; 539 540 boolean mTurnOnScreen; 541 542 DragState mDragState = null; 543 544 /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple 545 * methods. */ 546 class LayoutFields { 547 static final int SET_UPDATE_ROTATION = 1 << 0; 548 static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1; 549 static final int SET_FORCE_HIDING_CHANGED = 1 << 2; 550 static final int SET_ORIENTATION_CHANGE_COMPLETE = 1 << 3; 551 static final int SET_TURN_ON_SCREEN = 1 << 4; 552 static final int SET_WALLPAPER_ACTION_PENDING = 1 << 5; 553 554 boolean mWallpaperForceHidingChanged = false; 555 boolean mWallpaperMayChange = false; 556 boolean mOrientationChangeComplete = true; 557 private Session mHoldScreen = null; 558 private boolean mObscured = false; 559 boolean mDimming = false; 560 private boolean mSyswin = false; 561 private float mScreenBrightness = -1; 562 private float mButtonBrightness = -1; 563 private long mUserActivityTimeout = -1; 564 private boolean mUpdateRotation = false; 565 boolean mWallpaperActionPending = false; 566 567 private static final int DISPLAY_CONTENT_UNKNOWN = 0; 568 private static final int DISPLAY_CONTENT_MIRROR = 1; 569 private static final int DISPLAY_CONTENT_UNIQUE = 2; 570 private int mDisplayHasContent = DISPLAY_CONTENT_UNKNOWN; 571 } 572 final LayoutFields mInnerFields = new LayoutFields(); 573 574 static class AppWindowAnimParams { 575 AppWindowAnimator mAppAnimator; 576 ArrayList<WindowStateAnimator> mWinAnimators; 577 578 public AppWindowAnimParams(final AppWindowAnimator appAnimator) { 579 mAppAnimator = appAnimator; 580 581 final AppWindowToken atoken = appAnimator.mAppToken; 582 mWinAnimators = new ArrayList<WindowStateAnimator>(); 583 final int N = atoken.allAppWindows.size(); 584 for (int i = 0; i < N; i++) { 585 mWinAnimators.add(atoken.allAppWindows.get(i).mWinAnimator); 586 } 587 } 588 } 589 590 boolean mAnimationScheduled; 591 592 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this 593 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */ 594 private int mTransactionSequence; 595 596 /** Only do a maximum of 6 repeated layouts. After that quit */ 597 private int mLayoutRepeatCount; 598 599 final WindowAnimator mAnimator; 600 601 final class DragInputEventReceiver extends InputEventReceiver { 602 public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { 603 super(inputChannel, looper); 604 } 605 606 @Override 607 public void onInputEvent(InputEvent event) { 608 boolean handled = false; 609 try { 610 if (event instanceof MotionEvent 611 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0 612 && mDragState != null) { 613 final MotionEvent motionEvent = (MotionEvent)event; 614 boolean endDrag = false; 615 final float newX = motionEvent.getRawX(); 616 final float newY = motionEvent.getRawY(); 617 618 switch (motionEvent.getAction()) { 619 case MotionEvent.ACTION_DOWN: { 620 if (DEBUG_DRAG) { 621 Slog.w(TAG, "Unexpected ACTION_DOWN in drag layer"); 622 } 623 } break; 624 625 case MotionEvent.ACTION_MOVE: { 626 synchronized (mWindowMap) { 627 // move the surface and tell the involved window(s) where we are 628 mDragState.notifyMoveLw(newX, newY); 629 } 630 } break; 631 632 case MotionEvent.ACTION_UP: { 633 if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at " 634 + newX + "," + newY); 635 synchronized (mWindowMap) { 636 endDrag = mDragState.notifyDropLw(newX, newY); 637 } 638 } break; 639 640 case MotionEvent.ACTION_CANCEL: { 641 if (DEBUG_DRAG) Slog.d(TAG, "Drag cancelled!"); 642 endDrag = true; 643 } break; 644 } 645 646 if (endDrag) { 647 if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state"); 648 // tell all the windows that the drag has ended 649 synchronized (mWindowMap) { 650 mDragState.endDragLw(); 651 } 652 } 653 654 handled = true; 655 } 656 } catch (Exception e) { 657 Slog.e(TAG, "Exception caught by drag handleMotion", e); 658 } finally { 659 finishInputEvent(event, handled); 660 } 661 } 662 } 663 664 /** 665 * Whether the UI is currently running in touch mode (not showing 666 * navigational focus because the user is directly pressing the screen). 667 */ 668 boolean mInTouchMode = true; 669 670 private ViewServer mViewServer; 671 private ArrayList<WindowChangeListener> mWindowChangeListeners = 672 new ArrayList<WindowChangeListener>(); 673 private boolean mWindowsChanged = false; 674 675 public interface WindowChangeListener { 676 public void windowsChanged(); 677 public void focusChanged(); 678 } 679 680 final Configuration mTempConfiguration = new Configuration(); 681 682 // The desired scaling factor for compatible apps. 683 float mCompatibleScreenScale; 684 685 // If true, only the core apps and services are being launched because the device 686 // is in a special boot mode, such as being encrypted or waiting for a decryption password. 687 // For example, when this flag is true, there will be no wallpaper service. 688 final boolean mOnlyCore; 689 690 public static WindowManagerService main(final Context context, 691 final PowerManagerService pm, final DisplayManagerService dm, 692 final InputManagerService im, 693 final Handler uiHandler, final Handler wmHandler, 694 final boolean haveInputMethods, final boolean showBootMsgs, 695 final boolean onlyCore) { 696 final WindowManagerService[] holder = new WindowManagerService[1]; 697 wmHandler.runWithScissors(new Runnable() { 698 @Override 699 public void run() { 700 holder[0] = new WindowManagerService(context, pm, dm, im, 701 uiHandler, haveInputMethods, showBootMsgs, onlyCore); 702 } 703 }, 0); 704 return holder[0]; 705 } 706 707 private void initPolicy(Handler uiHandler) { 708 uiHandler.runWithScissors(new Runnable() { 709 @Override 710 public void run() { 711 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper()); 712 713 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this); 714 mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer() 715 * TYPE_LAYER_MULTIPLIER 716 + TYPE_LAYER_OFFSET; 717 } 718 }, 0); 719 } 720 721 private WindowManagerService(Context context, PowerManagerService pm, 722 DisplayManagerService displayManager, InputManagerService inputManager, 723 Handler uiHandler, 724 boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) { 725 mContext = context; 726 mHaveInputMethods = haveInputMethods; 727 mAllowBootMessages = showBootMsgs; 728 mOnlyCore = onlyCore; 729 mLimitedAlphaCompositing = context.getResources().getBoolean( 730 com.android.internal.R.bool.config_sf_limitedAlpha); 731 mDisplayManagerService = displayManager; 732 mHeadless = displayManager.isHeadless(); 733 734 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); 735 mDisplayManager.registerDisplayListener(this, null); 736 Display[] displays = mDisplayManager.getDisplays(); 737 for (Display display : displays) { 738 createDisplayContentLocked(display); 739 } 740 741 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy); 742 743 mPowerManager = pm; 744 mPowerManager.setPolicy(mPolicy); 745 PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 746 mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN"); 747 mScreenFrozenLock.setReferenceCounted(false); 748 749 mAppTransition = new AppTransition(context, mH); 750 751 mActivityManager = ActivityManagerNative.getDefault(); 752 mBatteryStats = BatteryStatsService.getService(); 753 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 754 mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null, 755 new AppOpsManager.Callback() { 756 @Override 757 public void opChanged(int op, String packageName) { 758 updateAppOpsState(); 759 } 760 } 761 ); 762 763 // Get persisted window scale setting 764 mWindowAnimationScale = Settings.Global.getFloat(context.getContentResolver(), 765 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); 766 mTransitionAnimationScale = Settings.Global.getFloat(context.getContentResolver(), 767 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); 768 setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(), 769 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale)); 770 771 // Track changes to DevicePolicyManager state so we can enable/disable keyguard. 772 IntentFilter filter = new IntentFilter(); 773 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 774 mContext.registerReceiver(mBroadcastReceiver, filter); 775 776 mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK 777 | PowerManager.ON_AFTER_RELEASE, TAG); 778 mHoldingScreenWakeLock.setReferenceCounted(false); 779 780 mInputManager = inputManager; 781 mFxSession = new SurfaceSession(); 782 mAnimator = new WindowAnimator(this); 783 784 initPolicy(uiHandler); 785 786 // Add ourself to the Watchdog monitors. 787 Watchdog.getInstance().addMonitor(this); 788 789 Surface.openTransaction(); 790 try { 791 createWatermarkInTransaction(); 792 } finally { 793 Surface.closeTransaction(); 794 } 795 } 796 797 public InputMonitor getInputMonitor() { 798 return mInputMonitor; 799 } 800 801 @Override 802 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 803 throws RemoteException { 804 try { 805 return super.onTransact(code, data, reply, flags); 806 } catch (RuntimeException e) { 807 // The window manager only throws security exceptions, so let's 808 // log all others. 809 if (!(e instanceof SecurityException)) { 810 Log.wtf(TAG, "Window Manager Crash", e); 811 } 812 throw e; 813 } 814 } 815 816 private void placeWindowAfter(WindowState pos, WindowState window) { 817 final WindowList windows = pos.getWindowList(); 818 final int i = windows.indexOf(pos); 819 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 820 TAG, "Adding window " + window + " at " 821 + (i+1) + " of " + windows.size() + " (after " + pos + ")"); 822 windows.add(i+1, window); 823 mWindowsChanged = true; 824 } 825 826 private void placeWindowBefore(WindowState pos, WindowState window) { 827 final WindowList windows = pos.getWindowList(); 828 final int i = windows.indexOf(pos); 829 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 830 TAG, "Adding window " + window + " at " 831 + i + " of " + windows.size() + " (before " + pos + ")"); 832 windows.add(i, window); 833 mWindowsChanged = true; 834 } 835 836 //This method finds out the index of a window that has the same app token as 837 //win. used for z ordering the windows in mWindows 838 private int findIdxBasedOnAppTokens(WindowState win) { 839 WindowList windows = win.getWindowList(); 840 for(int j = windows.size() - 1; j >= 0; j--) { 841 WindowState wentry = windows.get(j); 842 if(wentry.mAppToken == win.mAppToken) { 843 return j; 844 } 845 } 846 return -1; 847 } 848 849 /** 850 * Return the list of Windows from the passed token on the given Display. 851 * @param token The token with all the windows. 852 * @param displayContent The display we are interested in. 853 * @return List of windows from token that are on displayContent. 854 */ 855 WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) { 856 final WindowList windowList = new WindowList(); 857 final int count = token.windows.size(); 858 for (int i = 0; i < count; i++) { 859 final WindowState win = token.windows.get(i); 860 if (win.mDisplayContent == displayContent) { 861 windowList.add(win); 862 } 863 } 864 return windowList; 865 } 866 867 /** 868 * Recursive search through a WindowList and all of its windows' children. 869 * @param targetWin The window to search for. 870 * @param windows The list to search. 871 * @return The index of win in windows or of the window that is an ancestor of win. 872 */ 873 private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) { 874 for (int i = windows.size() - 1; i >= 0; i--) { 875 final WindowState w = windows.get(i); 876 if (w == targetWin) { 877 return i; 878 } 879 if (!w.mChildWindows.isEmpty()) { 880 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) { 881 return i; 882 } 883 } 884 } 885 return -1; 886 } 887 888 private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) { 889 final IWindow client = win.mClient; 890 final WindowToken token = win.mToken; 891 final DisplayContent displayContent = win.mDisplayContent; 892 893 final WindowList windows = win.getWindowList(); 894 final int N = windows.size(); 895 final WindowState attached = win.mAttachedWindow; 896 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 897 if (attached == null) { 898 int tokenWindowsPos = 0; 899 int windowListPos = tokenWindowList.size(); 900 if (token.appWindowToken != null) { 901 int index = windowListPos - 1; 902 if (index >= 0) { 903 // If this application has existing windows, we 904 // simply place the new window on top of them... but 905 // keep the starting window on top. 906 if (win.mAttrs.type == TYPE_BASE_APPLICATION) { 907 // Base windows go behind everything else. 908 WindowState lowestWindow = tokenWindowList.get(0); 909 placeWindowBefore(lowestWindow, win); 910 tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows); 911 } else { 912 AppWindowToken atoken = win.mAppToken; 913 WindowState lastWindow = tokenWindowList.get(index); 914 if (atoken != null && lastWindow == atoken.startingWindow) { 915 placeWindowBefore(lastWindow, win); 916 tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows); 917 } else { 918 int newIdx = findIdxBasedOnAppTokens(win); 919 //there is a window above this one associated with the same 920 //apptoken note that the window could be a floating window 921 //that was created later or a window at the top of the list of 922 //windows associated with this token. 923 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) { 924 Slog.v(TAG, "Adding window " + win + " at " 925 + (newIdx + 1) + " of " + N); 926 } 927 windows.add(newIdx + 1, win); 928 if (newIdx < 0) { 929 // No window from token found on win's display. 930 tokenWindowsPos = 0; 931 } else { 932 tokenWindowsPos = indexOfWinInWindowList( 933 windows.get(newIdx), token.windows) + 1; 934 } 935 mWindowsChanged = true; 936 } 937 } 938 } else { 939 // No windows from this token on this display 940 if (localLOGV) Slog.v( 941 TAG, "Figuring out where to add app window " 942 + client.asBinder() + " (token=" + token + ")"); 943 // Figure out where the window should go, based on the 944 // order of applications. 945 WindowState pos = null; 946 AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR); 947 while (iterator.hasNext()) { 948 AppWindowToken t = iterator.next(); 949 if (t == token) { 950 break; 951 } 952 953 // We haven't reached the token yet; if this token 954 // is not going to the bottom and has windows on this display, we can 955 // use it as an anchor for when we do reach the token. 956 tokenWindowList = getTokenWindowsOnDisplay(t, win.mDisplayContent); 957 if (!t.sendingToBottom && tokenWindowList.size() > 0) { 958 pos = tokenWindowList.get(0); 959 } 960 } 961 // We now know the index into the apps. If we found 962 // an app window above, that gives us the position; else 963 // we need to look some more. 964 if (pos != null) { 965 // Move behind any windows attached to this one. 966 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 967 if (atoken != null) { 968 tokenWindowList = 969 getTokenWindowsOnDisplay(atoken, win.mDisplayContent); 970 final int NC = tokenWindowList.size(); 971 if (NC > 0) { 972 WindowState bottom = tokenWindowList.get(0); 973 if (bottom.mSubLayer < 0) { 974 pos = bottom; 975 } 976 } 977 } 978 placeWindowBefore(pos, win); 979 } else { 980 // Continue looking down until we find the first 981 // token that has windows on this display. 982 while (iterator.hasNext()) { 983 AppWindowToken t = iterator.next(); 984 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 985 final int NW = tokenWindowList.size(); 986 if (NW > 0) { 987 pos = tokenWindowList.get(NW-1); 988 break; 989 } 990 } 991 if (pos != null) { 992 // Move in front of any windows attached to this 993 // one. 994 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 995 if (atoken != null) { 996 final int NC = atoken.windows.size(); 997 if (NC > 0) { 998 WindowState top = atoken.windows.get(NC-1); 999 if (top.mSubLayer >= 0) { 1000 pos = top; 1001 } 1002 } 1003 } 1004 placeWindowAfter(pos, win); 1005 } else { 1006 // Just search for the start of this layer. 1007 final int myLayer = win.mBaseLayer; 1008 int i; 1009 for (i = 0; i < N; i++) { 1010 WindowState w = windows.get(i); 1011 if (w.mBaseLayer > myLayer) { 1012 break; 1013 } 1014 } 1015 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) { 1016 Slog.v(TAG, "Adding window " + win + " at " 1017 + i + " of " + N); 1018 } 1019 windows.add(i, win); 1020 mWindowsChanged = true; 1021 } 1022 } 1023 } 1024 } else { 1025 // Figure out where window should go, based on layer. 1026 final int myLayer = win.mBaseLayer; 1027 int i; 1028 for (i = N - 1; i >= 0; i--) { 1029 if (windows.get(i).mBaseLayer <= myLayer) { 1030 break; 1031 } 1032 } 1033 i++; 1034 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 1035 TAG, "Adding window " + win + " at " 1036 + i + " of " + N); 1037 windows.add(i, win); 1038 mWindowsChanged = true; 1039 } 1040 1041 if (addToToken) { 1042 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1043 token.windows.add(tokenWindowsPos, win); 1044 } 1045 1046 } else { 1047 // Figure out this window's ordering relative to the window 1048 // it is attached to. 1049 final int NA = tokenWindowList.size(); 1050 final int sublayer = win.mSubLayer; 1051 int largestSublayer = Integer.MIN_VALUE; 1052 WindowState windowWithLargestSublayer = null; 1053 int i; 1054 for (i = 0; i < NA; i++) { 1055 WindowState w = tokenWindowList.get(i); 1056 final int wSublayer = w.mSubLayer; 1057 if (wSublayer >= largestSublayer) { 1058 largestSublayer = wSublayer; 1059 windowWithLargestSublayer = w; 1060 } 1061 if (sublayer < 0) { 1062 // For negative sublayers, we go below all windows 1063 // in the same sublayer. 1064 if (wSublayer >= sublayer) { 1065 if (addToToken) { 1066 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1067 token.windows.add(i, win); 1068 } 1069 placeWindowBefore(wSublayer >= 0 ? attached : w, win); 1070 break; 1071 } 1072 } else { 1073 // For positive sublayers, we go above all windows 1074 // in the same sublayer. 1075 if (wSublayer > sublayer) { 1076 if (addToToken) { 1077 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1078 token.windows.add(i, win); 1079 } 1080 placeWindowBefore(w, win); 1081 break; 1082 } 1083 } 1084 } 1085 if (i >= NA) { 1086 if (addToToken) { 1087 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1088 token.windows.add(win); 1089 } 1090 if (sublayer < 0) { 1091 placeWindowBefore(attached, win); 1092 } else { 1093 placeWindowAfter(largestSublayer >= 0 1094 ? windowWithLargestSublayer 1095 : attached, 1096 win); 1097 } 1098 } 1099 } 1100 1101 if (win.mAppToken != null && addToToken) { 1102 win.mAppToken.allAppWindows.add(win); 1103 } 1104 } 1105 1106 static boolean canBeImeTarget(WindowState w) { 1107 final int fl = w.mAttrs.flags 1108 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); 1109 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM) 1110 || w.mAttrs.type == TYPE_APPLICATION_STARTING) { 1111 if (DEBUG_INPUT_METHOD) { 1112 Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding()); 1113 if (!w.isVisibleOrAdding()) { 1114 Slog.i(TAG, " mSurface=" + w.mWinAnimator.mSurface 1115 + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility 1116 + " policyVis=" + w.mPolicyVisibility 1117 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim 1118 + " attachHid=" + w.mAttachedHidden 1119 + " exiting=" + w.mExiting + " destroying=" + w.mDestroying); 1120 if (w.mAppToken != null) { 1121 Slog.i(TAG, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested); 1122 } 1123 } 1124 } 1125 return w.isVisibleOrAdding(); 1126 } 1127 return false; 1128 } 1129 1130 /** 1131 * Dig through the WindowStates and find the one that the Input Method will target. 1132 * @param willMove 1133 * @return The index+1 in mWindows of the discovered target. 1134 */ 1135 int findDesiredInputMethodWindowIndexLocked(boolean willMove) { 1136 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the 1137 // same display. Or even when the current IME/target are not on the same screen as the next 1138 // IME/target. For now only look for input windows on the main screen. 1139 WindowList windows = getDefaultWindowListLocked(); 1140 final int N = windows.size(); 1141 WindowState w = null; 1142 int i = N; 1143 while (i > 0) { 1144 i--; 1145 w = windows.get(i); 1146 1147 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i 1148 + " " + w + " fl=0x" + Integer.toHexString(w.mAttrs.flags)); 1149 if (canBeImeTarget(w)) { 1150 //Slog.i(TAG, "Putting input method here!"); 1151 1152 // Yet more tricksyness! If this window is a "starting" 1153 // window, we do actually want to be on top of it, but 1154 // it is not -really- where input will go. So if the caller 1155 // is not actually looking to move the IME, look down below 1156 // for a real window to target... 1157 if (!willMove 1158 && w.mAttrs.type == TYPE_APPLICATION_STARTING 1159 && i > 0) { 1160 WindowState wb = windows.get(i-1); 1161 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) { 1162 i--; 1163 w = wb; 1164 } 1165 } 1166 break; 1167 } 1168 } 1169 1170 // Now w is either mWindows[0] or an IME (or null if mWindows is empty). 1171 1172 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w); 1173 1174 // Now, a special case -- if the last target's window is in the 1175 // process of exiting, and is above the new target, keep on the 1176 // last target to avoid flicker. Consider for example a Dialog with 1177 // the IME shown: when the Dialog is dismissed, we want to keep 1178 // the IME above it until it is completely gone so it doesn't drop 1179 // behind the dialog or its full-screen scrim. 1180 final WindowState curTarget = mInputMethodTarget; 1181 if (curTarget != null && w != null 1182 && curTarget.isDisplayedLw() 1183 && curTarget.isClosing() 1184 && (curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) { 1185 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing"); 1186 return windows.indexOf(curTarget) + 1; 1187 } 1188 1189 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target=" 1190 + w + " willMove=" + willMove); 1191 1192 if (willMove && w != null) { 1193 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken; 1194 if (token != null) { 1195 1196 // Now some fun for dealing with window animations that 1197 // modify the Z order. We need to look at all windows below 1198 // the current target that are in this app, finding the highest 1199 // visible one in layering. 1200 WindowState highestTarget = null; 1201 int highestPos = 0; 1202 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) { 1203 WindowList curWindows = curTarget.getWindowList(); 1204 int pos = curWindows.indexOf(curTarget); 1205 while (pos >= 0) { 1206 WindowState win = curWindows.get(pos); 1207 if (win.mAppToken != token) { 1208 break; 1209 } 1210 if (!win.mRemoved) { 1211 if (highestTarget == null || win.mWinAnimator.mAnimLayer > 1212 highestTarget.mWinAnimator.mAnimLayer) { 1213 highestTarget = win; 1214 highestPos = pos; 1215 } 1216 } 1217 pos--; 1218 } 1219 } 1220 1221 if (highestTarget != null) { 1222 if (DEBUG_INPUT_METHOD) Slog.v(TAG, mAppTransition + " " + highestTarget 1223 + " animating=" + highestTarget.mWinAnimator.isAnimating() 1224 + " layer=" + highestTarget.mWinAnimator.mAnimLayer 1225 + " new layer=" + w.mWinAnimator.mAnimLayer); 1226 1227 if (mAppTransition.isTransitionSet()) { 1228 // If we are currently setting up for an animation, 1229 // hold everything until we can find out what will happen. 1230 mInputMethodTargetWaitingAnim = true; 1231 mInputMethodTarget = highestTarget; 1232 return highestPos + 1; 1233 } else if (highestTarget.mWinAnimator.isAnimating() && 1234 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) { 1235 // If the window we are currently targeting is involved 1236 // with an animation, and it is on top of the next target 1237 // we will be over, then hold off on moving until 1238 // that is done. 1239 mInputMethodTargetWaitingAnim = true; 1240 mInputMethodTarget = highestTarget; 1241 return highestPos + 1; 1242 } 1243 } 1244 } 1245 } 1246 1247 //Slog.i(TAG, "Placing input method @" + (i+1)); 1248 if (w != null) { 1249 if (willMove) { 1250 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to " 1251 + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4))); 1252 mInputMethodTarget = w; 1253 mInputMethodTargetWaitingAnim = false; 1254 if (w.mAppToken != null) { 1255 setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment); 1256 } else { 1257 setInputMethodAnimLayerAdjustment(0); 1258 } 1259 } 1260 return i+1; 1261 } 1262 if (willMove) { 1263 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null." 1264 + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4))); 1265 mInputMethodTarget = null; 1266 setInputMethodAnimLayerAdjustment(0); 1267 } 1268 return -1; 1269 } 1270 1271 void addInputMethodWindowToListLocked(WindowState win) { 1272 int pos = findDesiredInputMethodWindowIndexLocked(true); 1273 if (pos >= 0) { 1274 win.mTargetAppToken = mInputMethodTarget.mAppToken; 1275 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 1276 TAG, "Adding input method window " + win + " at " + pos); 1277 // TODO(multidisplay): IMEs are only supported on the default display. 1278 getDefaultWindowListLocked().add(pos, win); 1279 mWindowsChanged = true; 1280 moveInputMethodDialogsLocked(pos+1); 1281 return; 1282 } 1283 win.mTargetAppToken = null; 1284 addWindowToListInOrderLocked(win, true); 1285 moveInputMethodDialogsLocked(pos); 1286 } 1287 1288 void setInputMethodAnimLayerAdjustment(int adj) { 1289 if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj); 1290 mInputMethodAnimLayerAdjustment = adj; 1291 WindowState imw = mInputMethodWindow; 1292 if (imw != null) { 1293 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj; 1294 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw 1295 + " anim layer: " + imw.mWinAnimator.mAnimLayer); 1296 int wi = imw.mChildWindows.size(); 1297 while (wi > 0) { 1298 wi--; 1299 WindowState cw = imw.mChildWindows.get(wi); 1300 cw.mWinAnimator.mAnimLayer = cw.mLayer + adj; 1301 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw 1302 + " anim layer: " + cw.mWinAnimator.mAnimLayer); 1303 } 1304 } 1305 int di = mInputMethodDialogs.size(); 1306 while (di > 0) { 1307 di --; 1308 imw = mInputMethodDialogs.get(di); 1309 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj; 1310 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw 1311 + " anim layer: " + imw.mWinAnimator.mAnimLayer); 1312 } 1313 } 1314 1315 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) { 1316 WindowList windows = win.getWindowList(); 1317 int wpos = windows.indexOf(win); 1318 if (wpos >= 0) { 1319 if (wpos < interestingPos) interestingPos--; 1320 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win); 1321 windows.remove(wpos); 1322 mWindowsChanged = true; 1323 int NC = win.mChildWindows.size(); 1324 while (NC > 0) { 1325 NC--; 1326 WindowState cw = win.mChildWindows.get(NC); 1327 int cpos = windows.indexOf(cw); 1328 if (cpos >= 0) { 1329 if (cpos < interestingPos) interestingPos--; 1330 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at " 1331 + cpos + ": " + cw); 1332 windows.remove(cpos); 1333 } 1334 } 1335 } 1336 return interestingPos; 1337 } 1338 1339 private void reAddWindowToListInOrderLocked(WindowState win) { 1340 addWindowToListInOrderLocked(win, false); 1341 // This is a hack to get all of the child windows added as well 1342 // at the right position. Child windows should be rare and 1343 // this case should be rare, so it shouldn't be that big a deal. 1344 WindowList windows = win.getWindowList(); 1345 int wpos = windows.indexOf(win); 1346 if (wpos >= 0) { 1347 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win); 1348 windows.remove(wpos); 1349 mWindowsChanged = true; 1350 reAddWindowLocked(wpos, win); 1351 } 1352 } 1353 1354 void logWindowList(final WindowList windows, String prefix) { 1355 int N = windows.size(); 1356 while (N > 0) { 1357 N--; 1358 Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N)); 1359 } 1360 } 1361 1362 void moveInputMethodDialogsLocked(int pos) { 1363 ArrayList<WindowState> dialogs = mInputMethodDialogs; 1364 1365 // TODO(multidisplay): IMEs are only supported on the default display. 1366 WindowList windows = getDefaultWindowListLocked(); 1367 final int N = dialogs.size(); 1368 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos); 1369 for (int i=0; i<N; i++) { 1370 pos = tmpRemoveWindowLocked(pos, dialogs.get(i)); 1371 } 1372 if (DEBUG_INPUT_METHOD) { 1373 Slog.v(TAG, "Window list w/pos=" + pos); 1374 logWindowList(windows, " "); 1375 } 1376 1377 if (pos >= 0) { 1378 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken; 1379 if (pos < windows.size()) { 1380 WindowState wp = windows.get(pos); 1381 if (wp == mInputMethodWindow) { 1382 pos++; 1383 } 1384 } 1385 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos); 1386 for (int i=0; i<N; i++) { 1387 WindowState win = dialogs.get(i); 1388 win.mTargetAppToken = targetAppToken; 1389 pos = reAddWindowLocked(pos, win); 1390 } 1391 if (DEBUG_INPUT_METHOD) { 1392 Slog.v(TAG, "Final window list:"); 1393 logWindowList(windows, " "); 1394 } 1395 return; 1396 } 1397 for (int i=0; i<N; i++) { 1398 WindowState win = dialogs.get(i); 1399 win.mTargetAppToken = null; 1400 reAddWindowToListInOrderLocked(win); 1401 if (DEBUG_INPUT_METHOD) { 1402 Slog.v(TAG, "No IM target, final list:"); 1403 logWindowList(windows, " "); 1404 } 1405 } 1406 } 1407 1408 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) { 1409 final WindowState imWin = mInputMethodWindow; 1410 final int DN = mInputMethodDialogs.size(); 1411 if (imWin == null && DN == 0) { 1412 return false; 1413 } 1414 1415 // TODO(multidisplay): IMEs are only supported on the default display. 1416 WindowList windows = getDefaultWindowListLocked(); 1417 1418 int imPos = findDesiredInputMethodWindowIndexLocked(true); 1419 if (imPos >= 0) { 1420 // In this case, the input method windows are to be placed 1421 // immediately above the window they are targeting. 1422 1423 // First check to see if the input method windows are already 1424 // located here, and contiguous. 1425 final int N = windows.size(); 1426 WindowState firstImWin = imPos < N 1427 ? windows.get(imPos) : null; 1428 1429 // Figure out the actual input method window that should be 1430 // at the bottom of their stack. 1431 WindowState baseImWin = imWin != null 1432 ? imWin : mInputMethodDialogs.get(0); 1433 if (baseImWin.mChildWindows.size() > 0) { 1434 WindowState cw = baseImWin.mChildWindows.get(0); 1435 if (cw.mSubLayer < 0) baseImWin = cw; 1436 } 1437 1438 if (firstImWin == baseImWin) { 1439 // The windows haven't moved... but are they still contiguous? 1440 // First find the top IM window. 1441 int pos = imPos+1; 1442 while (pos < N) { 1443 if (!(windows.get(pos)).mIsImWindow) { 1444 break; 1445 } 1446 pos++; 1447 } 1448 pos++; 1449 // Now there should be no more input method windows above. 1450 while (pos < N) { 1451 if ((windows.get(pos)).mIsImWindow) { 1452 break; 1453 } 1454 pos++; 1455 } 1456 if (pos >= N) { 1457 // All is good! 1458 return false; 1459 } 1460 } 1461 1462 if (imWin != null) { 1463 if (DEBUG_INPUT_METHOD) { 1464 Slog.v(TAG, "Moving IM from " + imPos); 1465 logWindowList(windows, " "); 1466 } 1467 imPos = tmpRemoveWindowLocked(imPos, imWin); 1468 if (DEBUG_INPUT_METHOD) { 1469 Slog.v(TAG, "List after removing with new pos " + imPos + ":"); 1470 logWindowList(windows, " "); 1471 } 1472 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1473 reAddWindowLocked(imPos, imWin); 1474 if (DEBUG_INPUT_METHOD) { 1475 Slog.v(TAG, "List after moving IM to " + imPos + ":"); 1476 logWindowList(windows, " "); 1477 } 1478 if (DN > 0) moveInputMethodDialogsLocked(imPos+1); 1479 } else { 1480 moveInputMethodDialogsLocked(imPos); 1481 } 1482 1483 } else { 1484 // In this case, the input method windows go in a fixed layer, 1485 // because they aren't currently associated with a focus window. 1486 1487 if (imWin != null) { 1488 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos); 1489 tmpRemoveWindowLocked(0, imWin); 1490 imWin.mTargetAppToken = null; 1491 reAddWindowToListInOrderLocked(imWin); 1492 if (DEBUG_INPUT_METHOD) { 1493 Slog.v(TAG, "List with no IM target:"); 1494 logWindowList(windows, " "); 1495 } 1496 if (DN > 0) moveInputMethodDialogsLocked(-1); 1497 } else { 1498 moveInputMethodDialogsLocked(-1); 1499 } 1500 1501 } 1502 1503 if (needAssignLayers) { 1504 assignLayersLocked(windows); 1505 } 1506 1507 return true; 1508 } 1509 1510 void adjustInputMethodDialogsLocked() { 1511 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true)); 1512 } 1513 1514 final boolean isWallpaperVisible(WindowState wallpaperTarget) { 1515 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured=" 1516 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??") 1517 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null) 1518 ? wallpaperTarget.mAppToken.mAppAnimator.animation : null) 1519 + " upper=" + mUpperWallpaperTarget 1520 + " lower=" + mLowerWallpaperTarget); 1521 return (wallpaperTarget != null 1522 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null 1523 && wallpaperTarget.mAppToken.mAppAnimator.animation != null))) 1524 || mUpperWallpaperTarget != null 1525 || mLowerWallpaperTarget != null; 1526 } 1527 1528 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1; 1529 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2; 1530 1531 int adjustWallpaperWindowsLocked() { 1532 mInnerFields.mWallpaperMayChange = false; 1533 boolean targetChanged = false; 1534 1535 // TODO(multidisplay): Wallpapers on main screen only. 1536 final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo(); 1537 final int dw = displayInfo.appWidth; 1538 final int dh = displayInfo.appHeight; 1539 1540 // First find top-most window that has asked to be on top of the 1541 // wallpaper; all wallpapers go behind it. 1542 final WindowList windows = getDefaultWindowListLocked(); 1543 int N = windows.size(); 1544 WindowState w = null; 1545 WindowState foundW = null; 1546 int foundI = 0; 1547 WindowState topCurW = null; 1548 int topCurI = 0; 1549 int windowDetachedI = -1; 1550 int i = N; 1551 while (i > 0) { 1552 i--; 1553 w = windows.get(i); 1554 if ((w.mAttrs.type == TYPE_WALLPAPER)) { 1555 if (topCurW == null) { 1556 topCurW = w; 1557 topCurI = i; 1558 } 1559 continue; 1560 } 1561 topCurW = null; 1562 if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) { 1563 // If this window's app token is hidden and not animating, 1564 // it is of no interest to us. 1565 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) { 1566 if (DEBUG_WALLPAPER) Slog.v(TAG, 1567 "Skipping hidden and not animating token: " + w); 1568 continue; 1569 } 1570 } 1571 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen=" 1572 + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState); 1573 if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isOnScreen() 1574 && (mWallpaperTarget == w || w.isDrawFinishedLw())) { 1575 if (DEBUG_WALLPAPER) Slog.v(TAG, 1576 "Found wallpaper target: #" + i + "=" + w); 1577 foundW = w; 1578 foundI = i; 1579 if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) { 1580 // The current wallpaper target is animating, so we'll 1581 // look behind it for another possible target and figure 1582 // out what is going on below. 1583 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w 1584 + ": token animating, looking behind."); 1585 continue; 1586 } 1587 break; 1588 } else if (w == mAnimator.mWindowDetachedWallpaper) { 1589 windowDetachedI = i; 1590 } 1591 } 1592 1593 if (foundW == null && windowDetachedI >= 0) { 1594 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 1595 "Found animating detached wallpaper activity: #" + i + "=" + w); 1596 foundW = w; 1597 foundI = windowDetachedI; 1598 } 1599 1600 if (mWallpaperTarget != foundW 1601 && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) { 1602 if (DEBUG_WALLPAPER_LIGHT) { 1603 Slog.v(TAG, "New wallpaper target: " + foundW 1604 + " oldTarget: " + mWallpaperTarget); 1605 } 1606 1607 mLowerWallpaperTarget = null; 1608 mUpperWallpaperTarget = null; 1609 1610 WindowState oldW = mWallpaperTarget; 1611 mWallpaperTarget = foundW; 1612 targetChanged = true; 1613 1614 // Now what is happening... if the current and new targets are 1615 // animating, then we are in our super special mode! 1616 if (foundW != null && oldW != null) { 1617 boolean oldAnim = oldW.isAnimatingLw(); 1618 boolean foundAnim = foundW.isAnimatingLw(); 1619 if (DEBUG_WALLPAPER_LIGHT) { 1620 Slog.v(TAG, "New animation: " + foundAnim 1621 + " old animation: " + oldAnim); 1622 } 1623 if (foundAnim && oldAnim) { 1624 int oldI = windows.indexOf(oldW); 1625 if (DEBUG_WALLPAPER_LIGHT) { 1626 Slog.v(TAG, "New i: " + foundI + " old i: " + oldI); 1627 } 1628 if (oldI >= 0) { 1629 if (DEBUG_WALLPAPER_LIGHT) { 1630 Slog.v(TAG, "Animating wallpapers: old#" + oldI 1631 + "=" + oldW + "; new#" + foundI 1632 + "=" + foundW); 1633 } 1634 1635 // Set the new target correctly. 1636 if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) { 1637 if (DEBUG_WALLPAPER_LIGHT) { 1638 Slog.v(TAG, "Old wallpaper still the target."); 1639 } 1640 mWallpaperTarget = oldW; 1641 foundW = oldW; 1642 foundI = oldI; 1643 } 1644 // Now set the upper and lower wallpaper targets 1645 // correctly, and make sure that we are positioning 1646 // the wallpaper below the lower. 1647 else if (foundI > oldI) { 1648 // The new target is on top of the old one. 1649 if (DEBUG_WALLPAPER_LIGHT) { 1650 Slog.v(TAG, "Found target above old target."); 1651 } 1652 mUpperWallpaperTarget = foundW; 1653 mLowerWallpaperTarget = oldW; 1654 foundW = oldW; 1655 foundI = oldI; 1656 } else { 1657 // The new target is below the old one. 1658 if (DEBUG_WALLPAPER_LIGHT) { 1659 Slog.v(TAG, "Found target below old target."); 1660 } 1661 mUpperWallpaperTarget = oldW; 1662 mLowerWallpaperTarget = foundW; 1663 } 1664 } 1665 } 1666 } 1667 1668 } else if (mLowerWallpaperTarget != null) { 1669 // Is it time to stop animating? 1670 if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) { 1671 if (DEBUG_WALLPAPER_LIGHT) { 1672 Slog.v(TAG, "No longer animating wallpaper targets!"); 1673 } 1674 mLowerWallpaperTarget = null; 1675 mUpperWallpaperTarget = null; 1676 mWallpaperTarget = foundW; 1677 targetChanged = true; 1678 } 1679 } 1680 1681 boolean visible = foundW != null; 1682 if (visible) { 1683 // The window is visible to the compositor... but is it visible 1684 // to the user? That is what the wallpaper cares about. 1685 visible = isWallpaperVisible(foundW); 1686 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible); 1687 1688 // If the wallpaper target is animating, we may need to copy 1689 // its layer adjustment. Only do this if we are not transfering 1690 // between two wallpaper targets. 1691 mWallpaperAnimLayerAdjustment = 1692 (mLowerWallpaperTarget == null && foundW.mAppToken != null) 1693 ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0; 1694 1695 final int maxLayer = mPolicy.getMaxWallpaperLayer() 1696 * TYPE_LAYER_MULTIPLIER 1697 + TYPE_LAYER_OFFSET; 1698 1699 // Now w is the window we are supposed to be behind... but we 1700 // need to be sure to also be behind any of its attached windows, 1701 // AND any starting window associated with it, AND below the 1702 // maximum layer the policy allows for wallpapers. 1703 while (foundI > 0) { 1704 WindowState wb = windows.get(foundI-1); 1705 if (wb.mBaseLayer < maxLayer && 1706 wb.mAttachedWindow != foundW && 1707 (foundW.mAttachedWindow == null || 1708 wb.mAttachedWindow != foundW.mAttachedWindow) && 1709 (wb.mAttrs.type != TYPE_APPLICATION_STARTING || 1710 foundW.mToken == null || wb.mToken != foundW.mToken)) { 1711 // This window is not related to the previous one in any 1712 // interesting way, so stop here. 1713 break; 1714 } 1715 foundW = wb; 1716 foundI--; 1717 } 1718 } else { 1719 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target"); 1720 } 1721 1722 if (foundW == null && topCurW != null) { 1723 // There is no wallpaper target, so it goes at the bottom. 1724 // We will assume it is the same place as last time, if known. 1725 foundW = topCurW; 1726 foundI = topCurI+1; 1727 } else { 1728 // Okay i is the position immediately above the wallpaper. Look at 1729 // what is below it for later. 1730 foundW = foundI > 0 ? windows.get(foundI-1) : null; 1731 } 1732 1733 if (visible) { 1734 if (mWallpaperTarget.mWallpaperX >= 0) { 1735 mLastWallpaperX = mWallpaperTarget.mWallpaperX; 1736 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep; 1737 } 1738 if (mWallpaperTarget.mWallpaperY >= 0) { 1739 mLastWallpaperY = mWallpaperTarget.mWallpaperY; 1740 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep; 1741 } 1742 } 1743 1744 // Start stepping backwards from here, ensuring that our wallpaper windows 1745 // are correctly placed. 1746 int changed = 0; 1747 int curTokenIndex = mWallpaperTokens.size(); 1748 while (curTokenIndex > 0) { 1749 curTokenIndex--; 1750 WindowToken token = mWallpaperTokens.get(curTokenIndex); 1751 if (token.hidden == visible) { 1752 if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, 1753 "Wallpaper token " + token + " hidden=" + !visible); 1754 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED; 1755 token.hidden = !visible; 1756 // Need to do a layout to ensure the wallpaper now has the 1757 // correct size. 1758 getDefaultDisplayContentLocked().layoutNeeded = true; 1759 } 1760 1761 int curWallpaperIndex = token.windows.size(); 1762 while (curWallpaperIndex > 0) { 1763 curWallpaperIndex--; 1764 WindowState wallpaper = token.windows.get(curWallpaperIndex); 1765 1766 if (visible) { 1767 updateWallpaperOffsetLocked(wallpaper, dw, dh, false); 1768 } 1769 1770 // First, make sure the client has the current visibility 1771 // state. 1772 dispatchWallpaperVisibility(wallpaper, visible); 1773 1774 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment; 1775 if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win " 1776 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); 1777 1778 // First, if this window is at the current index, then all 1779 // is well. 1780 if (wallpaper == foundW) { 1781 foundI--; 1782 foundW = foundI > 0 1783 ? windows.get(foundI-1) : null; 1784 continue; 1785 } 1786 1787 // The window didn't match... the current wallpaper window, 1788 // wherever it is, is in the wrong place, so make sure it is 1789 // not in the list. 1790 int oldIndex = windows.indexOf(wallpaper); 1791 if (oldIndex >= 0) { 1792 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at " 1793 + oldIndex + ": " + wallpaper); 1794 windows.remove(oldIndex); 1795 mWindowsChanged = true; 1796 if (oldIndex < foundI) { 1797 foundI--; 1798 } 1799 } 1800 1801 // Now stick it in. 1802 if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) { 1803 Slog.v(TAG, "Moving wallpaper " + wallpaper 1804 + " from " + oldIndex + " to " + foundI); 1805 } 1806 1807 windows.add(foundI, wallpaper); 1808 mWindowsChanged = true; 1809 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED; 1810 } 1811 } 1812 1813 if (targetChanged && DEBUG_WALLPAPER_LIGHT) { 1814 Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget 1815 + " lower=" + mLowerWallpaperTarget + " upper=" 1816 + mUpperWallpaperTarget); 1817 } 1818 1819 return changed; 1820 } 1821 1822 void setWallpaperAnimLayerAdjustmentLocked(int adj) { 1823 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, 1824 "Setting wallpaper layer adj to " + adj); 1825 mWallpaperAnimLayerAdjustment = adj; 1826 int curTokenIndex = mWallpaperTokens.size(); 1827 while (curTokenIndex > 0) { 1828 curTokenIndex--; 1829 WindowToken token = mWallpaperTokens.get(curTokenIndex); 1830 int curWallpaperIndex = token.windows.size(); 1831 while (curWallpaperIndex > 0) { 1832 curWallpaperIndex--; 1833 WindowState wallpaper = token.windows.get(curWallpaperIndex); 1834 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj; 1835 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win " 1836 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); 1837 } 1838 } 1839 } 1840 1841 boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh, 1842 boolean sync) { 1843 boolean changed = false; 1844 boolean rawChanged = false; 1845 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f; 1846 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f; 1847 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw; 1848 int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0; 1849 changed = wallpaperWin.mXOffset != offset; 1850 if (changed) { 1851 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " 1852 + wallpaperWin + " x: " + offset); 1853 wallpaperWin.mXOffset = offset; 1854 } 1855 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) { 1856 wallpaperWin.mWallpaperX = wpx; 1857 wallpaperWin.mWallpaperXStep = wpxs; 1858 rawChanged = true; 1859 } 1860 1861 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f; 1862 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f; 1863 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh; 1864 offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0; 1865 if (wallpaperWin.mYOffset != offset) { 1866 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " 1867 + wallpaperWin + " y: " + offset); 1868 changed = true; 1869 wallpaperWin.mYOffset = offset; 1870 } 1871 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) { 1872 wallpaperWin.mWallpaperY = wpy; 1873 wallpaperWin.mWallpaperYStep = wpys; 1874 rawChanged = true; 1875 } 1876 1877 if (rawChanged && (wallpaperWin.mAttrs.privateFlags & 1878 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) { 1879 try { 1880 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset " 1881 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX 1882 + " y=" + wallpaperWin.mWallpaperY); 1883 if (sync) { 1884 mWaitingOnWallpaper = wallpaperWin; 1885 } 1886 wallpaperWin.mClient.dispatchWallpaperOffsets( 1887 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY, 1888 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync); 1889 if (sync) { 1890 if (mWaitingOnWallpaper != null) { 1891 long start = SystemClock.uptimeMillis(); 1892 if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY) 1893 < start) { 1894 try { 1895 if (DEBUG_WALLPAPER) Slog.v(TAG, 1896 "Waiting for offset complete..."); 1897 mWindowMap.wait(WALLPAPER_TIMEOUT); 1898 } catch (InterruptedException e) { 1899 } 1900 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!"); 1901 if ((start+WALLPAPER_TIMEOUT) 1902 < SystemClock.uptimeMillis()) { 1903 Slog.i(TAG, "Timeout waiting for wallpaper to offset: " 1904 + wallpaperWin); 1905 mLastWallpaperTimeoutTime = start; 1906 } 1907 } 1908 mWaitingOnWallpaper = null; 1909 } 1910 } 1911 } catch (RemoteException e) { 1912 } 1913 } 1914 1915 return changed; 1916 } 1917 1918 void wallpaperOffsetsComplete(IBinder window) { 1919 synchronized (mWindowMap) { 1920 if (mWaitingOnWallpaper != null && 1921 mWaitingOnWallpaper.mClient.asBinder() == window) { 1922 mWaitingOnWallpaper = null; 1923 mWindowMap.notifyAll(); 1924 } 1925 } 1926 } 1927 1928 void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) { 1929 final DisplayContent displayContent = changingTarget.mDisplayContent; 1930 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 1931 final int dw = displayInfo.appWidth; 1932 final int dh = displayInfo.appHeight; 1933 1934 WindowState target = mWallpaperTarget; 1935 if (target != null) { 1936 if (target.mWallpaperX >= 0) { 1937 mLastWallpaperX = target.mWallpaperX; 1938 } else if (changingTarget.mWallpaperX >= 0) { 1939 mLastWallpaperX = changingTarget.mWallpaperX; 1940 } 1941 if (target.mWallpaperY >= 0) { 1942 mLastWallpaperY = target.mWallpaperY; 1943 } else if (changingTarget.mWallpaperY >= 0) { 1944 mLastWallpaperY = changingTarget.mWallpaperY; 1945 } 1946 } 1947 1948 int curTokenIndex = mWallpaperTokens.size(); 1949 while (curTokenIndex > 0) { 1950 curTokenIndex--; 1951 WindowToken token = mWallpaperTokens.get(curTokenIndex); 1952 int curWallpaperIndex = token.windows.size(); 1953 while (curWallpaperIndex > 0) { 1954 curWallpaperIndex--; 1955 WindowState wallpaper = token.windows.get(curWallpaperIndex); 1956 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) { 1957 WindowStateAnimator winAnimator = wallpaper.mWinAnimator; 1958 winAnimator.computeShownFrameLocked(); 1959 // No need to lay out the windows - we can just set the wallpaper position 1960 // directly. 1961 winAnimator.setWallpaperOffset(wallpaper.mShownFrame); 1962 // We only want to be synchronous with one wallpaper. 1963 sync = false; 1964 } 1965 } 1966 } 1967 } 1968 1969 /** 1970 * Check wallpaper for visiblity change and notify window if so. 1971 * @param wallpaper The wallpaper to test and notify. 1972 * @param visible Current visibility. 1973 */ 1974 void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) { 1975 if (wallpaper.mWallpaperVisible != visible) { 1976 wallpaper.mWallpaperVisible = visible; 1977 try { 1978 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 1979 "Updating vis of wallpaper " + wallpaper 1980 + ": " + visible + " from:\n" + Debug.getCallers(4, " ")); 1981 wallpaper.mClient.dispatchAppVisibility(visible); 1982 } catch (RemoteException e) { 1983 } 1984 } 1985 } 1986 1987 void updateWallpaperVisibilityLocked() { 1988 final boolean visible = isWallpaperVisible(mWallpaperTarget); 1989 final DisplayContent displayContent = mWallpaperTarget.mDisplayContent; 1990 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 1991 final int dw = displayInfo.appWidth; 1992 final int dh = displayInfo.appHeight; 1993 1994 int curTokenIndex = mWallpaperTokens.size(); 1995 while (curTokenIndex > 0) { 1996 curTokenIndex--; 1997 WindowToken token = mWallpaperTokens.get(curTokenIndex); 1998 if (token.hidden == visible) { 1999 token.hidden = !visible; 2000 // Need to do a layout to ensure the wallpaper now has the 2001 // correct size. 2002 getDefaultDisplayContentLocked().layoutNeeded = true; 2003 } 2004 2005 int curWallpaperIndex = token.windows.size(); 2006 while (curWallpaperIndex > 0) { 2007 curWallpaperIndex--; 2008 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2009 if (visible) { 2010 updateWallpaperOffsetLocked(wallpaper, dw, dh, false); 2011 } 2012 2013 dispatchWallpaperVisibility(wallpaper, visible); 2014 } 2015 } 2016 } 2017 2018 public int addWindow(Session session, IWindow client, int seq, 2019 WindowManager.LayoutParams attrs, int viewVisibility, int displayId, 2020 Rect outContentInsets, InputChannel outInputChannel) { 2021 int[] appOp = new int[1]; 2022 int res = mPolicy.checkAddPermission(attrs, appOp); 2023 if (res != WindowManagerGlobal.ADD_OKAY) { 2024 return res; 2025 } 2026 2027 boolean reportNewConfig = false; 2028 WindowState attachedWindow = null; 2029 WindowState win = null; 2030 long origId; 2031 final int type = attrs.type; 2032 2033 synchronized(mWindowMap) { 2034 if (!mDisplayReady) { 2035 throw new IllegalStateException("Display has not been initialialized"); 2036 } 2037 2038 final DisplayContent displayContent = getDisplayContentLocked(displayId); 2039 if (displayContent == null) { 2040 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2041 } 2042 2043 if (mWindowMap.containsKey(client.asBinder())) { 2044 Slog.w(TAG, "Window " + client + " is already added"); 2045 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 2046 } 2047 2048 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) { 2049 attachedWindow = windowForClientLocked(null, attrs.token, false); 2050 if (attachedWindow == null) { 2051 Slog.w(TAG, "Attempted to add window with token that is not a window: " 2052 + attrs.token + ". Aborting."); 2053 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 2054 } 2055 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW 2056 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) { 2057 Slog.w(TAG, "Attempted to add window with token that is a sub-window: " 2058 + attrs.token + ". Aborting."); 2059 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 2060 } 2061 } 2062 2063 boolean addToken = false; 2064 WindowToken token = mTokenMap.get(attrs.token); 2065 if (token == null) { 2066 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2067 Slog.w(TAG, "Attempted to add application window with unknown token " 2068 + attrs.token + ". Aborting."); 2069 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2070 } 2071 if (type == TYPE_INPUT_METHOD) { 2072 Slog.w(TAG, "Attempted to add input method window with unknown token " 2073 + attrs.token + ". Aborting."); 2074 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2075 } 2076 if (type == TYPE_WALLPAPER) { 2077 Slog.w(TAG, "Attempted to add wallpaper window with unknown token " 2078 + attrs.token + ". Aborting."); 2079 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2080 } 2081 if (type == TYPE_DREAM) { 2082 Slog.w(TAG, "Attempted to add Dream window with unknown token " 2083 + attrs.token + ". Aborting."); 2084 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2085 } 2086 token = new WindowToken(this, attrs.token, -1, false); 2087 addToken = true; 2088 } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2089 AppWindowToken atoken = token.appWindowToken; 2090 if (atoken == null) { 2091 Slog.w(TAG, "Attempted to add window with non-application token " 2092 + token + ". Aborting."); 2093 return WindowManagerGlobal.ADD_NOT_APP_TOKEN; 2094 } else if (atoken.removed) { 2095 Slog.w(TAG, "Attempted to add window with exiting application token " 2096 + token + ". Aborting."); 2097 return WindowManagerGlobal.ADD_APP_EXITING; 2098 } 2099 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) { 2100 // No need for this guy! 2101 if (localLOGV) Slog.v( 2102 TAG, "**** NO NEED TO START: " + attrs.getTitle()); 2103 return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED; 2104 } 2105 } else if (type == TYPE_INPUT_METHOD) { 2106 if (token.windowType != TYPE_INPUT_METHOD) { 2107 Slog.w(TAG, "Attempted to add input method window with bad token " 2108 + attrs.token + ". Aborting."); 2109 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2110 } 2111 } else if (type == TYPE_WALLPAPER) { 2112 if (token.windowType != TYPE_WALLPAPER) { 2113 Slog.w(TAG, "Attempted to add wallpaper window with bad token " 2114 + attrs.token + ". Aborting."); 2115 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2116 } 2117 } else if (type == TYPE_DREAM) { 2118 if (token.windowType != TYPE_DREAM) { 2119 Slog.w(TAG, "Attempted to add Dream window with bad token " 2120 + attrs.token + ". Aborting."); 2121 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2122 } 2123 } 2124 2125 win = new WindowState(this, session, client, token, 2126 attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent); 2127 if (win.mDeathRecipient == null) { 2128 // Client has apparently died, so there is no reason to 2129 // continue. 2130 Slog.w(TAG, "Adding window client " + client.asBinder() 2131 + " that is dead, aborting."); 2132 return WindowManagerGlobal.ADD_APP_EXITING; 2133 } 2134 2135 mPolicy.adjustWindowParamsLw(win.mAttrs); 2136 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs)); 2137 2138 res = mPolicy.prepareAddWindowLw(win, attrs); 2139 if (res != WindowManagerGlobal.ADD_OKAY) { 2140 return res; 2141 } 2142 2143 if (outInputChannel != null && (attrs.inputFeatures 2144 & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) { 2145 String name = win.makeInputChannelName(); 2146 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); 2147 win.setInputChannel(inputChannels[0]); 2148 inputChannels[1].transferTo(outInputChannel); 2149 2150 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle); 2151 } 2152 2153 // From now on, no exceptions or errors allowed! 2154 2155 res = WindowManagerGlobal.ADD_OKAY; 2156 2157 origId = Binder.clearCallingIdentity(); 2158 2159 if (addToken) { 2160 mTokenMap.put(attrs.token, token); 2161 } 2162 win.attach(); 2163 mWindowMap.put(client.asBinder(), win); 2164 if (win.mAppOp != AppOpsManager.OP_NONE) { 2165 if (mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage()) 2166 != AppOpsManager.MODE_ALLOWED) { 2167 win.setAppOpVisibilityLw(false); 2168 } 2169 } 2170 2171 if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) { 2172 token.appWindowToken.startingWindow = win; 2173 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken 2174 + " startingWindow=" + win); 2175 } 2176 2177 boolean imMayMove = true; 2178 2179 if (type == TYPE_INPUT_METHOD) { 2180 win.mGivenInsetsPending = true; 2181 mInputMethodWindow = win; 2182 addInputMethodWindowToListLocked(win); 2183 imMayMove = false; 2184 } else if (type == TYPE_INPUT_METHOD_DIALOG) { 2185 mInputMethodDialogs.add(win); 2186 addWindowToListInOrderLocked(win, true); 2187 adjustInputMethodDialogsLocked(); 2188 imMayMove = false; 2189 } else { 2190 addWindowToListInOrderLocked(win, true); 2191 if (type == TYPE_WALLPAPER) { 2192 mLastWallpaperTimeoutTime = 0; 2193 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2194 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2195 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2196 } else if (mWallpaperTarget != null 2197 && mWallpaperTarget.mLayer >= win.mBaseLayer) { 2198 // If there is currently a wallpaper being shown, and 2199 // the base layer of the new window is below the current 2200 // layer of the target window, then adjust the wallpaper. 2201 // This is to avoid a new window being placed between the 2202 // wallpaper and its target. 2203 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2204 } 2205 } 2206 2207 win.mWinAnimator.mEnterAnimationPending = true; 2208 2209 if (displayContent.isDefaultDisplay) { 2210 mPolicy.getContentInsetHintLw(attrs, outContentInsets); 2211 } else { 2212 outContentInsets.setEmpty(); 2213 } 2214 2215 if (mInTouchMode) { 2216 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE; 2217 } 2218 if (win.mAppToken == null || !win.mAppToken.clientHidden) { 2219 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE; 2220 } 2221 2222 mInputMonitor.setUpdateInputWindowsNeededLw(); 2223 2224 boolean focusChanged = false; 2225 if (win.canReceiveKeys()) { 2226 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, 2227 false /*updateInputWindows*/); 2228 if (focusChanged) { 2229 imMayMove = false; 2230 } 2231 } 2232 2233 if (imMayMove) { 2234 moveInputMethodWindowsIfNeededLocked(false); 2235 } 2236 2237 assignLayersLocked(displayContent.getWindowList()); 2238 // Don't do layout here, the window must call 2239 // relayout to be displayed, so we'll do it there. 2240 2241 if (focusChanged) { 2242 finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/); 2243 } 2244 mInputMonitor.updateInputWindowsLw(false /*force*/); 2245 2246 if (localLOGV) Slog.v( 2247 TAG, "New client " + client.asBinder() 2248 + ": window=" + win); 2249 2250 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) { 2251 reportNewConfig = true; 2252 } 2253 } 2254 2255 if (reportNewConfig) { 2256 sendNewConfiguration(); 2257 } 2258 2259 Binder.restoreCallingIdentity(origId); 2260 2261 return res; 2262 } 2263 2264 public void removeWindow(Session session, IWindow client) { 2265 synchronized(mWindowMap) { 2266 WindowState win = windowForClientLocked(session, client, false); 2267 if (win == null) { 2268 return; 2269 } 2270 removeWindowLocked(session, win); 2271 } 2272 } 2273 2274 public void removeWindowLocked(Session session, WindowState win) { 2275 2276 if (localLOGV || DEBUG_FOCUS) Slog.v( 2277 TAG, "Remove " + win + " client=" 2278 + Integer.toHexString(System.identityHashCode( 2279 win.mClient.asBinder())) 2280 + ", surface=" + win.mWinAnimator.mSurface); 2281 2282 final long origId = Binder.clearCallingIdentity(); 2283 2284 win.disposeInputChannel(); 2285 2286 if (DEBUG_APP_TRANSITIONS) Slog.v( 2287 TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurface 2288 + " mExiting=" + win.mExiting 2289 + " isAnimating=" + win.mWinAnimator.isAnimating() 2290 + " app-animation=" 2291 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null) 2292 + " inPendingTransaction=" 2293 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false) 2294 + " mDisplayFrozen=" + mDisplayFrozen); 2295 // Visibility of the removed window. Will be used later to update orientation later on. 2296 boolean wasVisible = false; 2297 // First, see if we need to run an animation. If we do, we have 2298 // to hold off on removing the window until the animation is done. 2299 // If the display is frozen, just remove immediately, since the 2300 // animation wouldn't be seen. 2301 if (win.mHasSurface && okToDisplay()) { 2302 // If we are not currently running the exit animation, we 2303 // need to see about starting one. 2304 wasVisible = win.isWinVisibleLw(); 2305 if (wasVisible) { 2306 2307 int transit = WindowManagerPolicy.TRANSIT_EXIT; 2308 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2309 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 2310 } 2311 // Try starting an animation. 2312 if (win.mWinAnimator.applyAnimationLocked(transit, false)) { 2313 win.mExiting = true; 2314 } 2315 //TODO (multidisplay): Magnification is supported only for the default display. 2316 if (mDisplayMagnifier != null 2317 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 2318 mDisplayMagnifier.onWindowTransitionLocked(win, transit); 2319 } 2320 } 2321 if (win.mExiting || win.mWinAnimator.isAnimating()) { 2322 // The exit animation is running... wait for it! 2323 //Slog.i(TAG, "*** Running exit animation..."); 2324 win.mExiting = true; 2325 win.mRemoveOnExit = true; 2326 win.mDisplayContent.layoutNeeded = true; 2327 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 2328 false /*updateInputWindows*/); 2329 performLayoutAndPlaceSurfacesLocked(); 2330 mInputMonitor.updateInputWindowsLw(false /*force*/); 2331 if (win.mAppToken != null) { 2332 win.mAppToken.updateReportedVisibilityLocked(); 2333 } 2334 //dump(); 2335 Binder.restoreCallingIdentity(origId); 2336 return; 2337 } 2338 } 2339 2340 removeWindowInnerLocked(session, win); 2341 // Removing a visible window will effect the computed orientation 2342 // So just update orientation if needed. 2343 if (wasVisible && updateOrientationFromAppTokensLocked(false)) { 2344 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 2345 } 2346 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 2347 Binder.restoreCallingIdentity(origId); 2348 } 2349 2350 private void removeWindowInnerLocked(Session session, WindowState win) { 2351 if (win.mRemoved) { 2352 // Nothing to do. 2353 return; 2354 } 2355 2356 for (int i=win.mChildWindows.size()-1; i>=0; i--) { 2357 WindowState cwin = win.mChildWindows.get(i); 2358 Slog.w(TAG, "Force-removing child win " + cwin + " from container " 2359 + win); 2360 removeWindowInnerLocked(cwin.mSession, cwin); 2361 } 2362 2363 win.mRemoved = true; 2364 2365 if (mInputMethodTarget == win) { 2366 moveInputMethodWindowsIfNeededLocked(false); 2367 } 2368 2369 if (false) { 2370 RuntimeException e = new RuntimeException("here"); 2371 e.fillInStackTrace(); 2372 Slog.w(TAG, "Removing window " + win, e); 2373 } 2374 2375 mPolicy.removeWindowLw(win); 2376 win.removeLocked(); 2377 2378 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win); 2379 mWindowMap.remove(win.mClient.asBinder()); 2380 if (win.mAppOp != AppOpsManager.OP_NONE) { 2381 mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage()); 2382 } 2383 2384 final WindowList windows = win.getWindowList(); 2385 windows.remove(win); 2386 mPendingRemove.remove(win); 2387 mResizingWindows.remove(win); 2388 mWindowsChanged = true; 2389 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win); 2390 2391 if (mInputMethodWindow == win) { 2392 mInputMethodWindow = null; 2393 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) { 2394 mInputMethodDialogs.remove(win); 2395 } 2396 2397 final WindowToken token = win.mToken; 2398 final AppWindowToken atoken = win.mAppToken; 2399 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token); 2400 token.windows.remove(win); 2401 if (atoken != null) { 2402 atoken.allAppWindows.remove(win); 2403 } 2404 if (localLOGV) Slog.v( 2405 TAG, "**** Removing window " + win + ": count=" 2406 + token.windows.size()); 2407 if (token.windows.size() == 0) { 2408 if (!token.explicit) { 2409 mTokenMap.remove(token.token); 2410 } else if (atoken != null) { 2411 atoken.firstWindowDrawn = false; 2412 } 2413 } 2414 2415 if (atoken != null) { 2416 if (atoken.startingWindow == win) { 2417 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling startingWindow " + win); 2418 atoken.startingWindow = null; 2419 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) { 2420 // If this is the last window and we had requested a starting 2421 // transition window, well there is no point now. 2422 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling last startingWindow"); 2423 atoken.startingData = null; 2424 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) { 2425 // If this is the last window except for a starting transition 2426 // window, we need to get rid of the starting transition. 2427 if (DEBUG_STARTING_WINDOW) { 2428 Slog.v(TAG, "Schedule remove starting " + token 2429 + ": no more real windows"); 2430 } 2431 Message m = mH.obtainMessage(H.REMOVE_STARTING, atoken); 2432 mH.sendMessage(m); 2433 } 2434 } 2435 2436 if (win.mAttrs.type == TYPE_WALLPAPER) { 2437 mLastWallpaperTimeoutTime = 0; 2438 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2439 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2440 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2441 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2442 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2443 } 2444 2445 if (!mInLayout) { 2446 assignLayersLocked(windows); 2447 win.mDisplayContent.layoutNeeded = true; 2448 performLayoutAndPlaceSurfacesLocked(); 2449 if (win.mAppToken != null) { 2450 win.mAppToken.updateReportedVisibilityLocked(); 2451 } 2452 } 2453 2454 mInputMonitor.updateInputWindowsLw(true /*force*/); 2455 } 2456 2457 public void updateAppOpsState() { 2458 synchronized(mWindowMap) { 2459 mTmpWindowsIterator.reset(FORWARD_ITERATOR); 2460 while (mTmpWindowsIterator.hasNext()) { 2461 final WindowState win = mTmpWindowsIterator.next(); 2462 if (win.mAppOp != AppOpsManager.OP_NONE) { 2463 final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(), 2464 win.getOwningPackage()); 2465 win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED); 2466 } 2467 } 2468 } 2469 } 2470 2471 static void logSurface(WindowState w, String msg, RuntimeException where) { 2472 String str = " SURFACE " + msg + ": " + w; 2473 if (where != null) { 2474 Slog.i(TAG, str, where); 2475 } else { 2476 Slog.i(TAG, str); 2477 } 2478 } 2479 2480 static void logSurface(Surface s, String title, String msg, RuntimeException where) { 2481 String str = " SURFACE " + s + ": " + msg + " / " + title; 2482 if (where != null) { 2483 Slog.i(TAG, str, where); 2484 } else { 2485 Slog.i(TAG, str); 2486 } 2487 } 2488 2489 void setTransparentRegionWindow(Session session, IWindow client, Region region) { 2490 long origId = Binder.clearCallingIdentity(); 2491 try { 2492 synchronized (mWindowMap) { 2493 WindowState w = windowForClientLocked(session, client, false); 2494 if ((w != null) && w.mHasSurface) { 2495 w.mWinAnimator.setTransparentRegionHintLocked(region); 2496 } 2497 } 2498 } finally { 2499 Binder.restoreCallingIdentity(origId); 2500 } 2501 } 2502 2503 void setInsetsWindow(Session session, IWindow client, 2504 int touchableInsets, Rect contentInsets, 2505 Rect visibleInsets, Region touchableRegion) { 2506 long origId = Binder.clearCallingIdentity(); 2507 try { 2508 synchronized (mWindowMap) { 2509 WindowState w = windowForClientLocked(session, client, false); 2510 if (w != null) { 2511 w.mGivenInsetsPending = false; 2512 w.mGivenContentInsets.set(contentInsets); 2513 w.mGivenVisibleInsets.set(visibleInsets); 2514 w.mGivenTouchableRegion.set(touchableRegion); 2515 w.mTouchableInsets = touchableInsets; 2516 if (w.mGlobalScale != 1) { 2517 w.mGivenContentInsets.scale(w.mGlobalScale); 2518 w.mGivenVisibleInsets.scale(w.mGlobalScale); 2519 w.mGivenTouchableRegion.scale(w.mGlobalScale); 2520 } 2521 w.mDisplayContent.layoutNeeded = true; 2522 performLayoutAndPlaceSurfacesLocked(); 2523 } 2524 } 2525 } finally { 2526 Binder.restoreCallingIdentity(origId); 2527 } 2528 } 2529 2530 public void getWindowDisplayFrame(Session session, IWindow client, 2531 Rect outDisplayFrame) { 2532 synchronized(mWindowMap) { 2533 WindowState win = windowForClientLocked(session, client, false); 2534 if (win == null) { 2535 outDisplayFrame.setEmpty(); 2536 return; 2537 } 2538 outDisplayFrame.set(win.mDisplayFrame); 2539 } 2540 } 2541 2542 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y, 2543 float xStep, float yStep) { 2544 if (window.mWallpaperX != x || window.mWallpaperY != y) { 2545 window.mWallpaperX = x; 2546 window.mWallpaperY = y; 2547 window.mWallpaperXStep = xStep; 2548 window.mWallpaperYStep = yStep; 2549 updateWallpaperOffsetLocked(window, true); 2550 } 2551 } 2552 2553 void wallpaperCommandComplete(IBinder window, Bundle result) { 2554 synchronized (mWindowMap) { 2555 if (mWaitingOnWallpaper != null && 2556 mWaitingOnWallpaper.mClient.asBinder() == window) { 2557 mWaitingOnWallpaper = null; 2558 mWindowMap.notifyAll(); 2559 } 2560 } 2561 } 2562 2563 public Bundle sendWindowWallpaperCommandLocked(WindowState window, 2564 String action, int x, int y, int z, Bundle extras, boolean sync) { 2565 if (window == mWallpaperTarget || window == mLowerWallpaperTarget 2566 || window == mUpperWallpaperTarget) { 2567 boolean doWait = sync; 2568 int curTokenIndex = mWallpaperTokens.size(); 2569 while (curTokenIndex > 0) { 2570 curTokenIndex--; 2571 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2572 int curWallpaperIndex = token.windows.size(); 2573 while (curWallpaperIndex > 0) { 2574 curWallpaperIndex--; 2575 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2576 try { 2577 wallpaper.mClient.dispatchWallpaperCommand(action, 2578 x, y, z, extras, sync); 2579 // We only want to be synchronous with one wallpaper. 2580 sync = false; 2581 } catch (RemoteException e) { 2582 } 2583 } 2584 } 2585 2586 if (doWait) { 2587 // XXX Need to wait for result. 2588 } 2589 } 2590 2591 return null; 2592 } 2593 2594 public void setUniverseTransformLocked(WindowState window, float alpha, 2595 float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) { 2596 Transformation transform = window.mWinAnimator.mUniverseTransform; 2597 transform.setAlpha(alpha); 2598 Matrix matrix = transform.getMatrix(); 2599 matrix.getValues(mTmpFloats); 2600 mTmpFloats[Matrix.MTRANS_X] = offx; 2601 mTmpFloats[Matrix.MTRANS_Y] = offy; 2602 mTmpFloats[Matrix.MSCALE_X] = dsdx; 2603 mTmpFloats[Matrix.MSKEW_Y] = dtdx; 2604 mTmpFloats[Matrix.MSKEW_X] = dsdy; 2605 mTmpFloats[Matrix.MSCALE_Y] = dtdy; 2606 matrix.setValues(mTmpFloats); 2607 final DisplayInfo displayInfo = window.mDisplayContent.getDisplayInfo(); 2608 final RectF dispRect = new RectF(0, 0, 2609 displayInfo.logicalWidth, displayInfo.logicalHeight); 2610 matrix.mapRect(dispRect); 2611 window.mGivenTouchableRegion.set(0, 0, 2612 displayInfo.logicalWidth, displayInfo.logicalHeight); 2613 window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top, 2614 (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE); 2615 window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; 2616 window.mDisplayContent.layoutNeeded = true; 2617 performLayoutAndPlaceSurfacesLocked(); 2618 } 2619 2620 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle, boolean immediate) { 2621 synchronized (mWindowMap) { 2622 if (mDisplayMagnifier != null) { 2623 WindowState window = mWindowMap.get(token); 2624 //TODO (multidisplay): Magnification is supported only for the default display. 2625 if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 2626 mDisplayMagnifier.onRectangleOnScreenRequestedLocked(rectangle, immediate); 2627 } 2628 } 2629 } 2630 } 2631 2632 public int relayoutWindow(Session session, IWindow client, int seq, 2633 WindowManager.LayoutParams attrs, int requestedWidth, 2634 int requestedHeight, int viewVisibility, int flags, 2635 Rect outFrame, Rect outContentInsets, 2636 Rect outVisibleInsets, Configuration outConfig, Surface outSurface) { 2637 boolean toBeDisplayed = false; 2638 boolean inTouchMode; 2639 boolean configChanged; 2640 boolean surfaceChanged = false; 2641 boolean animating; 2642 2643 // if they don't have this permission, mask out the status bar bits 2644 int systemUiVisibility = 0; 2645 if (attrs != null) { 2646 systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility); 2647 if ((systemUiVisibility & StatusBarManager.DISABLE_MASK) != 0) { 2648 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 2649 != PackageManager.PERMISSION_GRANTED) { 2650 systemUiVisibility &= ~StatusBarManager.DISABLE_MASK; 2651 } 2652 } 2653 } 2654 long origId = Binder.clearCallingIdentity(); 2655 2656 synchronized(mWindowMap) { 2657 WindowState win = windowForClientLocked(session, client, false); 2658 if (win == null) { 2659 return 0; 2660 } 2661 WindowStateAnimator winAnimator = win.mWinAnimator; 2662 if (win.mRequestedWidth != requestedWidth 2663 || win.mRequestedHeight != requestedHeight) { 2664 win.mLayoutNeeded = true; 2665 win.mRequestedWidth = requestedWidth; 2666 win.mRequestedHeight = requestedHeight; 2667 } 2668 if (attrs != null && seq == win.mSeq) { 2669 win.mSystemUiVisibility = systemUiVisibility; 2670 } 2671 2672 if (attrs != null) { 2673 mPolicy.adjustWindowParamsLw(attrs); 2674 } 2675 2676 winAnimator.mSurfaceDestroyDeferred = 2677 (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0; 2678 2679 int attrChanges = 0; 2680 int flagChanges = 0; 2681 if (attrs != null) { 2682 if (win.mAttrs.type != attrs.type) { 2683 throw new IllegalArgumentException( 2684 "Window type can not be changed after the window is added."); 2685 } 2686 flagChanges = win.mAttrs.flags ^= attrs.flags; 2687 attrChanges = win.mAttrs.copyFrom(attrs); 2688 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED 2689 | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) { 2690 win.mLayoutNeeded = true; 2691 } 2692 } 2693 2694 if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility 2695 + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs); 2696 2697 win.mEnforceSizeCompat = (win.mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0; 2698 2699 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) { 2700 winAnimator.mAlpha = attrs.alpha; 2701 } 2702 2703 final boolean scaledWindow = 2704 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0); 2705 2706 if (scaledWindow) { 2707 // requested{Width|Height} Surface's physical size 2708 // attrs.{width|height} Size on screen 2709 win.mHScale = (attrs.width != requestedWidth) ? 2710 (attrs.width / (float)requestedWidth) : 1.0f; 2711 win.mVScale = (attrs.height != requestedHeight) ? 2712 (attrs.height / (float)requestedHeight) : 1.0f; 2713 } else { 2714 win.mHScale = win.mVScale = 1; 2715 } 2716 2717 boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0; 2718 2719 final boolean isDefaultDisplay = win.isDefaultDisplay(); 2720 boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility 2721 || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0) 2722 || (!win.mRelayoutCalled)); 2723 2724 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility 2725 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0; 2726 wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0; 2727 2728 win.mRelayoutCalled = true; 2729 final int oldVisibility = win.mViewVisibility; 2730 win.mViewVisibility = viewVisibility; 2731 if (DEBUG_SCREEN_ON) { 2732 RuntimeException stack = new RuntimeException(); 2733 stack.fillInStackTrace(); 2734 Slog.i(TAG, "Relayout " + win + ": oldVis=" + oldVisibility 2735 + " newVis=" + viewVisibility, stack); 2736 } 2737 if (viewVisibility == View.VISIBLE && 2738 (win.mAppToken == null || !win.mAppToken.clientHidden)) { 2739 toBeDisplayed = !win.isVisibleLw(); 2740 if (win.mExiting) { 2741 winAnimator.cancelExitAnimationForNextAnimationLocked(); 2742 win.mExiting = false; 2743 } 2744 if (win.mDestroying) { 2745 win.mDestroying = false; 2746 mDestroySurface.remove(win); 2747 } 2748 if (oldVisibility == View.GONE) { 2749 winAnimator.mEnterAnimationPending = true; 2750 } 2751 if (toBeDisplayed) { 2752 if (win.isDrawnLw() && okToDisplay()) { 2753 winAnimator.applyEnterAnimationLocked(); 2754 } 2755 if ((win.mAttrs.flags 2756 & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) { 2757 if (DEBUG_VISIBILITY) Slog.v(TAG, 2758 "Relayout window turning screen on: " + win); 2759 win.mTurnOnScreen = true; 2760 } 2761 if (win.isConfigChanged()) { 2762 if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win 2763 + " visible with new config: " + mCurConfiguration); 2764 outConfig.setTo(mCurConfiguration); 2765 } 2766 } 2767 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) { 2768 // To change the format, we need to re-build the surface. 2769 winAnimator.destroySurfaceLocked(); 2770 toBeDisplayed = true; 2771 surfaceChanged = true; 2772 } 2773 try { 2774 if (!win.mHasSurface) { 2775 surfaceChanged = true; 2776 } 2777 Surface surface = winAnimator.createSurfaceLocked(); 2778 if (surface != null) { 2779 outSurface.copyFrom(surface); 2780 if (SHOW_TRANSACTIONS) Slog.i(TAG, 2781 " OUT SURFACE " + outSurface + ": copied"); 2782 } else { 2783 // For some reason there isn't a surface. Clear the 2784 // caller's object so they see the same state. 2785 outSurface.release(); 2786 } 2787 } catch (Exception e) { 2788 mInputMonitor.updateInputWindowsLw(true /*force*/); 2789 2790 Slog.w(TAG, "Exception thrown when creating surface for client " 2791 + client + " (" + win.mAttrs.getTitle() + ")", 2792 e); 2793 Binder.restoreCallingIdentity(origId); 2794 return 0; 2795 } 2796 if (toBeDisplayed) { 2797 focusMayChange = isDefaultDisplay; 2798 } 2799 if (win.mAttrs.type == TYPE_INPUT_METHOD 2800 && mInputMethodWindow == null) { 2801 mInputMethodWindow = win; 2802 imMayMove = true; 2803 } 2804 if (win.mAttrs.type == TYPE_BASE_APPLICATION 2805 && win.mAppToken != null 2806 && win.mAppToken.startingWindow != null) { 2807 // Special handling of starting window over the base 2808 // window of the app: propagate lock screen flags to it, 2809 // to provide the correct semantics while starting. 2810 final int mask = 2811 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED 2812 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD 2813 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; 2814 WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs; 2815 sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask); 2816 } 2817 } else { 2818 winAnimator.mEnterAnimationPending = false; 2819 if (winAnimator.mSurface != null) { 2820 if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win 2821 + ": mExiting=" + win.mExiting); 2822 // If we are not currently running the exit animation, we 2823 // need to see about starting one. 2824 if (!win.mExiting) { 2825 surfaceChanged = true; 2826 // Try starting an animation; if there isn't one, we 2827 // can destroy the surface right away. 2828 int transit = WindowManagerPolicy.TRANSIT_EXIT; 2829 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2830 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 2831 } 2832 if (win.isWinVisibleLw() && 2833 winAnimator.applyAnimationLocked(transit, false)) { 2834 focusMayChange = isDefaultDisplay; 2835 win.mExiting = true; 2836 } else if (win.mWinAnimator.isAnimating()) { 2837 // Currently in a hide animation... turn this into 2838 // an exit. 2839 win.mExiting = true; 2840 } else if (win == mWallpaperTarget) { 2841 // If the wallpaper is currently behind this 2842 // window, we need to change both of them inside 2843 // of a transaction to avoid artifacts. 2844 win.mExiting = true; 2845 win.mWinAnimator.mAnimating = true; 2846 } else { 2847 if (mInputMethodWindow == win) { 2848 mInputMethodWindow = null; 2849 } 2850 winAnimator.destroySurfaceLocked(); 2851 } 2852 //TODO (multidisplay): Magnification is supported only for the default 2853 if (mDisplayMagnifier != null 2854 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 2855 mDisplayMagnifier.onWindowTransitionLocked(win, transit); 2856 } 2857 } 2858 } 2859 2860 outSurface.release(); 2861 if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win); 2862 } 2863 2864 if (focusMayChange) { 2865 //System.out.println("Focus may change: " + win.mAttrs.getTitle()); 2866 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 2867 false /*updateInputWindows*/)) { 2868 imMayMove = false; 2869 } 2870 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus); 2871 } 2872 2873 // updateFocusedWindowLocked() already assigned layers so we only need to 2874 // reassign them at this point if the IM window state gets shuffled 2875 if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) { 2876 // Little hack here -- we -should- be able to rely on the 2877 // function to return true if the IME has moved and needs 2878 // its layer recomputed. However, if the IME was hidden 2879 // and isn't actually moved in the list, its layer may be 2880 // out of data so we make sure to recompute it. 2881 assignLayersLocked(win.getWindowList()); 2882 } 2883 2884 if (wallpaperMayMove) { 2885 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2886 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2887 } 2888 2889 win.mDisplayContent.layoutNeeded = true; 2890 win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0; 2891 configChanged = updateOrientationFromAppTokensLocked(false); 2892 performLayoutAndPlaceSurfacesLocked(); 2893 if (toBeDisplayed && win.mIsWallpaper) { 2894 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 2895 updateWallpaperOffsetLocked(win, 2896 displayInfo.appWidth, displayInfo.appHeight, false); 2897 } 2898 if (win.mAppToken != null) { 2899 win.mAppToken.updateReportedVisibilityLocked(); 2900 } 2901 outFrame.set(win.mCompatFrame); 2902 outContentInsets.set(win.mContentInsets); 2903 outVisibleInsets.set(win.mVisibleInsets); 2904 if (localLOGV) Slog.v( 2905 TAG, "Relayout given client " + client.asBinder() 2906 + ", requestedWidth=" + requestedWidth 2907 + ", requestedHeight=" + requestedHeight 2908 + ", viewVisibility=" + viewVisibility 2909 + "\nRelayout returning frame=" + outFrame 2910 + ", surface=" + outSurface); 2911 2912 if (localLOGV || DEBUG_FOCUS) Slog.v( 2913 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange); 2914 2915 inTouchMode = mInTouchMode; 2916 animating = mAnimator.mAnimating; 2917 if (animating && !mRelayoutWhileAnimating.contains(win)) { 2918 mRelayoutWhileAnimating.add(win); 2919 } 2920 2921 mInputMonitor.updateInputWindowsLw(true /*force*/); 2922 2923 if (DEBUG_LAYOUT) { 2924 Slog.v(TAG, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString()); 2925 } 2926 } 2927 2928 if (configChanged) { 2929 sendNewConfiguration(); 2930 } 2931 2932 Binder.restoreCallingIdentity(origId); 2933 2934 return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0) 2935 | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0) 2936 | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0) 2937 | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0); 2938 } 2939 2940 public void performDeferredDestroyWindow(Session session, IWindow client) { 2941 long origId = Binder.clearCallingIdentity(); 2942 2943 try { 2944 synchronized (mWindowMap) { 2945 WindowState win = windowForClientLocked(session, client, false); 2946 if (win == null) { 2947 return; 2948 } 2949 win.mWinAnimator.destroyDeferredSurfaceLocked(); 2950 } 2951 } finally { 2952 Binder.restoreCallingIdentity(origId); 2953 } 2954 } 2955 2956 public boolean outOfMemoryWindow(Session session, IWindow client) { 2957 long origId = Binder.clearCallingIdentity(); 2958 2959 try { 2960 synchronized (mWindowMap) { 2961 WindowState win = windowForClientLocked(session, client, false); 2962 if (win == null) { 2963 return false; 2964 } 2965 return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false); 2966 } 2967 } finally { 2968 Binder.restoreCallingIdentity(origId); 2969 } 2970 } 2971 2972 public void finishDrawingWindow(Session session, IWindow client) { 2973 final long origId = Binder.clearCallingIdentity(); 2974 try { 2975 synchronized (mWindowMap) { 2976 WindowState win = windowForClientLocked(session, client, false); 2977 if (win != null && win.mWinAnimator.finishDrawingLocked()) { 2978 if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 2979 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2980 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2981 } 2982 win.mDisplayContent.layoutNeeded = true; 2983 requestTraversalLocked(); 2984 } 2985 } 2986 } finally { 2987 Binder.restoreCallingIdentity(origId); 2988 } 2989 } 2990 2991 @Override 2992 public void getWindowFrame(IBinder token, Rect outBounds) { 2993 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 2994 "getWindowInfo()")) { 2995 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission."); 2996 } 2997 synchronized (mWindowMap) { 2998 WindowState windowState = mWindowMap.get(token); 2999 if (windowState != null) { 3000 outBounds.set(windowState.mFrame); 3001 } else { 3002 outBounds.setEmpty(); 3003 } 3004 } 3005 } 3006 3007 @Override 3008 public void setMagnificationSpec(MagnificationSpec spec) { 3009 if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY, 3010 "setMagnificationSpec()")) { 3011 throw new SecurityException("Requires MAGNIFY_DISPLAY permission."); 3012 } 3013 synchronized (mWindowMap) { 3014 if (mDisplayMagnifier != null) { 3015 mDisplayMagnifier.setMagnificationSpecLocked(spec); 3016 } else { 3017 throw new IllegalStateException("Magnification callbacks not set!"); 3018 } 3019 } 3020 if (Binder.getCallingPid() != android.os.Process.myPid()) { 3021 spec.recycle(); 3022 } 3023 } 3024 3025 @Override 3026 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { 3027 if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY, 3028 "getCompatibleMagnificationSpecForWindow()")) { 3029 throw new SecurityException("Requires MAGNIFY_DISPLAY permission."); 3030 } 3031 synchronized (mWindowMap) { 3032 WindowState windowState = mWindowMap.get(windowToken); 3033 if (windowState == null) { 3034 return null; 3035 } 3036 MagnificationSpec spec = null; 3037 if (mDisplayMagnifier != null) { 3038 spec = mDisplayMagnifier.getMagnificationSpecForWindowLocked(windowState); 3039 } 3040 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) { 3041 return null; 3042 } 3043 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec); 3044 spec.scale *= windowState.mGlobalScale; 3045 return spec; 3046 } 3047 } 3048 3049 @Override 3050 public void setMagnificationCallbacks(IMagnificationCallbacks callbacks) { 3051 if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY, 3052 "setMagnificationCallbacks()")) { 3053 throw new SecurityException("Requires MAGNIFY_DISPLAY permission."); 3054 } 3055 synchronized (mWindowMap) { 3056 if (mDisplayMagnifier == null) { 3057 mDisplayMagnifier = new DisplayMagnifier(this, callbacks); 3058 } else { 3059 if (callbacks == null) { 3060 if (mDisplayMagnifier != null) { 3061 mDisplayMagnifier.destroyLocked(); 3062 mDisplayMagnifier = null; 3063 } 3064 } else { 3065 throw new IllegalStateException("Magnification callbacks already set!"); 3066 } 3067 } 3068 } 3069 } 3070 3071 private boolean applyAnimationLocked(AppWindowToken atoken, 3072 WindowManager.LayoutParams lp, int transit, boolean enter) { 3073 // Only apply an animation if the display isn't frozen. If it is 3074 // frozen, there is no reason to animate and it can cause strange 3075 // artifacts when we unfreeze the display if some different animation 3076 // is running. 3077 if (okToDisplay()) { 3078 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 3079 final int width = displayInfo.appWidth; 3080 final int height = displayInfo.appHeight; 3081 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation: atoken=" 3082 + atoken); 3083 Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height); 3084 if (a != null) { 3085 if (DEBUG_ANIM) { 3086 RuntimeException e = null; 3087 if (!HIDE_STACK_CRAWLS) { 3088 e = new RuntimeException(); 3089 e.fillInStackTrace(); 3090 } 3091 Slog.v(TAG, "Loaded animation " + a + " for " + atoken, e); 3092 } 3093 atoken.mAppAnimator.setAnimation(a, width, height); 3094 } 3095 } else { 3096 atoken.mAppAnimator.clearAnimation(); 3097 } 3098 3099 return atoken.mAppAnimator.animation != null; 3100 } 3101 3102 // ------------------------------------------------------------- 3103 // Application Window Tokens 3104 // ------------------------------------------------------------- 3105 3106 public void validateAppTokens(List<TaskGroup> tasks) { 3107 synchronized (mWindowMap) { 3108 int t = tasks.size() - 1; 3109 if (t < 0) { 3110 Slog.w(TAG, "validateAppTokens: empty task list"); 3111 return; 3112 } 3113 3114 TaskGroup task = tasks.get(0); 3115 int taskId = task.taskId; 3116 DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId); 3117 if (displayContent == null) { 3118 Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId); 3119 return; 3120 } 3121 3122 AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR); 3123 for ( ; t >= 0; --t) { 3124 task = tasks.get(t); 3125 List<IApplicationToken> tokens = task.tokens; 3126 int v = task.tokens.size() - 1; 3127 3128 DisplayContent lastDisplayContent = displayContent; 3129 displayContent = mTaskIdToDisplayContents.get(taskId); 3130 if (displayContent != lastDisplayContent) { 3131 Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!"); 3132 return; 3133 } 3134 3135 while (v >= 0 && iterator.hasNext()) { 3136 AppWindowToken atoken = iterator.next(); 3137 if (atoken.removed) { 3138 continue; 3139 } 3140 if (tokens.get(v) != atoken.token) { 3141 Slog.w(TAG, "Tokens out of sync: external is " + tokens.get(v) 3142 + " @ " + v + ", internal is " + atoken.token); 3143 } 3144 v--; 3145 } 3146 while (v >= 0) { 3147 Slog.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v); 3148 v--; 3149 } 3150 } 3151 3152 while (iterator.hasNext()) { 3153 AppWindowToken atoken = iterator.next(); 3154 if (!atoken.removed) { 3155 Slog.w(TAG, "Invalid internal atoken: " + atoken.token); 3156 } 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 Surface.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 Surface.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 = Surface.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 Surface.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 Surface.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 Surface surface = new Surface(session, "drag surface", 6326 width, height, PixelFormat.TRANSLUCENT, Surface.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 (Surface.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 synchronized(mWindowMap) { 7092 // Set some sort of reasonable bounds on the size of the display that we 7093 // will try to emulate. 7094 final int MIN_WIDTH = 200; 7095 final int MIN_HEIGHT = 200; 7096 final int MAX_SCALE = 2; 7097 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7098 if (displayContent != null) { 7099 width = Math.min(Math.max(width, MIN_WIDTH), 7100 displayContent.mInitialDisplayWidth * MAX_SCALE); 7101 height = Math.min(Math.max(height, MIN_HEIGHT), 7102 displayContent.mInitialDisplayHeight * MAX_SCALE); 7103 setForcedDisplaySizeLocked(displayContent, width, height); 7104 Settings.Global.putString(mContext.getContentResolver(), 7105 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 7106 } 7107 } 7108 } 7109 7110 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 7111 final String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 7112 Settings.Global.DISPLAY_SIZE_FORCED); 7113 if (sizeStr != null && sizeStr.length() > 0) { 7114 final int pos = sizeStr.indexOf(','); 7115 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 7116 int width, height; 7117 try { 7118 width = Integer.parseInt(sizeStr.substring(0, pos)); 7119 height = Integer.parseInt(sizeStr.substring(pos+1)); 7120 synchronized(displayContent.mDisplaySizeLock) { 7121 if (displayContent.mBaseDisplayWidth != width 7122 || displayContent.mBaseDisplayHeight != height) { 7123 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 7124 displayContent.mBaseDisplayWidth = width; 7125 displayContent.mBaseDisplayHeight = height; 7126 } 7127 } 7128 } catch (NumberFormatException ex) { 7129 } 7130 } 7131 } 7132 final String densityStr = Settings.Global.getString(mContext.getContentResolver(), 7133 Settings.Global.DISPLAY_DENSITY_FORCED); 7134 if (densityStr != null && densityStr.length() > 0) { 7135 int density; 7136 try { 7137 density = Integer.parseInt(densityStr); 7138 synchronized(displayContent.mDisplaySizeLock) { 7139 if (displayContent.mBaseDisplayDensity != density) { 7140 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 7141 displayContent.mBaseDisplayDensity = density; 7142 } 7143 } 7144 } catch (NumberFormatException ex) { 7145 } 7146 } 7147 } 7148 7149 // displayContent must not be null 7150 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 7151 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7152 7153 synchronized(displayContent.mDisplaySizeLock) { 7154 displayContent.mBaseDisplayWidth = width; 7155 displayContent.mBaseDisplayHeight = height; 7156 } 7157 reconfigureDisplayLocked(displayContent); 7158 } 7159 7160 @Override 7161 public void clearForcedDisplaySize(int displayId) { 7162 synchronized(mWindowMap) { 7163 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7164 if (displayContent != null) { 7165 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 7166 displayContent.mInitialDisplayHeight); 7167 Settings.Global.putString(mContext.getContentResolver(), 7168 Settings.Global.DISPLAY_SIZE_FORCED, ""); 7169 } 7170 } 7171 } 7172 7173 @Override 7174 public void setForcedDisplayDensity(int displayId, int density) { 7175 synchronized(mWindowMap) { 7176 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7177 if (displayContent != null) { 7178 setForcedDisplayDensityLocked(displayContent, density); 7179 Settings.Global.putString(mContext.getContentResolver(), 7180 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 7181 } 7182 } 7183 } 7184 7185 // displayContent must not be null 7186 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 7187 Slog.i(TAG, "Using new display density: " + density); 7188 7189 synchronized(displayContent.mDisplaySizeLock) { 7190 displayContent.mBaseDisplayDensity = density; 7191 } 7192 reconfigureDisplayLocked(displayContent); 7193 } 7194 7195 @Override 7196 public void clearForcedDisplayDensity(int displayId) { 7197 synchronized(mWindowMap) { 7198 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7199 if (displayContent != null) { 7200 setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity); 7201 Settings.Global.putString(mContext.getContentResolver(), 7202 Settings.Global.DISPLAY_DENSITY_FORCED, ""); 7203 } 7204 } 7205 } 7206 7207 // displayContent must not be null 7208 private void reconfigureDisplayLocked(DisplayContent displayContent) { 7209 // TODO: Multidisplay: for now only use with default display. 7210 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 7211 displayContent.mBaseDisplayWidth, 7212 displayContent.mBaseDisplayHeight, 7213 displayContent.mBaseDisplayDensity); 7214 7215 displayContent.layoutNeeded = true; 7216 7217 boolean configChanged = updateOrientationFromAppTokensLocked(false); 7218 mTempConfiguration.setToDefaults(); 7219 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 7220 if (computeScreenConfigurationLocked(mTempConfiguration)) { 7221 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 7222 configChanged = true; 7223 } 7224 } 7225 7226 if (configChanged) { 7227 mWaitingForConfig = true; 7228 startFreezingDisplayLocked(false, 0, 0); 7229 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 7230 } 7231 7232 performLayoutAndPlaceSurfacesLocked(); 7233 } 7234 7235 @Override 7236 public boolean hasSystemNavBar() { 7237 return mPolicy.hasSystemNavBar(); 7238 } 7239 7240 // ------------------------------------------------------------- 7241 // Internals 7242 // ------------------------------------------------------------- 7243 7244 final WindowState windowForClientLocked(Session session, IWindow client, 7245 boolean throwOnError) { 7246 return windowForClientLocked(session, client.asBinder(), throwOnError); 7247 } 7248 7249 final WindowState windowForClientLocked(Session session, IBinder client, 7250 boolean throwOnError) { 7251 WindowState win = mWindowMap.get(client); 7252 if (localLOGV) Slog.v( 7253 TAG, "Looking up client " + client + ": " + win); 7254 if (win == null) { 7255 RuntimeException ex = new IllegalArgumentException( 7256 "Requested window " + client + " does not exist"); 7257 if (throwOnError) { 7258 throw ex; 7259 } 7260 Slog.w(TAG, "Failed looking up window", ex); 7261 return null; 7262 } 7263 if (session != null && win.mSession != session) { 7264 RuntimeException ex = new IllegalArgumentException( 7265 "Requested window " + client + " is in session " + 7266 win.mSession + ", not " + session); 7267 if (throwOnError) { 7268 throw ex; 7269 } 7270 Slog.w(TAG, "Failed looking up window", ex); 7271 return null; 7272 } 7273 7274 return win; 7275 } 7276 7277 final void rebuildAppWindowListLocked() { 7278 DisplayContentsIterator iterator = new DisplayContentsIterator(); 7279 while (iterator.hasNext()) { 7280 rebuildAppWindowListLocked(iterator.next()); 7281 } 7282 } 7283 7284 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 7285 final WindowList windows = displayContent.getWindowList(); 7286 int NW = windows.size(); 7287 int i; 7288 int lastBelow = -1; 7289 int numRemoved = 0; 7290 7291 if (mRebuildTmp.length < NW) { 7292 mRebuildTmp = new WindowState[NW+10]; 7293 } 7294 7295 // First remove all existing app windows. 7296 i=0; 7297 while (i < NW) { 7298 WindowState w = windows.get(i); 7299 if (w.mAppToken != null) { 7300 WindowState win = windows.remove(i); 7301 win.mRebuilding = true; 7302 mRebuildTmp[numRemoved] = win; 7303 mWindowsChanged = true; 7304 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 7305 "Rebuild removing window: " + win); 7306 NW--; 7307 numRemoved++; 7308 continue; 7309 } else if (lastBelow == i-1) { 7310 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 7311 lastBelow = i; 7312 } 7313 } 7314 i++; 7315 } 7316 7317 // Keep whatever windows were below the app windows still below, 7318 // by skipping them. 7319 lastBelow++; 7320 i = lastBelow; 7321 7322 // First add all of the exiting app tokens... these are no longer 7323 // in the main app list, but still have windows shown. We put them 7324 // in the back because now that the animation is over we no longer 7325 // will care about them. 7326 AppTokenList exitingAppTokens = displayContent.mExitingAppTokens; 7327 int NT = exitingAppTokens.size(); 7328 for (int j=0; j<NT; j++) { 7329 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 7330 } 7331 7332 // And add in the still active app tokens in Z order. 7333 AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR); 7334 while (iterator.hasNext()) { 7335 i = reAddAppWindowsLocked(displayContent, i, iterator.next()); 7336 } 7337 7338 i -= lastBelow; 7339 if (i != numRemoved) { 7340 Slog.w(TAG, "Rebuild removed " + numRemoved 7341 + " windows but added " + i); 7342 for (i=0; i<numRemoved; i++) { 7343 WindowState ws = mRebuildTmp[i]; 7344 if (ws.mRebuilding) { 7345 StringWriter sw = new StringWriter(); 7346 PrintWriter pw = new PrintWriter(sw); 7347 ws.dump(pw, "", true); 7348 pw.flush(); 7349 Slog.w(TAG, "This window was lost: " + ws); 7350 Slog.w(TAG, sw.toString()); 7351 ws.mWinAnimator.destroySurfaceLocked(); 7352 } 7353 } 7354 Slog.w(TAG, "Current app token list:"); 7355 dumpAppTokensLocked(); 7356 Slog.w(TAG, "Final window list:"); 7357 dumpWindowsLocked(); 7358 } 7359 } 7360 7361 private final void assignLayersLocked(WindowList windows) { 7362 int N = windows.size(); 7363 int curBaseLayer = 0; 7364 int curLayer = 0; 7365 int i; 7366 7367 if (DEBUG_LAYERS) { 7368 RuntimeException here = new RuntimeException("here"); 7369 here.fillInStackTrace(); 7370 Slog.v(TAG, "Assigning layers", here); 7371 } 7372 7373 boolean anyLayerChanged = false; 7374 7375 for (i=0; i<N; i++) { 7376 final WindowState w = windows.get(i); 7377 final WindowStateAnimator winAnimator = w.mWinAnimator; 7378 boolean layerChanged = false; 7379 int oldLayer = w.mLayer; 7380 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 7381 || (i > 0 && w.mIsWallpaper)) { 7382 curLayer += WINDOW_LAYER_MULTIPLIER; 7383 w.mLayer = curLayer; 7384 } else { 7385 curBaseLayer = curLayer = w.mBaseLayer; 7386 w.mLayer = curLayer; 7387 } 7388 if (w.mLayer != oldLayer) { 7389 layerChanged = true; 7390 anyLayerChanged = true; 7391 } 7392 oldLayer = winAnimator.mAnimLayer; 7393 if (w.mTargetAppToken != null) { 7394 winAnimator.mAnimLayer = 7395 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 7396 } else if (w.mAppToken != null) { 7397 winAnimator.mAnimLayer = 7398 w.mLayer + w.mAppToken.mAppAnimator.animLayerAdjustment; 7399 } else { 7400 winAnimator.mAnimLayer = w.mLayer; 7401 } 7402 if (w.mIsImWindow) { 7403 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 7404 } else if (w.mIsWallpaper) { 7405 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 7406 } 7407 if (winAnimator.mAnimLayer != oldLayer) { 7408 layerChanged = true; 7409 anyLayerChanged = true; 7410 } 7411 if (layerChanged && mAnimator.isDimmingLocked(winAnimator)) { 7412 // Force an animation pass just to update the mDimAnimator layer. 7413 scheduleAnimationLocked(); 7414 } 7415 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 7416 + "mBase=" + w.mBaseLayer 7417 + " mLayer=" + w.mLayer 7418 + (w.mAppToken == null ? 7419 "" : " mAppLayer=" + w.mAppToken.mAppAnimator.animLayerAdjustment) 7420 + " =mAnimLayer=" + winAnimator.mAnimLayer); 7421 //System.out.println( 7422 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 7423 } 7424 7425 //TODO (multidisplay): Magnification is supported only for the default display. 7426 if (mDisplayMagnifier != null && anyLayerChanged 7427 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) { 7428 mDisplayMagnifier.onWindowLayersChangedLocked(); 7429 } 7430 } 7431 7432 private final void performLayoutAndPlaceSurfacesLocked() { 7433 int loopCount = 6; 7434 do { 7435 mTraversalScheduled = false; 7436 performLayoutAndPlaceSurfacesLockedLoop(); 7437 mH.removeMessages(H.DO_TRAVERSAL); 7438 loopCount--; 7439 } while (mTraversalScheduled && loopCount > 0); 7440 mInnerFields.mWallpaperActionPending = false; 7441 } 7442 7443 private boolean mInLayout = false; 7444 private final void performLayoutAndPlaceSurfacesLockedLoop() { 7445 if (mInLayout) { 7446 if (DEBUG) { 7447 throw new RuntimeException("Recursive call!"); 7448 } 7449 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 7450 + Debug.getCallers(3)); 7451 return; 7452 } 7453 7454 if (mWaitingForConfig) { 7455 // Our configuration has changed (most likely rotation), but we 7456 // don't yet have the complete configuration to report to 7457 // applications. Don't do any window layout until we have it. 7458 return; 7459 } 7460 7461 if (!mDisplayReady) { 7462 // Not yet initialized, nothing to do. 7463 return; 7464 } 7465 7466 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 7467 mInLayout = true; 7468 boolean recoveringMemory = false; 7469 7470 try { 7471 if (mForceRemoves != null) { 7472 recoveringMemory = true; 7473 // Wait a little bit for things to settle down, and off we go. 7474 for (int i=0; i<mForceRemoves.size(); i++) { 7475 WindowState ws = mForceRemoves.get(i); 7476 Slog.i(TAG, "Force removing: " + ws); 7477 removeWindowInnerLocked(ws.mSession, ws); 7478 } 7479 mForceRemoves = null; 7480 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 7481 Object tmp = new Object(); 7482 synchronized (tmp) { 7483 try { 7484 tmp.wait(250); 7485 } catch (InterruptedException e) { 7486 } 7487 } 7488 } 7489 } catch (RuntimeException e) { 7490 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 7491 } 7492 7493 try { 7494 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 7495 7496 mInLayout = false; 7497 7498 if (needsLayout()) { 7499 if (++mLayoutRepeatCount < 6) { 7500 requestTraversalLocked(); 7501 } else { 7502 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 7503 mLayoutRepeatCount = 0; 7504 } 7505 } else { 7506 mLayoutRepeatCount = 0; 7507 } 7508 7509 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 7510 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 7511 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE); 7512 } 7513 } catch (RuntimeException e) { 7514 mInLayout = false; 7515 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 7516 } 7517 7518 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 7519 } 7520 7521 private final void performLayoutLockedInner(final DisplayContent displayContent, 7522 boolean initial, boolean updateInputWindows) { 7523 if (!displayContent.layoutNeeded) { 7524 return; 7525 } 7526 displayContent.layoutNeeded = false; 7527 WindowList windows = displayContent.getWindowList(); 7528 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 7529 7530 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7531 final int dw = displayInfo.logicalWidth; 7532 final int dh = displayInfo.logicalHeight; 7533 7534 final int NFW = mFakeWindows.size(); 7535 for (int i=0; i<NFW; i++) { 7536 mFakeWindows.get(i).layout(dw, dh); 7537 } 7538 7539 final int N = windows.size(); 7540 int i; 7541 7542 if (DEBUG_LAYOUT) { 7543 Slog.v(TAG, "-------------------------------------"); 7544 Slog.v(TAG, "performLayout: needed=" 7545 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 7546 } 7547 7548 WindowStateAnimator universeBackground = null; 7549 7550 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); 7551 if (isDefaultDisplay) { 7552 // Not needed on non-default displays. 7553 mSystemDecorLayer = mPolicy.getSystemDecorRectLw(mSystemDecorRect); 7554 mScreenRect.set(0, 0, dw, dh); 7555 } 7556 7557 int seq = mLayoutSeq+1; 7558 if (seq < 0) seq = 0; 7559 mLayoutSeq = seq; 7560 7561 boolean behindDream = false; 7562 7563 // First perform layout of any root windows (not attached 7564 // to another window). 7565 int topAttached = -1; 7566 for (i = N-1; i >= 0; i--) { 7567 final WindowState win = windows.get(i); 7568 7569 // Don't do layout of a window if it is not visible, or 7570 // soon won't be visible, to avoid wasting time and funky 7571 // changes while a window is animating away. 7572 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) 7573 || win.isGoneForLayoutLw(); 7574 7575 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 7576 Slog.v(TAG, "1ST PASS " + win 7577 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 7578 + " mLayoutAttached=" + win.mLayoutAttached 7579 + " screen changed=" + win.isConfigChanged()); 7580 final AppWindowToken atoken = win.mAppToken; 7581 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 7582 + win.mViewVisibility + " mRelayoutCalled=" 7583 + win.mRelayoutCalled + " hidden=" 7584 + win.mRootToken.hidden + " hiddenRequested=" 7585 + (atoken != null && atoken.hiddenRequested) 7586 + " mAttachedHidden=" + win.mAttachedHidden); 7587 else Slog.v(TAG, " VIS: mViewVisibility=" 7588 + win.mViewVisibility + " mRelayoutCalled=" 7589 + win.mRelayoutCalled + " hidden=" 7590 + win.mRootToken.hidden + " hiddenRequested=" 7591 + (atoken != null && atoken.hiddenRequested) 7592 + " mAttachedHidden=" + win.mAttachedHidden); 7593 } 7594 7595 // If this view is GONE, then skip it -- keep the current 7596 // frame, and let the caller know so they can ignore it 7597 // if they want. (We do the normal layout for INVISIBLE 7598 // windows, since that means "perform layout as normal, 7599 // just don't display"). 7600 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 7601 || (win.mAttrs.type == TYPE_KEYGUARD && win.isConfigChanged()) 7602 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 7603 if (!win.mLayoutAttached) { 7604 if (initial) { 7605 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 7606 win.mContentChanged = false; 7607 } 7608 if (win.mAttrs.type == TYPE_DREAM) { 7609 // Don't layout windows behind a dream, so that if it 7610 // does stuff like hide the status bar we won't get a 7611 // bad transition when it goes away. 7612 behindDream = true; 7613 } 7614 win.mLayoutNeeded = false; 7615 win.prelayout(); 7616 mPolicy.layoutWindowLw(win, win.mAttrs, null); 7617 win.mLayoutSeq = seq; 7618 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 7619 + win.mFrame + " mContainingFrame=" 7620 + win.mContainingFrame + " mDisplayFrame=" 7621 + win.mDisplayFrame); 7622 } else { 7623 if (topAttached < 0) topAttached = i; 7624 } 7625 } 7626 if (win.mViewVisibility == View.VISIBLE 7627 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 7628 && universeBackground == null) { 7629 universeBackground = win.mWinAnimator; 7630 } 7631 } 7632 7633 if (mAnimator.mUniverseBackground != universeBackground) { 7634 mFocusMayChange = true; 7635 mAnimator.mUniverseBackground = universeBackground; 7636 } 7637 7638 boolean attachedBehindDream = false; 7639 7640 // Now perform layout of attached windows, which usually 7641 // depend on the position of the window they are attached to. 7642 // XXX does not deal with windows that are attached to windows 7643 // that are themselves attached. 7644 for (i = topAttached; i >= 0; i--) { 7645 final WindowState win = windows.get(i); 7646 7647 if (win.mLayoutAttached) { 7648 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 7649 + " mHaveFrame=" + win.mHaveFrame 7650 + " mViewVisibility=" + win.mViewVisibility 7651 + " mRelayoutCalled=" + win.mRelayoutCalled); 7652 // If this view is GONE, then skip it -- keep the current 7653 // frame, and let the caller know so they can ignore it 7654 // if they want. (We do the normal layout for INVISIBLE 7655 // windows, since that means "perform layout as normal, 7656 // just don't display"). 7657 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) { 7658 continue; 7659 } 7660 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 7661 || !win.mHaveFrame || win.mLayoutNeeded) { 7662 if (initial) { 7663 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 7664 win.mContentChanged = false; 7665 } 7666 win.mLayoutNeeded = false; 7667 win.prelayout(); 7668 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 7669 win.mLayoutSeq = seq; 7670 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 7671 + win.mFrame + " mContainingFrame=" 7672 + win.mContainingFrame + " mDisplayFrame=" 7673 + win.mDisplayFrame); 7674 } 7675 } else if (win.mAttrs.type == TYPE_DREAM) { 7676 // Don't layout windows behind a dream, so that if it 7677 // does stuff like hide the status bar we won't get a 7678 // bad transition when it goes away. 7679 attachedBehindDream = behindDream; 7680 } 7681 } 7682 7683 // Window frames may have changed. Tell the input dispatcher about it. 7684 mInputMonitor.setUpdateInputWindowsNeededLw(); 7685 if (updateInputWindows) { 7686 mInputMonitor.updateInputWindowsLw(false /*force*/); 7687 } 7688 7689 mPolicy.finishLayoutLw(); 7690 } 7691 7692 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 7693 // If the screen is currently frozen or off, then keep 7694 // it frozen/off until this window draws at its new 7695 // orientation. 7696 if (!okToDisplay()) { 7697 if (DEBUG_ORIENTATION) Slog.v(TAG, 7698 "Changing surface while display frozen: " + w); 7699 w.mOrientationChanging = true; 7700 mInnerFields.mOrientationChangeComplete = false; 7701 if (!mWindowsFreezingScreen) { 7702 mWindowsFreezingScreen = true; 7703 // XXX should probably keep timeout from 7704 // when we first froze the display. 7705 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 7706 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 7707 WINDOW_FREEZE_TIMEOUT_DURATION); 7708 } 7709 } 7710 } 7711 7712 /** 7713 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 7714 * @param windows List of windows on default display. 7715 * @return bitmap indicating if another pass through layout must be made. 7716 */ 7717 public int handleAppTransitionReadyLocked(WindowList windows) { 7718 int changes = 0; 7719 int i; 7720 int NN = mOpeningApps.size(); 7721 boolean goodToGo = true; 7722 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7723 "Checking " + NN + " opening apps (frozen=" 7724 + mDisplayFrozen + " timeout=" 7725 + mAppTransition.isTimeout() + ")..."); 7726 if (!mDisplayFrozen && !mAppTransition.isTimeout()) { 7727 // If the display isn't frozen, wait to do anything until 7728 // all of the apps are ready. Otherwise just go because 7729 // we'll unfreeze the display when everyone is ready. 7730 for (i=0; i<NN && goodToGo; i++) { 7731 AppWindowToken wtoken = mOpeningApps.get(i); 7732 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7733 "Check opening app=" + wtoken + ": allDrawn=" 7734 + wtoken.allDrawn + " startingDisplayed=" 7735 + wtoken.startingDisplayed + " startingMoved=" 7736 + wtoken.startingMoved); 7737 if (!wtoken.allDrawn && !wtoken.startingDisplayed 7738 && !wtoken.startingMoved) { 7739 goodToGo = false; 7740 } 7741 } 7742 } 7743 if (goodToGo) { 7744 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 7745 int transit = mAppTransition.getAppTransition(); 7746 if (mSkipAppTransitionAnimation) { 7747 transit = AppTransition.TRANSIT_UNSET; 7748 } 7749 mAppTransition.goodToGo(); 7750 mStartingIconInTransition = false; 7751 mSkipAppTransitionAnimation = false; 7752 7753 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 7754 7755 rebuildAppWindowListLocked(); 7756 7757 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 7758 WindowState oldWallpaper = 7759 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 7760 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 7761 ? null : mWallpaperTarget; 7762 7763 mInnerFields.mWallpaperMayChange = false; 7764 7765 // The top-most window will supply the layout params, 7766 // and we will determine it below. 7767 LayoutParams animLp = null; 7768 int bestAnimLayer = -1; 7769 boolean fullscreenAnim = false; 7770 7771 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7772 "New wallpaper target=" + mWallpaperTarget 7773 + ", oldWallpaper=" + oldWallpaper 7774 + ", lower target=" + mLowerWallpaperTarget 7775 + ", upper target=" + mUpperWallpaperTarget); 7776 7777 boolean openingAppHasWallpaper = false; 7778 boolean closingAppHasWallpaper = false; 7779 final AppWindowToken lowerWallpaperAppToken; 7780 final AppWindowToken upperWallpaperAppToken; 7781 if (mLowerWallpaperTarget == null) { 7782 lowerWallpaperAppToken = upperWallpaperAppToken = null; 7783 } else { 7784 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken; 7785 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken; 7786 } 7787 7788 // Do a first pass through the tokens for two 7789 // things: 7790 // (1) Determine if both the closing and opening 7791 // app token sets are wallpaper targets, in which 7792 // case special animations are needed 7793 // (since the wallpaper needs to stay static 7794 // behind them). 7795 // (2) Find the layout params of the top-most 7796 // application window in the tokens, which is 7797 // what will control the animation theme. 7798 final int NC = mClosingApps.size(); 7799 NN = NC + mOpeningApps.size(); 7800 for (i=0; i<NN; i++) { 7801 final AppWindowToken wtoken; 7802 if (i < NC) { 7803 wtoken = mClosingApps.get(i); 7804 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 7805 closingAppHasWallpaper = true; 7806 } 7807 } else { 7808 wtoken = mOpeningApps.get(i - NC); 7809 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 7810 openingAppHasWallpaper = true; 7811 } 7812 } 7813 7814 if (wtoken.appFullscreen) { 7815 WindowState ws = wtoken.findMainWindow(); 7816 if (ws != null) { 7817 animLp = ws.mAttrs; 7818 bestAnimLayer = ws.mLayer; 7819 fullscreenAnim = true; 7820 } 7821 } else if (!fullscreenAnim) { 7822 WindowState ws = wtoken.findMainWindow(); 7823 if (ws != null) { 7824 if (ws.mLayer > bestAnimLayer) { 7825 animLp = ws.mAttrs; 7826 bestAnimLayer = ws.mLayer; 7827 } 7828 } 7829 } 7830 } 7831 7832 if (closingAppHasWallpaper && openingAppHasWallpaper) { 7833 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!"); 7834 switch (transit) { 7835 case AppTransition.TRANSIT_ACTIVITY_OPEN: 7836 case AppTransition.TRANSIT_TASK_OPEN: 7837 case AppTransition.TRANSIT_TASK_TO_FRONT: 7838 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN; 7839 break; 7840 case AppTransition.TRANSIT_ACTIVITY_CLOSE: 7841 case AppTransition.TRANSIT_TASK_CLOSE: 7842 case AppTransition.TRANSIT_TASK_TO_BACK: 7843 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; 7844 break; 7845 } 7846 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); 7847 } else if ((oldWallpaper != null) && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 7848 // We are transitioning from an activity with 7849 // a wallpaper to one without. 7850 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; 7851 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7852 "New transit away from wallpaper: " + transit); 7853 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) { 7854 // We are transitioning from an activity without 7855 // a wallpaper to now showing the wallpaper 7856 transit = AppTransition.TRANSIT_WALLPAPER_OPEN; 7857 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7858 "New transit into wallpaper: " + transit); 7859 } 7860 7861 // If all closing windows are obscured, then there is 7862 // no need to do an animation. This is the case, for 7863 // example, when this transition is being done behind 7864 // the lock screen. 7865 if (!mPolicy.allowAppAnimationsLw()) { 7866 animLp = null; 7867 } 7868 7869 AppWindowToken topOpeningApp = null; 7870 int topOpeningLayer = 0; 7871 7872 NN = mOpeningApps.size(); 7873 for (i=0; i<NN; i++) { 7874 AppWindowToken wtoken = mOpeningApps.get(i); 7875 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 7876 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 7877 appAnimator.clearThumbnail(); 7878 wtoken.inPendingTransaction = false; 7879 appAnimator.animation = null; 7880 setTokenVisibilityLocked(wtoken, animLp, true, transit, false); 7881 wtoken.updateReportedVisibilityLocked(); 7882 wtoken.waitingToShow = false; 7883 7884 appAnimator.mAllAppWinAnimators.clear(); 7885 final int N = wtoken.allAppWindows.size(); 7886 for (int j = 0; j < N; j++) { 7887 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 7888 } 7889 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 7890 7891 if (animLp != null) { 7892 int layer = -1; 7893 for (int j=0; j<wtoken.windows.size(); j++) { 7894 WindowState win = wtoken.windows.get(j); 7895 if (win.mWinAnimator.mAnimLayer > layer) { 7896 layer = win.mWinAnimator.mAnimLayer; 7897 } 7898 } 7899 if (topOpeningApp == null || layer > topOpeningLayer) { 7900 topOpeningApp = wtoken; 7901 topOpeningLayer = layer; 7902 } 7903 } 7904 } 7905 NN = mClosingApps.size(); 7906 for (i=0; i<NN; i++) { 7907 AppWindowToken wtoken = mClosingApps.get(i); 7908 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7909 "Now closing app " + wtoken); 7910 wtoken.mAppAnimator.clearThumbnail(); 7911 wtoken.inPendingTransaction = false; 7912 wtoken.mAppAnimator.animation = null; 7913 setTokenVisibilityLocked(wtoken, animLp, false, 7914 transit, false); 7915 wtoken.updateReportedVisibilityLocked(); 7916 wtoken.waitingToHide = false; 7917 // Force the allDrawn flag, because we want to start 7918 // this guy's animations regardless of whether it's 7919 // gotten drawn. 7920 wtoken.allDrawn = true; 7921 wtoken.deferClearAllDrawn = false; 7922 } 7923 7924 AppWindowAnimator appAnimator = 7925 topOpeningApp == null ? null : topOpeningApp.mAppAnimator; 7926 Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail(); 7927 if (nextAppTransitionThumbnail != null && appAnimator != null 7928 && appAnimator.animation != null) { 7929 // This thumbnail animation is very special, we need to have 7930 // an extra surface with the thumbnail included with the animation. 7931 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(), 7932 nextAppTransitionThumbnail.getHeight()); 7933 try { 7934 // TODO(multi-display): support other displays 7935 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7936 final Display display = displayContent.getDisplay(); 7937 Surface surface = new Surface(mFxSession, 7938 "thumbnail anim", 7939 dirty.width(), dirty.height(), 7940 PixelFormat.TRANSLUCENT, Surface.HIDDEN); 7941 surface.setLayerStack(display.getLayerStack()); 7942 appAnimator.thumbnail = surface; 7943 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surface + ": CREATE"); 7944 Surface drawSurface = new Surface(); 7945 drawSurface.copyFrom(surface); 7946 Canvas c = drawSurface.lockCanvas(dirty); 7947 c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null); 7948 drawSurface.unlockCanvasAndPost(c); 7949 drawSurface.release(); 7950 appAnimator.thumbnailLayer = topOpeningLayer; 7951 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 7952 Animation anim = mAppTransition.createThumbnailAnimationLocked( 7953 transit, true, true, displayInfo.appWidth, displayInfo.appHeight); 7954 appAnimator.thumbnailAnimation = anim; 7955 anim.restrictDuration(MAX_ANIMATION_DURATION); 7956 anim.scaleCurrentDuration(mTransitionAnimationScale); 7957 Point p = new Point(); 7958 mAppTransition.getStartingPoint(p); 7959 appAnimator.thumbnailX = p.x; 7960 appAnimator.thumbnailY = p.y; 7961 } catch (Surface.OutOfResourcesException e) { 7962 Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width() 7963 + " h=" + dirty.height(), e); 7964 appAnimator.clearThumbnail(); 7965 } 7966 } 7967 7968 mAppTransition.postAnimationCallback(); 7969 mAppTransition.clear(); 7970 7971 mOpeningApps.clear(); 7972 mClosingApps.clear(); 7973 7974 // This has changed the visibility of windows, so perform 7975 // a new layout to get them all up-to-date. 7976 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT 7977 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 7978 getDefaultDisplayContentLocked().layoutNeeded = true; 7979 7980 // TODO(multidisplay): IMEs are only supported on the default display. 7981 if (windows == getDefaultWindowListLocked() 7982 && !moveInputMethodWindowsIfNeededLocked(true)) { 7983 assignLayersLocked(windows); 7984 } 7985 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/); 7986 mFocusMayChange = false; 7987 } 7988 7989 return changes; 7990 } 7991 7992 /** 7993 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 7994 * @return bitmap indicating if another pass through layout must be made. 7995 */ 7996 private int handleAnimatingStoppedAndTransitionLocked() { 7997 int changes = 0; 7998 7999 mAppTransition.setIdle(); 8000 // Restore window app tokens to the ActivityManager views 8001 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8002 AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR); 8003 while (iterator.hasNext()) { 8004 iterator.next().sendingToBottom = false; 8005 } 8006 rebuildAppWindowListLocked(); 8007 8008 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8009 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 8010 "Wallpaper layer changed: assigning layers + relayout"); 8011 moveInputMethodWindowsIfNeededLocked(true); 8012 mInnerFields.mWallpaperMayChange = true; 8013 // Since the window list has been rebuilt, focus might 8014 // have to be recomputed since the actual order of windows 8015 // might have changed again. 8016 mFocusMayChange = true; 8017 8018 return changes; 8019 } 8020 8021 private void updateResizingWindows(final WindowState w) { 8022 final WindowStateAnimator winAnimator = w.mWinAnimator; 8023 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { 8024 w.mContentInsetsChanged |= 8025 !w.mLastContentInsets.equals(w.mContentInsets); 8026 w.mVisibleInsetsChanged |= 8027 !w.mLastVisibleInsets.equals(w.mVisibleInsets); 8028 boolean configChanged = w.isConfigChanged(); 8029 if (DEBUG_CONFIGURATION && configChanged) { 8030 Slog.v(TAG, "Win " + w + " config changed: " 8031 + mCurConfiguration); 8032 } 8033 if (localLOGV) Slog.v(TAG, "Resizing " + w 8034 + ": configChanged=" + configChanged 8035 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8036 w.mLastFrame.set(w.mFrame); 8037 if (w.mContentInsetsChanged 8038 || w.mVisibleInsetsChanged 8039 || winAnimator.mSurfaceResized 8040 || configChanged) { 8041 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8042 Slog.v(TAG, "Resize reasons: " 8043 + " contentInsetsChanged=" + w.mContentInsetsChanged 8044 + " " + w.mContentInsets.toShortString() 8045 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8046 + " " + w.mVisibleInsets.toShortString() 8047 + " surfaceResized=" + winAnimator.mSurfaceResized 8048 + " configChanged=" + configChanged); 8049 } 8050 8051 w.mLastContentInsets.set(w.mContentInsets); 8052 w.mLastVisibleInsets.set(w.mVisibleInsets); 8053 makeWindowFreezingScreenIfNeededLocked(w); 8054 // If the orientation is changing, then we need to 8055 // hold off on unfreezing the display until this 8056 // window has been redrawn; to do that, we need 8057 // to go through the process of getting informed 8058 // by the application when it has finished drawing. 8059 if (w.mOrientationChanging) { 8060 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 8061 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 8062 + w + ", surface " + winAnimator.mSurface); 8063 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 8064 if (w.mAppToken != null) { 8065 w.mAppToken.allDrawn = false; 8066 w.mAppToken.deferClearAllDrawn = false; 8067 } 8068 } 8069 if (!mResizingWindows.contains(w)) { 8070 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8071 "Resizing window " + w + " to " + winAnimator.mSurfaceW 8072 + "x" + winAnimator.mSurfaceH); 8073 mResizingWindows.add(w); 8074 } 8075 } else if (w.mOrientationChanging) { 8076 if (w.isDrawnLw()) { 8077 if (DEBUG_ORIENTATION) Slog.v(TAG, 8078 "Orientation not waiting for draw in " 8079 + w + ", surface " + winAnimator.mSurface); 8080 w.mOrientationChanging = false; 8081 } 8082 } 8083 } 8084 } 8085 8086 /** 8087 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8088 * 8089 * @param w WindowState this method is applied to. 8090 * @param currentTime The time which animations use for calculating transitions. 8091 * @param innerDw Width of app window. 8092 * @param innerDh Height of app window. 8093 */ 8094 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 8095 final int innerDw, final int innerDh) { 8096 final WindowManager.LayoutParams attrs = w.mAttrs; 8097 final int attrFlags = attrs.flags; 8098 final boolean canBeSeen = w.isDisplayedLw(); 8099 8100 if (w.mHasSurface) { 8101 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8102 mInnerFields.mHoldScreen = w.mSession; 8103 } 8104 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 8105 && mInnerFields.mScreenBrightness < 0) { 8106 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 8107 } 8108 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 8109 && mInnerFields.mButtonBrightness < 0) { 8110 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 8111 } 8112 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0 8113 && mInnerFields.mUserActivityTimeout < 0) { 8114 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout; 8115 } 8116 8117 final int type = attrs.type; 8118 if (canBeSeen 8119 && (type == TYPE_SYSTEM_DIALOG 8120 || type == TYPE_RECENTS_OVERLAY 8121 || type == TYPE_KEYGUARD 8122 || type == TYPE_SYSTEM_ERROR)) { 8123 mInnerFields.mSyswin = true; 8124 } 8125 8126 if (canBeSeen) { 8127 if (type == TYPE_DREAM || type == TYPE_KEYGUARD) { 8128 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_MIRROR; 8129 } else if (mInnerFields.mDisplayHasContent 8130 == LayoutFields.DISPLAY_CONTENT_UNKNOWN) { 8131 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNIQUE; 8132 } 8133 } 8134 } 8135 8136 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8137 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8138 // This window completely covers everything behind it, 8139 // so we want to leave all of them as undimmed (for 8140 // performance reasons). 8141 mInnerFields.mObscured = true; 8142 } 8143 } 8144 8145 private void handleFlagDimBehind(WindowState w, int innerDw, int innerDh) { 8146 final WindowManager.LayoutParams attrs = w.mAttrs; 8147 if ((attrs.flags & FLAG_DIM_BEHIND) != 0 8148 && w.isDisplayedLw() 8149 && !w.mExiting) { 8150 mInnerFields.mDimming = true; 8151 final WindowStateAnimator winAnimator = w.mWinAnimator; 8152 if (!mAnimator.isDimmingLocked(winAnimator)) { 8153 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming."); 8154 startDimmingLocked(winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount); 8155 } 8156 } 8157 } 8158 8159 private void updateAllDrawnLocked(DisplayContent displayContent) { 8160 // See if any windows have been drawn, so they (and others 8161 // associated with them) can now be shown. 8162 AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR); 8163 while (iterator.hasNext()) { 8164 AppWindowToken wtoken = iterator.next(); 8165 if (!wtoken.allDrawn) { 8166 int numInteresting = wtoken.numInterestingWindows; 8167 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 8168 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, 8169 "allDrawn: " + wtoken 8170 + " interesting=" + numInteresting 8171 + " drawn=" + wtoken.numDrawnWindows); 8172 wtoken.allDrawn = true; 8173 } 8174 } 8175 } 8176 } 8177 8178 // "Something has changed! Let's make it correct now." 8179 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 8180 if (DEBUG_WINDOW_TRACE) { 8181 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 8182 + Debug.getCallers(3)); 8183 } 8184 8185 final long currentTime = SystemClock.uptimeMillis(); 8186 8187 int i; 8188 8189 if (mFocusMayChange) { 8190 mFocusMayChange = false; 8191 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 8192 false /*updateInputWindows*/); 8193 } 8194 8195 // Initialize state of exiting tokens. 8196 DisplayContentsIterator iterator = new DisplayContentsIterator(); 8197 while (iterator.hasNext()) { 8198 final DisplayContent displayContent = iterator.next(); 8199 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) { 8200 displayContent.mExitingTokens.get(i).hasVisible = false; 8201 } 8202 8203 // Initialize state of exiting applications. 8204 for (i=displayContent.mExitingAppTokens.size()-1; i>=0; i--) { 8205 displayContent.mExitingAppTokens.get(i).hasVisible = false; 8206 } 8207 } 8208 8209 mInnerFields.mHoldScreen = null; 8210 mInnerFields.mScreenBrightness = -1; 8211 mInnerFields.mButtonBrightness = -1; 8212 mInnerFields.mUserActivityTimeout = -1; 8213 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN; 8214 8215 mTransactionSequence++; 8216 8217 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked(); 8218 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 8219 final int defaultDw = defaultInfo.logicalWidth; 8220 final int defaultDh = defaultInfo.logicalHeight; 8221 8222 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 8223 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 8224 Surface.openTransaction(); 8225 try { 8226 8227 if (mWatermark != null) { 8228 mWatermark.positionSurface(defaultDw, defaultDh); 8229 } 8230 if (mStrictModeFlash != null) { 8231 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 8232 } 8233 8234 boolean focusDisplayed = false; 8235 8236 iterator = new DisplayContentsIterator(); 8237 while (iterator.hasNext()) { 8238 boolean updateAllDrawn = false; 8239 final DisplayContent displayContent = iterator.next(); 8240 WindowList windows = displayContent.getWindowList(); 8241 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8242 final int displayId = displayContent.getDisplayId(); 8243 final int dw = displayInfo.logicalWidth; 8244 final int dh = displayInfo.logicalHeight; 8245 final int innerDw = displayInfo.appWidth; 8246 final int innerDh = displayInfo.appHeight; 8247 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 8248 8249 // Reset for each display unless we are forcing mirroring. 8250 if (mInnerFields.mDisplayHasContent != LayoutFields.DISPLAY_CONTENT_MIRROR) { 8251 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN; 8252 } 8253 8254 int repeats = 0; 8255 do { 8256 repeats++; 8257 if (repeats > 6) { 8258 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 8259 displayContent.layoutNeeded = false; 8260 break; 8261 } 8262 8263 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 8264 displayContent.pendingLayoutChanges); 8265 8266 if ((displayContent.pendingLayoutChanges & 8267 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 && 8268 (adjustWallpaperWindowsLocked() & 8269 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 8270 assignLayersLocked(windows); 8271 displayContent.layoutNeeded = true; 8272 } 8273 8274 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 8275 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 8276 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 8277 if (updateOrientationFromAppTokensLocked(true)) { 8278 displayContent.layoutNeeded = true; 8279 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8280 } 8281 } 8282 8283 if ((displayContent.pendingLayoutChanges 8284 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 8285 displayContent.layoutNeeded = true; 8286 } 8287 8288 // FIRST LOOP: Perform a layout, if needed. 8289 if (repeats < 4) { 8290 performLayoutLockedInner(displayContent, repeats == 1, 8291 false /*updateInputWindows*/); 8292 } else { 8293 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 8294 } 8295 8296 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 8297 // it is animating. 8298 displayContent.pendingLayoutChanges = 0; 8299 8300 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 8301 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 8302 8303 if (isDefaultDisplay) { 8304 mPolicy.beginPostLayoutPolicyLw(dw, dh); 8305 for (i = windows.size() - 1; i >= 0; i--) { 8306 WindowState w = windows.get(i); 8307 if (w.mHasSurface) { 8308 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); 8309 } 8310 } 8311 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 8312 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 8313 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges); 8314 } 8315 } while (displayContent.pendingLayoutChanges != 0); 8316 8317 mInnerFields.mObscured = false; 8318 mInnerFields.mDimming = false; 8319 mInnerFields.mSyswin = false; 8320 8321 // Only used if default window 8322 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 8323 8324 final int N = windows.size(); 8325 for (i=N-1; i>=0; i--) { 8326 WindowState w = windows.get(i); 8327 8328 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 8329 8330 // Update effect. 8331 w.mObscured = mInnerFields.mObscured; 8332 if (!mInnerFields.mObscured) { 8333 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 8334 } 8335 8336 if (!mInnerFields.mDimming) { 8337 handleFlagDimBehind(w, innerDw, innerDh); 8338 } 8339 8340 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 8341 && w.isVisibleLw()) { 8342 // This is the wallpaper target and its obscured state 8343 // changed... make sure the current wallaper's visibility 8344 // has been updated accordingly. 8345 updateWallpaperVisibilityLocked(); 8346 } 8347 8348 final WindowStateAnimator winAnimator = w.mWinAnimator; 8349 8350 // If the window has moved due to its containing 8351 // content frame changing, then we'd like to animate 8352 // it. 8353 if (w.mHasSurface && w.shouldAnimateMove()) { 8354 // Frame has moved, containing content frame 8355 // has also moved, and we're not currently animating... 8356 // let's do something. 8357 Animation a = AnimationUtils.loadAnimation(mContext, 8358 com.android.internal.R.anim.window_move_from_decor); 8359 winAnimator.setAnimation(a); 8360 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 8361 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 8362 try { 8363 w.mClient.moved(w.mFrame.left, w.mFrame.top); 8364 } catch (RemoteException e) { 8365 } 8366 } 8367 8368 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 8369 w.mContentChanged = false; 8370 8371 // Moved from updateWindowsAndWallpaperLocked(). 8372 if (w.mHasSurface) { 8373 // Take care of the window being ready to display. 8374 final boolean committed = 8375 winAnimator.commitFinishDrawingLocked(currentTime); 8376 if (isDefaultDisplay && committed) { 8377 if (w.mAttrs.type == TYPE_DREAM) { 8378 // HACK: When a dream is shown, it may at that 8379 // point hide the lock screen. So we need to 8380 // redo the layout to let the phone window manager 8381 // make this happen. 8382 displayContent.pendingLayoutChanges |= 8383 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 8384 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 8385 debugLayoutRepeats( 8386 "dream and commitFinishDrawingLocked true", 8387 displayContent.pendingLayoutChanges); 8388 } 8389 } 8390 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 8391 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 8392 "First draw done in potential wallpaper target " + w); 8393 mInnerFields.mWallpaperMayChange = true; 8394 displayContent.pendingLayoutChanges |= 8395 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 8396 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 8397 debugLayoutRepeats( 8398 "wallpaper and commitFinishDrawingLocked true", 8399 displayContent.pendingLayoutChanges); 8400 } 8401 } 8402 } 8403 8404 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 8405 8406 final AppWindowToken atoken = w.mAppToken; 8407 if (DEBUG_STARTING_WINDOW && atoken != null 8408 && w == atoken.startingWindow) { 8409 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 8410 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 8411 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 8412 } 8413 if (atoken != null 8414 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 8415 if (atoken.lastTransactionSequence != mTransactionSequence) { 8416 atoken.lastTransactionSequence = mTransactionSequence; 8417 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 8418 atoken.startingDisplayed = false; 8419 } 8420 if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 8421 && !w.mExiting && !w.mDestroying) { 8422 if (WindowManagerService.DEBUG_VISIBILITY || 8423 WindowManagerService.DEBUG_ORIENTATION) { 8424 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 8425 + ", isAnimating=" + winAnimator.isAnimating()); 8426 if (!w.isDrawnLw()) { 8427 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurface 8428 + " pv=" + w.mPolicyVisibility 8429 + " mDrawState=" + winAnimator.mDrawState 8430 + " ah=" + w.mAttachedHidden 8431 + " th=" + atoken.hiddenRequested 8432 + " a=" + winAnimator.mAnimating); 8433 } 8434 } 8435 if (w != atoken.startingWindow) { 8436 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 8437 atoken.numInterestingWindows++; 8438 if (w.isDrawnLw()) { 8439 atoken.numDrawnWindows++; 8440 if (WindowManagerService.DEBUG_VISIBILITY || 8441 WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG, 8442 "tokenMayBeDrawn: " + atoken 8443 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 8444 + " mAppFreezing=" + w.mAppFreezing); 8445 updateAllDrawn = true; 8446 } 8447 } 8448 } else if (w.isDrawnLw()) { 8449 atoken.startingDisplayed = true; 8450 } 8451 } 8452 } 8453 } 8454 8455 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 8456 && w.isDisplayedLw()) { 8457 focusDisplayed = true; 8458 } 8459 8460 updateResizingWindows(w); 8461 } 8462 8463 final boolean hasUniqueContent; 8464 switch (mInnerFields.mDisplayHasContent) { 8465 case LayoutFields.DISPLAY_CONTENT_MIRROR: 8466 hasUniqueContent = isDefaultDisplay; 8467 break; 8468 case LayoutFields.DISPLAY_CONTENT_UNIQUE: 8469 hasUniqueContent = true; 8470 break; 8471 case LayoutFields.DISPLAY_CONTENT_UNKNOWN: 8472 default: 8473 hasUniqueContent = false; 8474 break; 8475 } 8476 mDisplayManagerService.setDisplayHasContent(displayId, hasUniqueContent, 8477 true /* inTraversal, must call performTraversalInTrans... below */); 8478 8479 if (!mInnerFields.mDimming && mAnimator.isDimmingLocked(displayId)) { 8480 stopDimmingLocked(displayId); 8481 } 8482 8483 if (updateAllDrawn) { 8484 updateAllDrawnLocked(displayContent); 8485 } 8486 } 8487 8488 if (focusDisplayed) { 8489 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 8490 } 8491 8492 // Give the display manager a chance to adjust properties 8493 // like display rotation if it needs to. 8494 mDisplayManagerService.performTraversalInTransactionFromWindowManager(); 8495 8496 } catch (RuntimeException e) { 8497 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 8498 } finally { 8499 Surface.closeTransaction(); 8500 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 8501 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 8502 } 8503 8504 final WindowList defaultWindows = defaultDisplay.getWindowList(); 8505 8506 // If we are ready to perform an app transition, check through 8507 // all of the app tokens to be shown and see if they are ready 8508 // to go. 8509 if (mAppTransition.isReady()) { 8510 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 8511 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 8512 defaultDisplay.pendingLayoutChanges); 8513 } 8514 8515 if (!mAnimator.mAnimating && mAppTransition.isRunning()) { 8516 // We have finished the animation of an app transition. To do 8517 // this, we have delayed a lot of operations like showing and 8518 // hiding apps, moving apps in Z-order, etc. The app token list 8519 // reflects the correct Z-order, but the window list may now 8520 // be out of sync with it. So here we will just rebuild the 8521 // entire app window list. Fun! 8522 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 8523 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 8524 defaultDisplay.pendingLayoutChanges); 8525 } 8526 8527 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 8528 && !mAppTransition.isReady()) { 8529 // At this point, there was a window with a wallpaper that 8530 // was force hiding other windows behind it, but now it 8531 // is going away. This may be simple -- just animate 8532 // away the wallpaper and its window -- or it may be 8533 // hard -- the wallpaper now needs to be shown behind 8534 // something that was hidden. 8535 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 8536 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 8537 defaultDisplay.pendingLayoutChanges); 8538 } 8539 mInnerFields.mWallpaperForceHidingChanged = false; 8540 8541 if (mInnerFields.mWallpaperMayChange) { 8542 if (WindowManagerService.DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 8543 "Wallpaper may change! Adjusting"); 8544 defaultDisplay.pendingLayoutChanges |= 8545 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 8546 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange", 8547 defaultDisplay.pendingLayoutChanges); 8548 } 8549 8550 if (mFocusMayChange) { 8551 mFocusMayChange = false; 8552 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 8553 false /*updateInputWindows*/)) { 8554 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 8555 } 8556 } 8557 8558 if (needsLayout()) { 8559 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 8560 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 8561 defaultDisplay.pendingLayoutChanges); 8562 } 8563 8564 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 8565 WindowState win = mResizingWindows.get(i); 8566 if (win.mAppFreezing) { 8567 // Don't remove this window until rotation has completed. 8568 continue; 8569 } 8570 final WindowStateAnimator winAnimator = win.mWinAnimator; 8571 try { 8572 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8573 "Reporting new frame to " + win + ": " + win.mCompatFrame); 8574 int diff = 0; 8575 boolean configChanged = win.isConfigChanged(); 8576 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) 8577 && configChanged) { 8578 Slog.i(TAG, "Sending new config to window " + win + ": " 8579 + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH 8580 + " / " + mCurConfiguration + " / 0x" 8581 + Integer.toHexString(diff)); 8582 } 8583 win.setConfiguration(mCurConfiguration); 8584 if (DEBUG_ORIENTATION && 8585 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i( 8586 TAG, "Resizing " + win + " WITH DRAW PENDING"); 8587 win.mClient.resized(win.mFrame, win.mLastContentInsets, win.mLastVisibleInsets, 8588 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING, 8589 configChanged ? win.mConfiguration : null); 8590 win.mContentInsetsChanged = false; 8591 win.mVisibleInsetsChanged = false; 8592 winAnimator.mSurfaceResized = false; 8593 } catch (RemoteException e) { 8594 win.mOrientationChanging = false; 8595 } 8596 mResizingWindows.remove(i); 8597 } 8598 8599 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 8600 "With display frozen, orientationChangeComplete=" 8601 + mInnerFields.mOrientationChangeComplete); 8602 if (mInnerFields.mOrientationChangeComplete) { 8603 if (mWindowsFreezingScreen) { 8604 mWindowsFreezingScreen = false; 8605 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8606 } 8607 stopFreezingDisplayLocked(); 8608 } 8609 8610 // Destroy the surface of any windows that are no longer visible. 8611 boolean wallpaperDestroyed = false; 8612 i = mDestroySurface.size(); 8613 if (i > 0) { 8614 do { 8615 i--; 8616 WindowState win = mDestroySurface.get(i); 8617 win.mDestroying = false; 8618 if (mInputMethodWindow == win) { 8619 mInputMethodWindow = null; 8620 } 8621 if (win == mWallpaperTarget) { 8622 wallpaperDestroyed = true; 8623 } 8624 win.mWinAnimator.destroySurfaceLocked(); 8625 } while (i > 0); 8626 mDestroySurface.clear(); 8627 } 8628 8629 // Time to remove any exiting tokens? 8630 iterator = new DisplayContentsIterator(); 8631 while (iterator.hasNext()) { 8632 final DisplayContent displayContent = iterator.next(); 8633 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens; 8634 for (i = exitingTokens.size() - 1; i >= 0; i--) { 8635 WindowToken token = exitingTokens.get(i); 8636 if (!token.hasVisible) { 8637 exitingTokens.remove(i); 8638 if (token.windowType == TYPE_WALLPAPER) { 8639 mWallpaperTokens.remove(token); 8640 } 8641 } 8642 } 8643 8644 // Time to remove any exiting applications? 8645 AppTokenList exitingAppTokens = displayContent.mExitingAppTokens; 8646 for (i = exitingAppTokens.size() - 1; i >= 0; i--) { 8647 AppWindowToken token = exitingAppTokens.get(i); 8648 if (!token.hasVisible && !mClosingApps.contains(token)) { 8649 // Make sure there is no animation running on this token, 8650 // so any windows associated with it will be removed as 8651 // soon as their animations are complete 8652 token.mAppAnimator.clearAnimation(); 8653 token.mAppAnimator.animating = false; 8654 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 8655 "performLayout: App token exiting now removed" + token); 8656 displayContent.removeAppToken(token); 8657 exitingAppTokens.remove(i); 8658 } 8659 } 8660 } 8661 8662 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 8663 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 8664 try { 8665 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 8666 } catch (RemoteException e) { 8667 } 8668 } 8669 mRelayoutWhileAnimating.clear(); 8670 } 8671 8672 if (wallpaperDestroyed) { 8673 defaultDisplay.pendingLayoutChanges |= 8674 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 8675 defaultDisplay.layoutNeeded = true; 8676 } 8677 8678 iterator = new DisplayContentsIterator(); 8679 while (iterator.hasNext()) { 8680 DisplayContent displayContent = iterator.next(); 8681 if (displayContent.pendingLayoutChanges != 0) { 8682 displayContent.layoutNeeded = true; 8683 } 8684 } 8685 8686 // Finally update all input windows now that the window changes have stabilized. 8687 mInputMonitor.updateInputWindowsLw(true /*force*/); 8688 8689 setHoldScreenLocked(mInnerFields.mHoldScreen); 8690 if (!mDisplayFrozen) { 8691 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 8692 mPowerManager.setScreenBrightnessOverrideFromWindowManager(-1); 8693 } else { 8694 mPowerManager.setScreenBrightnessOverrideFromWindowManager( 8695 toBrightnessOverride(mInnerFields.mScreenBrightness)); 8696 } 8697 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 8698 mPowerManager.setButtonBrightnessOverrideFromWindowManager(-1); 8699 } else { 8700 mPowerManager.setButtonBrightnessOverrideFromWindowManager( 8701 toBrightnessOverride(mInnerFields.mButtonBrightness)); 8702 } 8703 mPowerManager.setUserActivityTimeoutOverrideFromWindowManager( 8704 mInnerFields.mUserActivityTimeout); 8705 } 8706 8707 if (mTurnOnScreen) { 8708 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 8709 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 8710 mTurnOnScreen = false; 8711 } 8712 8713 if (mInnerFields.mUpdateRotation) { 8714 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 8715 if (updateRotationUncheckedLocked(false)) { 8716 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8717 } else { 8718 mInnerFields.mUpdateRotation = false; 8719 } 8720 } 8721 8722 if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded 8723 && !mInnerFields.mUpdateRotation) { 8724 checkDrawnWindowsLocked(); 8725 } 8726 8727 final int N = mPendingRemove.size(); 8728 if (N > 0) { 8729 if (mPendingRemoveTmp.length < N) { 8730 mPendingRemoveTmp = new WindowState[N+10]; 8731 } 8732 mPendingRemove.toArray(mPendingRemoveTmp); 8733 mPendingRemove.clear(); 8734 DisplayContentList displayList = new DisplayContentList(); 8735 for (i = 0; i < N; i++) { 8736 WindowState w = mPendingRemoveTmp[i]; 8737 removeWindowInnerLocked(w.mSession, w); 8738 if (!displayList.contains(w.mDisplayContent)) { 8739 displayList.add(w.mDisplayContent); 8740 } 8741 } 8742 8743 for (DisplayContent displayContent : displayList) { 8744 assignLayersLocked(displayContent.getWindowList()); 8745 displayContent.layoutNeeded = true; 8746 } 8747 } 8748 8749 // Check to see if we are now in a state where the screen should 8750 // be enabled, because the window obscured flags have changed. 8751 enableScreenIfNeededLocked(); 8752 8753 scheduleAnimationLocked(); 8754 8755 if (DEBUG_WINDOW_TRACE) { 8756 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" 8757 + mAnimator.mAnimating); 8758 } 8759 } 8760 8761 private int toBrightnessOverride(float value) { 8762 return (int)(value * PowerManager.BRIGHTNESS_ON); 8763 } 8764 8765 void checkDrawnWindowsLocked() { 8766 if (mWaitingForDrawn.size() > 0) { 8767 for (int j=mWaitingForDrawn.size()-1; j>=0; j--) { 8768 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j); 8769 WindowState win = pair.first; 8770 //Slog.i(TAG, "Waiting for drawn " + win + ": removed=" 8771 // + win.mRemoved + " visible=" + win.isVisibleLw() 8772 // + " shown=" + win.mSurfaceShown); 8773 if (win.mRemoved || !win.isVisibleLw()) { 8774 // Window has been removed or made invisible; no draw 8775 // will now happen, so stop waiting. 8776 Slog.w(TAG, "Aborted waiting for drawn: " + pair.first); 8777 try { 8778 pair.second.sendResult(null); 8779 } catch (RemoteException e) { 8780 } 8781 mWaitingForDrawn.remove(pair); 8782 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 8783 } else if (win.mWinAnimator.mSurfaceShown) { 8784 // Window is now drawn (and shown). 8785 try { 8786 pair.second.sendResult(null); 8787 } catch (RemoteException e) { 8788 } 8789 mWaitingForDrawn.remove(pair); 8790 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 8791 } 8792 } 8793 } 8794 } 8795 8796 @Override 8797 public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) { 8798 if (token != null && callback != null) { 8799 synchronized (mWindowMap) { 8800 WindowState win = windowForClientLocked(null, token, true); 8801 if (win != null) { 8802 Pair<WindowState, IRemoteCallback> pair = 8803 new Pair<WindowState, IRemoteCallback>(win, callback); 8804 Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 8805 mH.sendMessageDelayed(m, 2000); 8806 mWaitingForDrawn.add(pair); 8807 checkDrawnWindowsLocked(); 8808 return true; 8809 } 8810 } 8811 } 8812 return false; 8813 } 8814 8815 void setHoldScreenLocked(final Session newHoldScreen) { 8816 final boolean hold = newHoldScreen != null; 8817 8818 if (hold && mHoldingScreenOn != newHoldScreen) { 8819 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 8820 } 8821 mHoldingScreenOn = newHoldScreen; 8822 8823 final boolean state = mHoldingScreenWakeLock.isHeld(); 8824 if (hold != state) { 8825 if (hold) { 8826 mHoldingScreenWakeLock.acquire(); 8827 mPolicy.keepScreenOnStartedLw(); 8828 } else { 8829 mPolicy.keepScreenOnStoppedLw(); 8830 mHoldingScreenWakeLock.release(); 8831 } 8832 } 8833 } 8834 8835 @Override 8836 public void requestTraversal() { 8837 synchronized (mWindowMap) { 8838 requestTraversalLocked(); 8839 } 8840 } 8841 8842 void requestTraversalLocked() { 8843 if (!mTraversalScheduled) { 8844 mTraversalScheduled = true; 8845 mH.sendEmptyMessage(H.DO_TRAVERSAL); 8846 } 8847 } 8848 8849 /** Note that Locked in this case is on mLayoutToAnim */ 8850 void scheduleAnimationLocked() { 8851 if (!mAnimationScheduled) { 8852 mAnimationScheduled = true; 8853 mChoreographer.postCallback( 8854 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 8855 } 8856 } 8857 8858 void startDimmingLocked(final WindowStateAnimator winAnimator, final float target) { 8859 mAnimator.setDimWinAnimatorLocked(winAnimator.mWin.getDisplayId(), winAnimator); 8860 } 8861 8862 void stopDimmingLocked(int displayId) { 8863 mAnimator.setDimWinAnimatorLocked(displayId, null); 8864 } 8865 8866 private boolean needsLayout() { 8867 DisplayContentsIterator iterator = new DisplayContentsIterator(); 8868 while (iterator.hasNext()) { 8869 if (iterator.next().layoutNeeded) { 8870 return true; 8871 } 8872 } 8873 return false; 8874 } 8875 8876 boolean copyAnimToLayoutParamsLocked() { 8877 boolean doRequest = false; 8878 8879 final int bulkUpdateParams = mAnimator.mBulkUpdateParams; 8880 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 8881 mInnerFields.mUpdateRotation = true; 8882 doRequest = true; 8883 } 8884 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 8885 mInnerFields.mWallpaperMayChange = true; 8886 doRequest = true; 8887 } 8888 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 8889 mInnerFields.mWallpaperForceHidingChanged = true; 8890 doRequest = true; 8891 } 8892 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 8893 mInnerFields.mOrientationChangeComplete = false; 8894 } else { 8895 mInnerFields.mOrientationChangeComplete = true; 8896 if (mWindowsFreezingScreen) { 8897 doRequest = true; 8898 } 8899 } 8900 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 8901 mTurnOnScreen = true; 8902 } 8903 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) { 8904 mInnerFields.mWallpaperActionPending = true; 8905 } 8906 8907 return doRequest; 8908 } 8909 8910 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 8911 boolean secure) { 8912 final Surface surface = winAnimator.mSurface; 8913 boolean leakedSurface = false; 8914 boolean killedApps = false; 8915 8916 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 8917 winAnimator.mSession.mPid, operation); 8918 8919 if (mForceRemoves == null) { 8920 mForceRemoves = new ArrayList<WindowState>(); 8921 } 8922 8923 long callingIdentity = Binder.clearCallingIdentity(); 8924 try { 8925 // There was some problem... first, do a sanity check of the 8926 // window list to make sure we haven't left any dangling surfaces 8927 // around. 8928 8929 mTmpWindowsIterator.reset(FORWARD_ITERATOR); 8930 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 8931 while (mTmpWindowsIterator.hasNext()) { 8932 WindowState ws = mTmpWindowsIterator.next(); 8933 WindowStateAnimator wsa = ws.mWinAnimator; 8934 if (wsa.mSurface != null) { 8935 if (!mSessions.contains(wsa.mSession)) { 8936 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 8937 + ws + " surface=" + wsa.mSurface 8938 + " token=" + ws.mToken 8939 + " pid=" + ws.mSession.mPid 8940 + " uid=" + ws.mSession.mUid); 8941 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 8942 wsa.mSurface.destroy(); 8943 wsa.mSurfaceShown = false; 8944 wsa.mSurface = null; 8945 ws.mHasSurface = false; 8946 mForceRemoves.add(ws); 8947 leakedSurface = true; 8948 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 8949 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 8950 + ws + " surface=" + wsa.mSurface 8951 + " token=" + ws.mAppToken); 8952 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 8953 wsa.mSurface.destroy(); 8954 wsa.mSurfaceShown = false; 8955 wsa.mSurface = null; 8956 ws.mHasSurface = false; 8957 leakedSurface = true; 8958 } 8959 } 8960 } 8961 8962 if (!leakedSurface) { 8963 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 8964 SparseIntArray pidCandidates = new SparseIntArray(); 8965 mTmpWindowsIterator.reset(FORWARD_ITERATOR); 8966 while (mTmpWindowsIterator.hasNext()) { 8967 WindowState ws = mTmpWindowsIterator.next(); 8968 if (mForceRemoves.contains(ws)) { 8969 continue; 8970 } 8971 WindowStateAnimator wsa = ws.mWinAnimator; 8972 if (wsa.mSurface != null) { 8973 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 8974 } 8975 } 8976 if (pidCandidates.size() > 0) { 8977 int[] pids = new int[pidCandidates.size()]; 8978 for (int i=0; i<pids.length; i++) { 8979 pids[i] = pidCandidates.keyAt(i); 8980 } 8981 try { 8982 if (mActivityManager.killPids(pids, "Free memory", secure)) { 8983 killedApps = true; 8984 } 8985 } catch (RemoteException e) { 8986 } 8987 } 8988 } 8989 8990 if (leakedSurface || killedApps) { 8991 // We managed to reclaim some memory, so get rid of the trouble 8992 // surface and ask the app to request another one. 8993 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 8994 if (surface != null) { 8995 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 8996 "RECOVER DESTROY", null); 8997 surface.destroy(); 8998 winAnimator.mSurfaceShown = false; 8999 winAnimator.mSurface = null; 9000 winAnimator.mWin.mHasSurface = false; 9001 } 9002 9003 try { 9004 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9005 } catch (RemoteException e) { 9006 } 9007 } 9008 } finally { 9009 Binder.restoreCallingIdentity(callingIdentity); 9010 } 9011 9012 return leakedSurface || killedApps; 9013 } 9014 9015 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9016 WindowState newFocus = computeFocusedWindowLocked(); 9017 if (mCurrentFocus != newFocus) { 9018 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9019 // This check makes sure that we don't already have the focus 9020 // change message pending. 9021 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9022 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9023 if (localLOGV) Slog.v( 9024 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus); 9025 final WindowState oldFocus = mCurrentFocus; 9026 mCurrentFocus = newFocus; 9027 mAnimator.setCurrentFocus(newFocus); 9028 mLosingFocus.remove(newFocus); 9029 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9030 9031 // TODO(multidisplay): Focused windows on default display only. 9032 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9033 9034 final WindowState imWindow = mInputMethodWindow; 9035 if (newFocus != imWindow && oldFocus != imWindow) { 9036 if (moveInputMethodWindowsIfNeededLocked( 9037 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS && 9038 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) { 9039 displayContent.layoutNeeded = true; 9040 } 9041 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9042 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9043 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9044 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9045 // Client will do the layout, but we need to assign layers 9046 // for handleNewWindowLocked() below. 9047 assignLayersLocked(displayContent.getWindowList()); 9048 } 9049 } 9050 9051 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9052 // The change in focus caused us to need to do a layout. Okay. 9053 displayContent.layoutNeeded = true; 9054 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9055 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9056 } 9057 } 9058 9059 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9060 // If we defer assigning layers, then the caller is responsible for 9061 // doing this part. 9062 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 9063 } 9064 9065 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9066 return true; 9067 } 9068 return false; 9069 } 9070 9071 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 9072 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9073 } 9074 9075 private WindowState computeFocusedWindowLocked() { 9076 if (mAnimator.mUniverseBackground != null 9077 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 9078 return mAnimator.mUniverseBackground.mWin; 9079 } 9080 9081 final int displayCount = mDisplayContents.size(); 9082 for (int i = 0; i < displayCount; i++) { 9083 final DisplayContent displayContent = mDisplayContents.valueAt(i); 9084 WindowState win = findFocusedWindowLocked(displayContent); 9085 if (win != null) { 9086 return win; 9087 } 9088 } 9089 return null; 9090 } 9091 9092 private WindowState findFocusedWindowLocked(DisplayContent displayContent) { 9093 AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR); 9094 WindowToken nextApp = iterator.hasNext() ? iterator.next() : null; 9095 9096 final WindowList windows = displayContent.getWindowList(); 9097 for (int i = windows.size() - 1; i >= 0; i--) { 9098 final WindowState win = windows.get(i); 9099 9100 if (localLOGV || DEBUG_FOCUS) Slog.v( 9101 TAG, "Looking for focus: " + i 9102 + " = " + win 9103 + ", flags=" + win.mAttrs.flags 9104 + ", canReceive=" + win.canReceiveKeys()); 9105 9106 AppWindowToken thisApp = win.mAppToken; 9107 9108 // If this window's application has been removed, just skip it. 9109 if (thisApp != null && (thisApp.removed || thisApp.sendingToBottom)) { 9110 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping app because " + (thisApp.removed 9111 ? "removed" : "sendingToBottom")); 9112 continue; 9113 } 9114 9115 // If there is a focused app, don't allow focus to go to any 9116 // windows below it. If this is an application window, step 9117 // through the app tokens until we find its app. 9118 if (thisApp != null && nextApp != null && thisApp != nextApp 9119 && win.mAttrs.type != TYPE_APPLICATION_STARTING) { 9120 final WindowToken origAppToken = nextApp; 9121 while (iterator.hasNext()) { 9122 if (nextApp == mFocusedApp) { 9123 // Whoops, we are below the focused app... no focus 9124 // for you! 9125 if (localLOGV || DEBUG_FOCUS) Slog.v( 9126 TAG, "Reached focused app: " + mFocusedApp); 9127 return null; 9128 } 9129 nextApp = iterator.next(); 9130 if (nextApp == thisApp) { 9131 break; 9132 } 9133 } 9134 if (thisApp != nextApp) { 9135 // Uh oh, the app token doesn't exist! This shouldn't 9136 // happen, but if it does we can get totally hosed... 9137 // so restart at the original app. 9138 nextApp = origAppToken; 9139 iterator = displayContent.new AppTokenIterator(true); 9140 while (iterator.hasNext()) { 9141 // return iterator to same place. 9142 if (iterator.next() == origAppToken) { 9143 break; 9144 } 9145 } 9146 } 9147 } 9148 9149 // Dispatch to this window if it is wants key events. 9150 if (win.canReceiveKeys()) { 9151 if (DEBUG_FOCUS) Slog.v( 9152 TAG, "Found focus @ " + i + " = " + win); 9153 return win; 9154 } 9155 } 9156 return null; 9157 } 9158 9159 private void startFreezingDisplayLocked(boolean inTransaction, 9160 int exitAnim, int enterAnim) { 9161 if (mDisplayFrozen) { 9162 return; 9163 } 9164 9165 if (!mDisplayReady || !mPolicy.isScreenOnFully()) { 9166 // No need to freeze the screen before the system is ready or if 9167 // the screen is off. 9168 return; 9169 } 9170 9171 mScreenFrozenLock.acquire(); 9172 9173 mDisplayFrozen = true; 9174 9175 mInputMonitor.freezeInputDispatchingLw(); 9176 9177 // Clear the last input window -- that is just used for 9178 // clean transitions between IMEs, and if we are freezing 9179 // the screen then the whole world is changing behind the scenes. 9180 mPolicy.setLastInputMethodWindowLw(null, null); 9181 9182 if (mAppTransition.isTransitionSet()) { 9183 mAppTransition.freeze(); 9184 } 9185 9186 if (PROFILE_ORIENTATION) { 9187 File file = new File("/data/system/frozen"); 9188 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 9189 } 9190 9191 if (CUSTOM_SCREEN_ROTATION) { 9192 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9193 final int displayId = displayContent.getDisplayId(); 9194 ScreenRotationAnimation screenRotationAnimation = 9195 mAnimator.getScreenRotationAnimationLocked(displayId); 9196 if (screenRotationAnimation != null) { 9197 screenRotationAnimation.kill(); 9198 } 9199 9200 // TODO(multidisplay): rotation on main screen only. 9201 final Display display = displayContent.getDisplay(); 9202 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9203 screenRotationAnimation = new ScreenRotationAnimation(mContext, 9204 display, mFxSession, inTransaction, displayInfo.logicalWidth, 9205 displayInfo.logicalHeight, display.getRotation(), 9206 exitAnim, enterAnim); 9207 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 9208 } 9209 } 9210 9211 private void stopFreezingDisplayLocked() { 9212 if (!mDisplayFrozen) { 9213 return; 9214 } 9215 9216 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen 9217 || mClientFreezingScreen) { 9218 if (DEBUG_ORIENTATION) Slog.d(TAG, 9219 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 9220 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 9221 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 9222 + ", mClientFreezingScreen=" + mClientFreezingScreen); 9223 return; 9224 } 9225 9226 mDisplayFrozen = false; 9227 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 9228 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 9229 if (PROFILE_ORIENTATION) { 9230 Debug.stopMethodTracing(); 9231 } 9232 9233 boolean updateRotation = false; 9234 9235 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9236 final int displayId = displayContent.getDisplayId(); 9237 ScreenRotationAnimation screenRotationAnimation = 9238 mAnimator.getScreenRotationAnimationLocked(displayId); 9239 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 9240 && screenRotationAnimation.hasScreenshot()) { 9241 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 9242 // TODO(multidisplay): rotation on main screen only. 9243 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9244 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 9245 mTransitionAnimationScale, displayInfo.logicalWidth, 9246 displayInfo.logicalHeight)) { 9247 scheduleAnimationLocked(); 9248 } else { 9249 screenRotationAnimation.kill(); 9250 screenRotationAnimation = null; 9251 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 9252 updateRotation = true; 9253 } 9254 } else { 9255 if (screenRotationAnimation != null) { 9256 screenRotationAnimation.kill(); 9257 screenRotationAnimation = null; 9258 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 9259 } 9260 updateRotation = true; 9261 } 9262 9263 mInputMonitor.thawInputDispatchingLw(); 9264 9265 boolean configChanged; 9266 9267 // While the display is frozen we don't re-compute the orientation 9268 // to avoid inconsistent states. However, something interesting 9269 // could have actually changed during that time so re-evaluate it 9270 // now to catch that. 9271 configChanged = updateOrientationFromAppTokensLocked(false); 9272 9273 // A little kludge: a lot could have happened while the 9274 // display was frozen, so now that we are coming back we 9275 // do a gc so that any remote references the system 9276 // processes holds on others can be released if they are 9277 // no longer needed. 9278 mH.removeMessages(H.FORCE_GC); 9279 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 9280 9281 mScreenFrozenLock.release(); 9282 9283 if (updateRotation) { 9284 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9285 configChanged |= updateRotationUncheckedLocked(false); 9286 } 9287 9288 if (configChanged) { 9289 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9290 } 9291 } 9292 9293 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 9294 DisplayMetrics dm) { 9295 if (index < tokens.length) { 9296 String str = tokens[index]; 9297 if (str != null && str.length() > 0) { 9298 try { 9299 int val = Integer.parseInt(str); 9300 return val; 9301 } catch (Exception e) { 9302 } 9303 } 9304 } 9305 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 9306 return defDps; 9307 } 9308 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 9309 return val; 9310 } 9311 9312 void createWatermarkInTransaction() { 9313 if (mWatermark != null) { 9314 return; 9315 } 9316 9317 File file = new File("/system/etc/setup.conf"); 9318 FileInputStream in = null; 9319 DataInputStream ind = null; 9320 try { 9321 in = new FileInputStream(file); 9322 ind = new DataInputStream(in); 9323 String line = ind.readLine(); 9324 if (line != null) { 9325 String[] toks = line.split("%"); 9326 if (toks != null && toks.length > 0) { 9327 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 9328 mRealDisplayMetrics, mFxSession, toks); 9329 } 9330 } 9331 } catch (FileNotFoundException e) { 9332 } catch (IOException e) { 9333 } finally { 9334 if (ind != null) { 9335 try { 9336 ind.close(); 9337 } catch (IOException e) { 9338 } 9339 } else if (in != null) { 9340 try { 9341 in.close(); 9342 } catch (IOException e) { 9343 } 9344 } 9345 } 9346 } 9347 9348 @Override 9349 public void statusBarVisibilityChanged(int visibility) { 9350 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 9351 != PackageManager.PERMISSION_GRANTED) { 9352 throw new SecurityException("Caller does not hold permission " 9353 + android.Manifest.permission.STATUS_BAR); 9354 } 9355 9356 synchronized (mWindowMap) { 9357 mLastStatusBarVisibility = visibility; 9358 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 9359 updateStatusBarVisibilityLocked(visibility); 9360 } 9361 } 9362 9363 // TOOD(multidisplay): StatusBar on multiple screens? 9364 void updateStatusBarVisibilityLocked(int visibility) { 9365 mInputManager.setSystemUiVisibility(visibility); 9366 final WindowList windows = getDefaultWindowListLocked(); 9367 final int N = windows.size(); 9368 for (int i = 0; i < N; i++) { 9369 WindowState ws = windows.get(i); 9370 try { 9371 int curValue = ws.mSystemUiVisibility; 9372 int diff = curValue ^ visibility; 9373 // We are only interested in differences of one of the 9374 // clearable flags... 9375 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 9376 // ...if it has actually been cleared. 9377 diff &= ~visibility; 9378 int newValue = (curValue&~diff) | (visibility&diff); 9379 if (newValue != curValue) { 9380 ws.mSeq++; 9381 ws.mSystemUiVisibility = newValue; 9382 } 9383 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 9384 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 9385 visibility, newValue, diff); 9386 } 9387 } catch (RemoteException e) { 9388 // so sorry 9389 } 9390 } 9391 } 9392 9393 @Override 9394 public void reevaluateStatusBarVisibility() { 9395 synchronized (mWindowMap) { 9396 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 9397 updateStatusBarVisibilityLocked(visibility); 9398 performLayoutAndPlaceSurfacesLocked(); 9399 } 9400 } 9401 9402 @Override 9403 public FakeWindow addFakeWindow(Looper looper, 9404 InputEventReceiver.Factory inputEventReceiverFactory, 9405 String name, int windowType, int layoutParamsFlags, boolean canReceiveKeys, 9406 boolean hasFocus, boolean touchFullscreen) { 9407 synchronized (mWindowMap) { 9408 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 9409 name, windowType, 9410 layoutParamsFlags, canReceiveKeys, hasFocus, touchFullscreen); 9411 int i=0; 9412 while (i<mFakeWindows.size()) { 9413 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 9414 break; 9415 } 9416 } 9417 mFakeWindows.add(i, fw); 9418 mInputMonitor.updateInputWindowsLw(true); 9419 return fw; 9420 } 9421 } 9422 9423 boolean removeFakeWindowLocked(FakeWindow window) { 9424 synchronized (mWindowMap) { 9425 if (mFakeWindows.remove(window)) { 9426 mInputMonitor.updateInputWindowsLw(true); 9427 return true; 9428 } 9429 return false; 9430 } 9431 } 9432 9433 // It is assumed that this method is called only by InputMethodManagerService. 9434 public void saveLastInputMethodWindowForTransition() { 9435 synchronized (mWindowMap) { 9436 // TODO(multidisplay): Pass in the displayID. 9437 DisplayContent displayContent = getDefaultDisplayContentLocked(); 9438 if (mInputMethodWindow != null) { 9439 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 9440 } 9441 } 9442 } 9443 9444 @Override 9445 public boolean hasNavigationBar() { 9446 return mPolicy.hasNavigationBar(); 9447 } 9448 9449 @Override 9450 public void lockNow(Bundle options) { 9451 mPolicy.lockNow(options); 9452 } 9453 9454 @Override 9455 public boolean isSafeModeEnabled() { 9456 return mSafeMode; 9457 } 9458 9459 @Override 9460 public void showAssistant() { 9461 // TODO: What permission? 9462 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER) 9463 != PackageManager.PERMISSION_GRANTED) { 9464 return; 9465 } 9466 mPolicy.showAssistant(); 9467 } 9468 9469 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 9470 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 9471 mPolicy.dump(" ", pw, args); 9472 } 9473 9474 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 9475 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 9476 mAnimator.dumpLocked(pw, " ", dumpAll); 9477 } 9478 9479 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 9480 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 9481 if (mTokenMap.size() > 0) { 9482 pw.println(" All tokens:"); 9483 Iterator<WindowToken> it = mTokenMap.values().iterator(); 9484 while (it.hasNext()) { 9485 WindowToken token = it.next(); 9486 pw.print(" "); pw.print(token); 9487 if (dumpAll) { 9488 pw.println(':'); 9489 token.dump(pw, " "); 9490 } else { 9491 pw.println(); 9492 } 9493 } 9494 } 9495 if (mWallpaperTokens.size() > 0) { 9496 pw.println(); 9497 pw.println(" Wallpaper tokens:"); 9498 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 9499 WindowToken token = mWallpaperTokens.get(i); 9500 pw.print(" Wallpaper #"); pw.print(i); 9501 pw.print(' '); pw.print(token); 9502 if (dumpAll) { 9503 pw.println(':'); 9504 token.dump(pw, " "); 9505 } else { 9506 pw.println(); 9507 } 9508 } 9509 } 9510 if (mFinishedStarting.size() > 0) { 9511 pw.println(); 9512 pw.println(" Finishing start of application tokens:"); 9513 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 9514 WindowToken token = mFinishedStarting.get(i); 9515 pw.print(" Finished Starting #"); pw.print(i); 9516 pw.print(' '); pw.print(token); 9517 if (dumpAll) { 9518 pw.println(':'); 9519 token.dump(pw, " "); 9520 } else { 9521 pw.println(); 9522 } 9523 } 9524 } 9525 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 9526 pw.println(); 9527 if (mOpeningApps.size() > 0) { 9528 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 9529 } 9530 if (mClosingApps.size() > 0) { 9531 pw.print(" mClosingApps="); pw.println(mClosingApps); 9532 } 9533 } 9534 } 9535 9536 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 9537 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 9538 if (mSessions.size() > 0) { 9539 Iterator<Session> it = mSessions.iterator(); 9540 while (it.hasNext()) { 9541 Session s = it.next(); 9542 pw.print(" Session "); pw.print(s); pw.println(':'); 9543 s.dump(pw, " "); 9544 } 9545 } 9546 } 9547 9548 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 9549 ArrayList<WindowState> windows) { 9550 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 9551 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 9552 } 9553 9554 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 9555 ArrayList<WindowState> windows) { 9556 int j = 0; 9557 mTmpWindowsIterator.reset(REVERSE_ITERATOR); 9558 while (mTmpWindowsIterator.hasNext()) { 9559 final WindowState w = mTmpWindowsIterator.next(); 9560 if (windows == null || windows.contains(w)) { 9561 pw.print(" Window #"); pw.print(j++); pw.print(' '); 9562 pw.print(w); pw.println(":"); 9563 w.dump(pw, " ", dumpAll || windows != null); 9564 } 9565 } 9566 if (mInputMethodDialogs.size() > 0) { 9567 pw.println(); 9568 pw.println(" Input method dialogs:"); 9569 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 9570 WindowState w = mInputMethodDialogs.get(i); 9571 if (windows == null || windows.contains(w)) { 9572 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 9573 } 9574 } 9575 } 9576 if (mPendingRemove.size() > 0) { 9577 pw.println(); 9578 pw.println(" Remove pending for:"); 9579 for (int i=mPendingRemove.size()-1; i>=0; i--) { 9580 WindowState w = mPendingRemove.get(i); 9581 if (windows == null || windows.contains(w)) { 9582 pw.print(" Remove #"); pw.print(i); pw.print(' '); 9583 pw.print(w); 9584 if (dumpAll) { 9585 pw.println(":"); 9586 w.dump(pw, " ", true); 9587 } else { 9588 pw.println(); 9589 } 9590 } 9591 } 9592 } 9593 if (mForceRemoves != null && mForceRemoves.size() > 0) { 9594 pw.println(); 9595 pw.println(" Windows force removing:"); 9596 for (int i=mForceRemoves.size()-1; i>=0; i--) { 9597 WindowState w = mForceRemoves.get(i); 9598 pw.print(" Removing #"); pw.print(i); pw.print(' '); 9599 pw.print(w); 9600 if (dumpAll) { 9601 pw.println(":"); 9602 w.dump(pw, " ", true); 9603 } else { 9604 pw.println(); 9605 } 9606 } 9607 } 9608 if (mDestroySurface.size() > 0) { 9609 pw.println(); 9610 pw.println(" Windows waiting to destroy their surface:"); 9611 for (int i=mDestroySurface.size()-1; i>=0; i--) { 9612 WindowState w = mDestroySurface.get(i); 9613 if (windows == null || windows.contains(w)) { 9614 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 9615 pw.print(w); 9616 if (dumpAll) { 9617 pw.println(":"); 9618 w.dump(pw, " ", true); 9619 } else { 9620 pw.println(); 9621 } 9622 } 9623 } 9624 } 9625 if (mLosingFocus.size() > 0) { 9626 pw.println(); 9627 pw.println(" Windows losing focus:"); 9628 for (int i=mLosingFocus.size()-1; i>=0; i--) { 9629 WindowState w = mLosingFocus.get(i); 9630 if (windows == null || windows.contains(w)) { 9631 pw.print(" Losing #"); pw.print(i); pw.print(' '); 9632 pw.print(w); 9633 if (dumpAll) { 9634 pw.println(":"); 9635 w.dump(pw, " ", true); 9636 } else { 9637 pw.println(); 9638 } 9639 } 9640 } 9641 } 9642 if (mResizingWindows.size() > 0) { 9643 pw.println(); 9644 pw.println(" Windows waiting to resize:"); 9645 for (int i=mResizingWindows.size()-1; i>=0; i--) { 9646 WindowState w = mResizingWindows.get(i); 9647 if (windows == null || windows.contains(w)) { 9648 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 9649 pw.print(w); 9650 if (dumpAll) { 9651 pw.println(":"); 9652 w.dump(pw, " ", true); 9653 } else { 9654 pw.println(); 9655 } 9656 } 9657 } 9658 } 9659 if (mWaitingForDrawn.size() > 0) { 9660 pw.println(); 9661 pw.println(" Clients waiting for these windows to be drawn:"); 9662 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 9663 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i); 9664 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first); 9665 pw.print(": "); pw.println(pair.second); 9666 } 9667 } 9668 pw.println(); 9669 pw.println(" DisplayContents:"); 9670 if (mDisplayReady) { 9671 DisplayContentsIterator dCIterator = new DisplayContentsIterator(); 9672 while (dCIterator.hasNext()) { 9673 dCIterator.next().dump(" ", pw); 9674 } 9675 } else { 9676 pw.println(" NO DISPLAY"); 9677 } 9678 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 9679 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 9680 if (mLastFocus != mCurrentFocus) { 9681 pw.print(" mLastFocus="); pw.println(mLastFocus); 9682 } 9683 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 9684 if (mInputMethodTarget != null) { 9685 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 9686 } 9687 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 9688 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 9689 if (dumpAll) { 9690 pw.print(" mSystemDecorRect="); pw.print(mSystemDecorRect.toShortString()); 9691 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 9692 pw.print(" mScreenRecr="); pw.println(mScreenRect.toShortString()); 9693 if (mLastStatusBarVisibility != 0) { 9694 pw.print(" mLastStatusBarVisibility=0x"); 9695 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 9696 } 9697 if (mInputMethodWindow != null) { 9698 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 9699 } 9700 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 9701 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) { 9702 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 9703 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 9704 } 9705 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 9706 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 9707 if (mInputMethodAnimLayerAdjustment != 0 || 9708 mWallpaperAnimLayerAdjustment != 0) { 9709 pw.print(" mInputMethodAnimLayerAdjustment="); 9710 pw.print(mInputMethodAnimLayerAdjustment); 9711 pw.print(" mWallpaperAnimLayerAdjustment="); 9712 pw.println(mWallpaperAnimLayerAdjustment); 9713 } 9714 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 9715 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 9716 if (needsLayout()) { 9717 pw.print(" layoutNeeded on displays="); 9718 DisplayContentsIterator dcIterator = new DisplayContentsIterator(); 9719 while (dcIterator.hasNext()) { 9720 final DisplayContent displayContent = dcIterator.next(); 9721 if (displayContent.layoutNeeded) { 9722 pw.print(displayContent.getDisplayId()); 9723 } 9724 } 9725 pw.println(); 9726 } 9727 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 9728 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 9729 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 9730 pw.print(" client="); pw.print(mClientFreezingScreen); 9731 pw.print(" apps="); pw.print(mAppsFreezingScreen); 9732 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 9733 pw.print(" mRotation="); pw.print(mRotation); 9734 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 9735 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 9736 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 9737 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 9738 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); 9739 pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale); 9740 pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale); 9741 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); 9742 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 9743 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 9744 pw.println(" mLayoutToAnim:"); 9745 mAppTransition.dump(pw); 9746 } 9747 } 9748 9749 boolean dumpWindows(PrintWriter pw, String name, String[] args, 9750 int opti, boolean dumpAll) { 9751 WindowList windows = new WindowList(); 9752 if ("visible".equals(name)) { 9753 synchronized(mWindowMap) { 9754 mTmpWindowsIterator.reset(REVERSE_ITERATOR); 9755 while (mTmpWindowsIterator.hasNext()) { 9756 final WindowState w = mTmpWindowsIterator.next(); 9757 if (w.mWinAnimator.mSurfaceShown) { 9758 windows.add(w); 9759 } 9760 } 9761 } 9762 } else { 9763 int objectId = 0; 9764 // See if this is an object ID. 9765 try { 9766 objectId = Integer.parseInt(name, 16); 9767 name = null; 9768 } catch (RuntimeException e) { 9769 } 9770 synchronized(mWindowMap) { 9771 mTmpWindowsIterator.reset(REVERSE_ITERATOR); 9772 while (mTmpWindowsIterator.hasNext()) { 9773 final WindowState w = mTmpWindowsIterator.next(); 9774 if (name != null) { 9775 if (w.mAttrs.getTitle().toString().contains(name)) { 9776 windows.add(w); 9777 } 9778 } else if (System.identityHashCode(w) == objectId) { 9779 windows.add(w); 9780 } 9781 } 9782 } 9783 } 9784 9785 if (windows.size() <= 0) { 9786 return false; 9787 } 9788 9789 synchronized(mWindowMap) { 9790 dumpWindowsLocked(pw, dumpAll, windows); 9791 } 9792 return true; 9793 } 9794 9795 void dumpLastANRLocked(PrintWriter pw) { 9796 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 9797 if (mLastANRState == null) { 9798 pw.println(" <no ANR has occurred since boot>"); 9799 } else { 9800 pw.println(mLastANRState); 9801 } 9802 } 9803 9804 /** 9805 * Saves information about the state of the window manager at 9806 * the time an ANR occurred before anything else in the system changes 9807 * in response. 9808 * 9809 * @param appWindowToken The application that ANR'd, may be null. 9810 * @param windowState The window that ANR'd, may be null. 9811 */ 9812 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState) { 9813 StringWriter sw = new StringWriter(); 9814 PrintWriter pw = new PrintWriter(sw); 9815 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 9816 if (appWindowToken != null) { 9817 pw.println(" Application at fault: " + appWindowToken.stringName); 9818 } 9819 if (windowState != null) { 9820 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 9821 } 9822 pw.println(); 9823 dumpWindowsNoHeaderLocked(pw, true, null); 9824 pw.close(); 9825 mLastANRState = sw.toString(); 9826 } 9827 9828 @Override 9829 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 9830 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 9831 != PackageManager.PERMISSION_GRANTED) { 9832 pw.println("Permission Denial: can't dump WindowManager from from pid=" 9833 + Binder.getCallingPid() 9834 + ", uid=" + Binder.getCallingUid()); 9835 return; 9836 } 9837 9838 boolean dumpAll = false; 9839 9840 int opti = 0; 9841 while (opti < args.length) { 9842 String opt = args[opti]; 9843 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 9844 break; 9845 } 9846 opti++; 9847 if ("-a".equals(opt)) { 9848 dumpAll = true; 9849 } else if ("-h".equals(opt)) { 9850 pw.println("Window manager dump options:"); 9851 pw.println(" [-a] [-h] [cmd] ..."); 9852 pw.println(" cmd may be one of:"); 9853 pw.println(" l[astanr]: last ANR information"); 9854 pw.println(" p[policy]: policy state"); 9855 pw.println(" a[animator]: animator state"); 9856 pw.println(" s[essions]: active sessions"); 9857 pw.println(" t[okens]: token list"); 9858 pw.println(" w[indows]: window list"); 9859 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 9860 pw.println(" be a partial substring in a window name, a"); 9861 pw.println(" Window hex object identifier, or"); 9862 pw.println(" \"all\" for all windows, or"); 9863 pw.println(" \"visible\" for the visible windows."); 9864 pw.println(" -a: include all available server state."); 9865 return; 9866 } else { 9867 pw.println("Unknown argument: " + opt + "; use -h for help"); 9868 } 9869 } 9870 9871 // Is the caller requesting to dump a particular piece of data? 9872 if (opti < args.length) { 9873 String cmd = args[opti]; 9874 opti++; 9875 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 9876 synchronized(mWindowMap) { 9877 dumpLastANRLocked(pw); 9878 } 9879 return; 9880 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 9881 synchronized(mWindowMap) { 9882 dumpPolicyLocked(pw, args, true); 9883 } 9884 return; 9885 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 9886 synchronized(mWindowMap) { 9887 dumpAnimatorLocked(pw, args, true); 9888 } 9889 return; 9890 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 9891 synchronized(mWindowMap) { 9892 dumpSessionsLocked(pw, true); 9893 } 9894 return; 9895 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 9896 synchronized(mWindowMap) { 9897 dumpTokensLocked(pw, true); 9898 } 9899 return; 9900 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 9901 synchronized(mWindowMap) { 9902 dumpWindowsLocked(pw, true, null); 9903 } 9904 return; 9905 } else if ("all".equals(cmd) || "a".equals(cmd)) { 9906 synchronized(mWindowMap) { 9907 dumpWindowsLocked(pw, true, null); 9908 } 9909 return; 9910 } else { 9911 // Dumping a single name? 9912 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 9913 pw.println("Bad window command, or no windows match: " + cmd); 9914 pw.println("Use -h for help."); 9915 } 9916 return; 9917 } 9918 } 9919 9920 synchronized(mWindowMap) { 9921 pw.println(); 9922 if (dumpAll) { 9923 pw.println("-------------------------------------------------------------------------------"); 9924 } 9925 dumpLastANRLocked(pw); 9926 pw.println(); 9927 if (dumpAll) { 9928 pw.println("-------------------------------------------------------------------------------"); 9929 } 9930 dumpPolicyLocked(pw, args, dumpAll); 9931 pw.println(); 9932 if (dumpAll) { 9933 pw.println("-------------------------------------------------------------------------------"); 9934 } 9935 dumpAnimatorLocked(pw, args, dumpAll); 9936 pw.println(); 9937 if (dumpAll) { 9938 pw.println("-------------------------------------------------------------------------------"); 9939 } 9940 dumpSessionsLocked(pw, dumpAll); 9941 pw.println(); 9942 if (dumpAll) { 9943 pw.println("-------------------------------------------------------------------------------"); 9944 } 9945 dumpTokensLocked(pw, dumpAll); 9946 pw.println(); 9947 if (dumpAll) { 9948 pw.println("-------------------------------------------------------------------------------"); 9949 } 9950 dumpWindowsLocked(pw, dumpAll, null); 9951 } 9952 } 9953 9954 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 9955 @Override 9956 public void monitor() { 9957 synchronized (mWindowMap) { } 9958 } 9959 9960 public interface OnHardKeyboardStatusChangeListener { 9961 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 9962 } 9963 9964 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 9965 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 9966 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 9967 Integer.toHexString(pendingLayoutChanges)); 9968 } 9969 } 9970 9971 public void createDisplayContentLocked(final Display display) { 9972 if (display == null) { 9973 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 9974 } 9975 final DisplayContent displayContent = new DisplayContent(display); 9976 mDisplayContents.put(display.getDisplayId(), displayContent); 9977 } 9978 9979 /** 9980 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 9981 * there is a Display for the displayId. 9982 * @param displayId The display the caller is interested in. 9983 * @return The DisplayContent associated with displayId or null if there is no Display for it. 9984 */ 9985 public DisplayContent getDisplayContentLocked(final int displayId) { 9986 DisplayContent displayContent = mDisplayContents.get(displayId); 9987 if (displayContent == null) { 9988 final Display display = mDisplayManager.getDisplay(displayId); 9989 if (display != null) { 9990 displayContent = new DisplayContent(display); 9991 mDisplayContents.put(displayId, displayContent); 9992 } 9993 } 9994 return displayContent; 9995 } 9996 9997 class DisplayContentsIterator implements Iterator<DisplayContent> { 9998 private int cur; 9999 10000 void reset() { 10001 cur = 0; 10002 } 10003 10004 @Override 10005 public boolean hasNext() { 10006 return cur < mDisplayContents.size(); 10007 } 10008 10009 @Override 10010 public DisplayContent next() { 10011 if (hasNext()) { 10012 return mDisplayContents.valueAt(cur++); 10013 } 10014 throw new NoSuchElementException(); 10015 } 10016 10017 @Override 10018 public void remove() { 10019 throw new IllegalArgumentException("AllDisplayContentIterator.remove not implemented"); 10020 } 10021 } 10022 10023 class AllWindowsIterator implements Iterator<WindowState> { 10024 private DisplayContent mDisplayContent; 10025 private DisplayContentsIterator mDisplayContentsIterator; 10026 private WindowList mWindowList; 10027 private int mWindowListIndex; 10028 private boolean mReverse; 10029 10030 AllWindowsIterator() { 10031 this(false); 10032 } 10033 10034 AllWindowsIterator(boolean reverse) { 10035 mDisplayContentsIterator = new DisplayContentsIterator(); 10036 reset(reverse); 10037 } 10038 10039 void reset(boolean reverse) { 10040 mReverse = reverse; 10041 mDisplayContentsIterator.reset(); 10042 if (mDisplayContentsIterator.hasNext()) { 10043 mDisplayContent = mDisplayContentsIterator.next(); 10044 mWindowList = mDisplayContent.getWindowList(); 10045 mWindowListIndex = reverse ? mWindowList.size() - 1 : 0; 10046 } else { 10047 mDisplayContent = null; 10048 mWindowList = null; 10049 mWindowListIndex = 0; 10050 } 10051 } 10052 10053 @Override 10054 public boolean hasNext() { 10055 if (mDisplayContent == null) { 10056 return false; 10057 } 10058 if (mReverse) { 10059 return mWindowListIndex >= 0; 10060 } 10061 return mWindowListIndex < mWindowList.size(); 10062 } 10063 10064 @Override 10065 public WindowState next() { 10066 if (hasNext()) { 10067 WindowState win = mWindowList.get(mWindowListIndex); 10068 if (mReverse) { 10069 mWindowListIndex--; 10070 if (mWindowListIndex < 0 && mDisplayContentsIterator.hasNext()) { 10071 mDisplayContent = mDisplayContentsIterator.next(); 10072 mWindowList = mDisplayContent.getWindowList(); 10073 mWindowListIndex = mWindowList.size() - 1; 10074 } 10075 } else { 10076 mWindowListIndex++; 10077 if (mWindowListIndex >= mWindowList.size() 10078 && mDisplayContentsIterator.hasNext()) { 10079 mDisplayContent = mDisplayContentsIterator.next(); 10080 mWindowList = mDisplayContent.getWindowList(); 10081 mWindowListIndex = 0; 10082 } 10083 } 10084 return win; 10085 } 10086 throw new NoSuchElementException(); 10087 } 10088 10089 @Override 10090 public void remove() { 10091 throw new IllegalArgumentException("AllWindowsIterator.remove not implemented"); 10092 } 10093 } 10094 10095 // There is an inherent assumption that this will never return null. 10096 public DisplayContent getDefaultDisplayContentLocked() { 10097 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 10098 } 10099 10100 public WindowList getDefaultWindowListLocked() { 10101 return getDefaultDisplayContentLocked().getWindowList(); 10102 } 10103 10104 public DisplayInfo getDefaultDisplayInfoLocked() { 10105 return getDefaultDisplayContentLocked().getDisplayInfo(); 10106 } 10107 10108 /** 10109 * Return the list of WindowStates associated on the passed display. 10110 * @param display The screen to return windows from. 10111 * @return The list of WindowStates on the screen, or null if the there is no screen. 10112 */ 10113 public WindowList getWindowListLocked(final Display display) { 10114 return getWindowListLocked(display.getDisplayId()); 10115 } 10116 10117 /** 10118 * Return the list of WindowStates associated on the passed display. 10119 * @param displayId The screen to return windows from. 10120 * @return The list of WindowStates on the screen, or null if the there is no screen. 10121 */ 10122 public WindowList getWindowListLocked(final int displayId) { 10123 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10124 return displayContent != null ? displayContent.getWindowList() : null; 10125 } 10126 10127 @Override 10128 public void onDisplayAdded(int displayId) { 10129 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 10130 } 10131 10132 private void handleDisplayAddedLocked(int displayId) { 10133 final Display display = mDisplayManager.getDisplay(displayId); 10134 if (display != null) { 10135 createDisplayContentLocked(display); 10136 displayReady(displayId); 10137 } 10138 } 10139 10140 @Override 10141 public void onDisplayRemoved(int displayId) { 10142 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 10143 } 10144 10145 private void handleDisplayRemovedLocked(int displayId) { 10146 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10147 if (displayContent != null) { 10148 mDisplayContents.delete(displayId); 10149 WindowList windows = displayContent.getWindowList(); 10150 while (!windows.isEmpty()) { 10151 final WindowState win = windows.get(windows.size() - 1); 10152 removeWindowLocked(win.mSession, win); 10153 } 10154 } 10155 mAnimator.removeDisplayLocked(displayId); 10156 } 10157 10158 @Override 10159 public void onDisplayChanged(int displayId) { 10160 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 10161 } 10162 10163 private void handleDisplayChangedLocked(int displayId) { 10164 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10165 if (displayContent != null) { 10166 displayContent.updateDisplayInfo(); 10167 } 10168 } 10169} 10170