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