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