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