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