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