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