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