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