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