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