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