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