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