WindowManagerService.java revision 7916ac65dc492e4e1431879875c77d7121fbf82e
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 InputDevice getInputDevice(int deviceId) { 4636 return mInputManager.getInputDevice(deviceId); 4637 } 4638 4639 public int[] getInputDeviceIds() { 4640 return mInputManager.getInputDeviceIds(); 4641 } 4642 4643 public void enableScreenAfterBoot() { 4644 synchronized(mWindowMap) { 4645 if (mSystemBooted) { 4646 return; 4647 } 4648 mSystemBooted = true; 4649 } 4650 4651 performEnableScreen(); 4652 } 4653 4654 public void enableScreenIfNeededLocked() { 4655 if (mDisplayEnabled) { 4656 return; 4657 } 4658 if (!mSystemBooted) { 4659 return; 4660 } 4661 mH.sendMessage(mH.obtainMessage(H.ENABLE_SCREEN)); 4662 } 4663 4664 public void performEnableScreen() { 4665 synchronized(mWindowMap) { 4666 if (mDisplayEnabled) { 4667 return; 4668 } 4669 if (!mSystemBooted) { 4670 return; 4671 } 4672 4673 // Don't enable the screen until all existing windows 4674 // have been drawn. 4675 final int N = mWindows.size(); 4676 for (int i=0; i<N; i++) { 4677 WindowState w = mWindows.get(i); 4678 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 4679 return; 4680 } 4681 } 4682 4683 mDisplayEnabled = true; 4684 if (false) { 4685 Slog.i(TAG, "ENABLING SCREEN!"); 4686 StringWriter sw = new StringWriter(); 4687 PrintWriter pw = new PrintWriter(sw); 4688 this.dump(null, pw, null); 4689 Slog.i(TAG, sw.toString()); 4690 } 4691 try { 4692 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); 4693 if (surfaceFlinger != null) { 4694 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); 4695 Parcel data = Parcel.obtain(); 4696 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 4697 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, 4698 data, null, 0); 4699 data.recycle(); 4700 } 4701 } catch (RemoteException ex) { 4702 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); 4703 } 4704 } 4705 4706 mPolicy.enableScreenAfterBoot(); 4707 4708 // Make sure the last requested orientation has been applied. 4709 setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 4710 mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE); 4711 } 4712 4713 public void setInTouchMode(boolean mode) { 4714 synchronized(mWindowMap) { 4715 mInTouchMode = mode; 4716 } 4717 } 4718 4719 // TODO: more accounting of which pid(s) turned it on, keep count, 4720 // only allow disables from pids which have count on, etc. 4721 public void showStrictModeViolation(boolean on) { 4722 int pid = Binder.getCallingPid(); 4723 synchronized(mWindowMap) { 4724 // Ignoring requests to enable the red border from clients 4725 // which aren't on screen. (e.g. Broadcast Receivers in 4726 // the background..) 4727 if (on) { 4728 boolean isVisible = false; 4729 for (WindowState ws : mWindows) { 4730 if (ws.mSession.mPid == pid && ws.isVisibleLw()) { 4731 isVisible = true; 4732 break; 4733 } 4734 } 4735 if (!isVisible) { 4736 return; 4737 } 4738 } 4739 4740 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION showStrictModeViolation"); 4741 Surface.openTransaction(); 4742 try { 4743 if (mStrictModeFlash == null) { 4744 mStrictModeFlash = new StrictModeFlash(mDisplay, mFxSession); 4745 } 4746 mStrictModeFlash.setVisibility(on); 4747 } finally { 4748 Surface.closeTransaction(); 4749 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION showStrictModeViolation"); 4750 } 4751 } 4752 } 4753 4754 public void setStrictModeVisualIndicatorPreference(String value) { 4755 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 4756 } 4757 4758 /** 4759 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 4760 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 4761 * of the target image. 4762 * 4763 * @param width the width of the target bitmap 4764 * @param height the height of the target bitmap 4765 */ 4766 public Bitmap screenshotApplications(IBinder appToken, int width, int height) { 4767 if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, 4768 "screenshotApplications()")) { 4769 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 4770 } 4771 4772 Bitmap rawss; 4773 4774 int maxLayer = 0; 4775 final Rect frame = new Rect(); 4776 4777 float scale; 4778 int dw, dh; 4779 int rot; 4780 4781 synchronized(mWindowMap) { 4782 long ident = Binder.clearCallingIdentity(); 4783 4784 dw = mPolicy.getNonDecorDisplayWidth(mCurDisplayWidth); 4785 dh = mPolicy.getNonDecorDisplayHeight(mCurDisplayHeight); 4786 4787 int aboveAppLayer = mPolicy.windowTypeToLayerLw( 4788 WindowManager.LayoutParams.TYPE_APPLICATION) * TYPE_LAYER_MULTIPLIER 4789 + TYPE_LAYER_OFFSET; 4790 aboveAppLayer += TYPE_LAYER_MULTIPLIER; 4791 4792 boolean isImeTarget = mInputMethodTarget != null 4793 && mInputMethodTarget.mAppToken != null 4794 && mInputMethodTarget.mAppToken.appToken != null 4795 && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken; 4796 4797 // Figure out the part of the screen that is actually the app. 4798 boolean including = false; 4799 for (int i=mWindows.size()-1; i>=0; i--) { 4800 WindowState ws = mWindows.get(i); 4801 if (ws.mSurface == null) { 4802 continue; 4803 } 4804 if (ws.mLayer >= aboveAppLayer) { 4805 continue; 4806 } 4807 // When we will skip windows: when we are not including 4808 // ones behind a window we didn't skip, and we are actually 4809 // taking a screenshot of a specific app. 4810 if (!including && appToken != null) { 4811 // Also, we can possibly skip this window if it is not 4812 // an IME target or the application for the screenshot 4813 // is not the current IME target. 4814 if (!ws.mIsImWindow || !isImeTarget) { 4815 // And finally, this window is of no interest if it 4816 // is not associated with the screenshot app. 4817 if (ws.mAppToken == null || ws.mAppToken.token != appToken) { 4818 continue; 4819 } 4820 } 4821 } 4822 4823 // We keep on including windows until we go past a full-screen 4824 // window. 4825 including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh); 4826 4827 if (maxLayer < ws.mAnimLayer) { 4828 maxLayer = ws.mAnimLayer; 4829 } 4830 4831 // Don't include wallpaper in bounds calculation 4832 if (!ws.mIsWallpaper) { 4833 final Rect wf = ws.mScaledFrame; 4834 final Rect cr = ws.mContentInsets; 4835 int left = wf.left + cr.left; 4836 int top = wf.top + cr.top; 4837 int right = wf.right - cr.right; 4838 int bottom = wf.bottom - cr.bottom; 4839 frame.union(left, top, right, bottom); 4840 } 4841 } 4842 Binder.restoreCallingIdentity(ident); 4843 4844 // Constrain frame to the screen size. 4845 frame.intersect(0, 0, dw, dh); 4846 4847 if (frame.isEmpty() || maxLayer == 0) { 4848 return null; 4849 } 4850 4851 // The screenshot API does not apply the current screen rotation. 4852 rot = mDisplay.getRotation(); 4853 int fw = frame.width(); 4854 int fh = frame.height(); 4855 4856 // First try reducing to fit in x dimension. 4857 scale = width/(float)fw; 4858 4859 // The screen shot will contain the entire screen. 4860 dw = (int)(dw*scale); 4861 dh = (int)(dh*scale); 4862 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 4863 int tmp = dw; 4864 dw = dh; 4865 dh = tmp; 4866 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; 4867 } 4868 rawss = Surface.screenshot(dw, dh, 0, maxLayer); 4869 } 4870 4871 if (rawss == null) { 4872 Log.w(TAG, "Failure taking screenshot for (" + dw + "x" + dh 4873 + ") to layer " + maxLayer); 4874 return null; 4875 } 4876 4877 Bitmap bm = Bitmap.createBitmap(width, height, rawss.getConfig()); 4878 Matrix matrix = new Matrix(); 4879 ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix); 4880 matrix.postTranslate(-(int)(frame.left*scale), -(int)(frame.top*scale)); 4881 Canvas canvas = new Canvas(bm); 4882 canvas.drawBitmap(rawss, matrix, null); 4883 4884 rawss.recycle(); 4885 return bm; 4886 } 4887 4888 public void freezeRotation() { 4889 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 4890 "freezeRotation()")) { 4891 throw new SecurityException("Requires SET_ORIENTATION permission"); 4892 } 4893 4894 if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); 4895 4896 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, mRotation); 4897 setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 0); 4898 } 4899 4900 public void thawRotation() { 4901 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 4902 "thawRotation()")) { 4903 throw new SecurityException("Requires SET_ORIENTATION permission"); 4904 } 4905 4906 if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); 4907 4908 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 777); // rot not used 4909 setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 0); 4910 } 4911 4912 public void setRotation(int rotation, 4913 boolean alwaysSendConfiguration, int animFlags) { 4914 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 4915 "setRotation()")) { 4916 throw new SecurityException("Requires SET_ORIENTATION permission"); 4917 } 4918 4919 setRotationUnchecked(rotation, alwaysSendConfiguration, animFlags); 4920 } 4921 4922 public void setRotationUnchecked(int rotation, 4923 boolean alwaysSendConfiguration, int animFlags) { 4924 if(DEBUG_ORIENTATION) Slog.v(TAG, 4925 "setRotationUnchecked(rotation=" + rotation + 4926 " alwaysSendConfiguration=" + alwaysSendConfiguration + 4927 " animFlags=" + animFlags); 4928 4929 long origId = Binder.clearCallingIdentity(); 4930 boolean changed; 4931 synchronized(mWindowMap) { 4932 changed = setRotationUncheckedLocked(rotation, animFlags, false); 4933 } 4934 4935 if (changed || alwaysSendConfiguration) { 4936 sendNewConfiguration(); 4937 } 4938 4939 Binder.restoreCallingIdentity(origId); 4940 } 4941 4942 /** 4943 * Apply a new rotation to the screen, respecting the requests of 4944 * applications. Use WindowManagerPolicy.USE_LAST_ROTATION to simply 4945 * re-evaluate the desired rotation. 4946 * 4947 * Returns null if the rotation has been changed. In this case YOU 4948 * MUST CALL setNewConfiguration() TO UNFREEZE THE SCREEN. 4949 */ 4950 public boolean setRotationUncheckedLocked(int rotation, int animFlags, boolean inTransaction) { 4951 if (mDragState != null || mScreenRotationAnimation != null) { 4952 // Potential rotation during a drag. Don't do the rotation now, but make 4953 // a note to perform the rotation later. 4954 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation."); 4955 if (rotation != WindowManagerPolicy.USE_LAST_ROTATION) { 4956 mDeferredRotation = rotation; 4957 mDeferredRotationAnimFlags = animFlags; 4958 } 4959 return false; 4960 } 4961 4962 boolean changed; 4963 if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) { 4964 if (mDeferredRotation != WindowManagerPolicy.USE_LAST_ROTATION) { 4965 rotation = mDeferredRotation; 4966 mRequestedRotation = rotation; 4967 mLastRotationFlags = mDeferredRotationAnimFlags; 4968 } 4969 rotation = mRequestedRotation; 4970 } else { 4971 mRequestedRotation = rotation; 4972 mLastRotationFlags = animFlags; 4973 } 4974 mDeferredRotation = WindowManagerPolicy.USE_LAST_ROTATION; 4975 if (DEBUG_ORIENTATION) Slog.v(TAG, "Overwriting rotation value from " + rotation); 4976 rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, 4977 mRotation, mDisplayEnabled); 4978 if (DEBUG_ORIENTATION) Slog.v(TAG, "new rotation is set to " + rotation); 4979 4980 int desiredRotation = rotation; 4981 int lockedRotation = mPolicy.getLockedRotationLw(); 4982 if (lockedRotation >= 0 && rotation != lockedRotation) { 4983 // We are locked in a rotation but something is requesting 4984 // a different rotation... we will either keep the locked 4985 // rotation if it results in the same orientation, or have to 4986 // switch into an emulated orientation mode. 4987 4988 // First, we know that our rotation is actually going to be 4989 // the locked rotation. 4990 rotation = lockedRotation; 4991 4992 // Now the difference between the desired and lockedRotation 4993 // may mean that the orientation is different... if that is 4994 // not the case, we can just make the desired rotation be the 4995 // same as the new locked rotation. 4996 switch (lockedRotation) { 4997 case Surface.ROTATION_0: 4998 if (rotation == Surface.ROTATION_180) { 4999 desiredRotation = lockedRotation; 5000 } 5001 break; 5002 case Surface.ROTATION_90: 5003 if (rotation == Surface.ROTATION_270) { 5004 desiredRotation = lockedRotation; 5005 } 5006 break; 5007 case Surface.ROTATION_180: 5008 if (rotation == Surface.ROTATION_0) { 5009 desiredRotation = lockedRotation; 5010 } 5011 break; 5012 case Surface.ROTATION_270: 5013 if (rotation == Surface.ROTATION_90) { 5014 desiredRotation = lockedRotation; 5015 } 5016 break; 5017 } 5018 } 5019 5020 changed = mDisplayEnabled && mRotation != rotation; 5021 if (mAltOrientation != (rotation != desiredRotation)) { 5022 changed = true; 5023 mAltOrientation = rotation != desiredRotation; 5024 } 5025 5026 if (changed) { 5027 if (DEBUG_ORIENTATION) Slog.v(TAG, 5028 "Rotation changed to " + rotation 5029 + " from " + mRotation 5030 + " (forceApp=" + mForcedAppOrientation 5031 + ", req=" + mRequestedRotation + ")"); 5032 mRotation = rotation; 5033 mWindowsFreezingScreen = true; 5034 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 5035 mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT), 5036 2000); 5037 mWaitingForConfig = true; 5038 mLayoutNeeded = true; 5039 startFreezingDisplayLocked(inTransaction); 5040 Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags); 5041 mInputManager.setDisplayOrientation(0, rotation); 5042 if (mDisplayEnabled) { 5043 // NOTE: We disable the rotation in the emulator because 5044 // it doesn't support hardware OpenGL emulation yet. 5045 if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null 5046 && mScreenRotationAnimation.hasScreenshot()) { 5047 Surface.freezeDisplay(0); 5048 if (!inTransaction) { 5049 if (SHOW_TRANSACTIONS) Slog.i(TAG, 5050 ">>> OPEN TRANSACTION setRotationUnchecked"); 5051 Surface.openTransaction(); 5052 } 5053 try { 5054 if (mScreenRotationAnimation != null) { 5055 mScreenRotationAnimation.setRotation(rotation); 5056 } 5057 } finally { 5058 if (!inTransaction) { 5059 Surface.closeTransaction(); 5060 if (SHOW_TRANSACTIONS) Slog.i(TAG, 5061 "<<< CLOSE TRANSACTION setRotationUnchecked"); 5062 } 5063 } 5064 Surface.setOrientation(0, rotation, animFlags); 5065 Surface.unfreezeDisplay(0); 5066 } else { 5067 Surface.setOrientation(0, rotation, animFlags); 5068 } 5069 rebuildBlackFrame(inTransaction); 5070 } 5071 5072 for (int i=mWindows.size()-1; i>=0; i--) { 5073 WindowState w = mWindows.get(i); 5074 if (w.mSurface != null) { 5075 w.mOrientationChanging = true; 5076 } 5077 } 5078 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 5079 try { 5080 mRotationWatchers.get(i).onRotationChanged(rotation); 5081 } catch (RemoteException e) { 5082 } 5083 } 5084 } //end if changed 5085 5086 return changed; 5087 } 5088 5089 public int getRotation() { 5090 return mRotation; 5091 } 5092 5093 public int watchRotation(IRotationWatcher watcher) { 5094 final IBinder watcherBinder = watcher.asBinder(); 5095 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 5096 public void binderDied() { 5097 synchronized (mWindowMap) { 5098 for (int i=0; i<mRotationWatchers.size(); i++) { 5099 if (watcherBinder == mRotationWatchers.get(i).asBinder()) { 5100 IRotationWatcher removed = mRotationWatchers.remove(i); 5101 if (removed != null) { 5102 removed.asBinder().unlinkToDeath(this, 0); 5103 } 5104 i--; 5105 } 5106 } 5107 } 5108 } 5109 }; 5110 5111 synchronized (mWindowMap) { 5112 try { 5113 watcher.asBinder().linkToDeath(dr, 0); 5114 mRotationWatchers.add(watcher); 5115 } catch (RemoteException e) { 5116 // Client died, no cleanup needed. 5117 } 5118 5119 return mRotation; 5120 } 5121 } 5122 5123 /** 5124 * Starts the view server on the specified port. 5125 * 5126 * @param port The port to listener to. 5127 * 5128 * @return True if the server was successfully started, false otherwise. 5129 * 5130 * @see com.android.server.wm.ViewServer 5131 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 5132 */ 5133 public boolean startViewServer(int port) { 5134 if (isSystemSecure()) { 5135 return false; 5136 } 5137 5138 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 5139 return false; 5140 } 5141 5142 if (port < 1024) { 5143 return false; 5144 } 5145 5146 if (mViewServer != null) { 5147 if (!mViewServer.isRunning()) { 5148 try { 5149 return mViewServer.start(); 5150 } catch (IOException e) { 5151 Slog.w(TAG, "View server did not start"); 5152 } 5153 } 5154 return false; 5155 } 5156 5157 try { 5158 mViewServer = new ViewServer(this, port); 5159 return mViewServer.start(); 5160 } catch (IOException e) { 5161 Slog.w(TAG, "View server did not start"); 5162 } 5163 return false; 5164 } 5165 5166 private boolean isSystemSecure() { 5167 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 5168 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 5169 } 5170 5171 /** 5172 * Stops the view server if it exists. 5173 * 5174 * @return True if the server stopped, false if it wasn't started or 5175 * couldn't be stopped. 5176 * 5177 * @see com.android.server.wm.ViewServer 5178 */ 5179 public boolean stopViewServer() { 5180 if (isSystemSecure()) { 5181 return false; 5182 } 5183 5184 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 5185 return false; 5186 } 5187 5188 if (mViewServer != null) { 5189 return mViewServer.stop(); 5190 } 5191 return false; 5192 } 5193 5194 /** 5195 * Indicates whether the view server is running. 5196 * 5197 * @return True if the server is running, false otherwise. 5198 * 5199 * @see com.android.server.wm.ViewServer 5200 */ 5201 public boolean isViewServerRunning() { 5202 if (isSystemSecure()) { 5203 return false; 5204 } 5205 5206 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 5207 return false; 5208 } 5209 5210 return mViewServer != null && mViewServer.isRunning(); 5211 } 5212 5213 /** 5214 * Lists all availble windows in the system. The listing is written in the 5215 * specified Socket's output stream with the following syntax: 5216 * windowHashCodeInHexadecimal windowName 5217 * Each line of the ouput represents a different window. 5218 * 5219 * @param client The remote client to send the listing to. 5220 * @return False if an error occured, true otherwise. 5221 */ 5222 boolean viewServerListWindows(Socket client) { 5223 if (isSystemSecure()) { 5224 return false; 5225 } 5226 5227 boolean result = true; 5228 5229 WindowState[] windows; 5230 synchronized (mWindowMap) { 5231 //noinspection unchecked 5232 windows = mWindows.toArray(new WindowState[mWindows.size()]); 5233 } 5234 5235 BufferedWriter out = null; 5236 5237 // Any uncaught exception will crash the system process 5238 try { 5239 OutputStream clientStream = client.getOutputStream(); 5240 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 5241 5242 final int count = windows.length; 5243 for (int i = 0; i < count; i++) { 5244 final WindowState w = windows[i]; 5245 out.write(Integer.toHexString(System.identityHashCode(w))); 5246 out.write(' '); 5247 out.append(w.mAttrs.getTitle()); 5248 out.write('\n'); 5249 } 5250 5251 out.write("DONE.\n"); 5252 out.flush(); 5253 } catch (Exception e) { 5254 result = false; 5255 } finally { 5256 if (out != null) { 5257 try { 5258 out.close(); 5259 } catch (IOException e) { 5260 result = false; 5261 } 5262 } 5263 } 5264 5265 return result; 5266 } 5267 5268 /** 5269 * Returns the focused window in the following format: 5270 * windowHashCodeInHexadecimal windowName 5271 * 5272 * @param client The remote client to send the listing to. 5273 * @return False if an error occurred, true otherwise. 5274 */ 5275 boolean viewServerGetFocusedWindow(Socket client) { 5276 if (isSystemSecure()) { 5277 return false; 5278 } 5279 5280 boolean result = true; 5281 5282 WindowState focusedWindow = getFocusedWindow(); 5283 5284 BufferedWriter out = null; 5285 5286 // Any uncaught exception will crash the system process 5287 try { 5288 OutputStream clientStream = client.getOutputStream(); 5289 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 5290 5291 if(focusedWindow != null) { 5292 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 5293 out.write(' '); 5294 out.append(focusedWindow.mAttrs.getTitle()); 5295 } 5296 out.write('\n'); 5297 out.flush(); 5298 } catch (Exception e) { 5299 result = false; 5300 } finally { 5301 if (out != null) { 5302 try { 5303 out.close(); 5304 } catch (IOException e) { 5305 result = false; 5306 } 5307 } 5308 } 5309 5310 return result; 5311 } 5312 5313 /** 5314 * Sends a command to a target window. The result of the command, if any, will be 5315 * written in the output stream of the specified socket. 5316 * 5317 * The parameters must follow this syntax: 5318 * windowHashcode extra 5319 * 5320 * Where XX is the length in characeters of the windowTitle. 5321 * 5322 * The first parameter is the target window. The window with the specified hashcode 5323 * will be the target. If no target can be found, nothing happens. The extra parameters 5324 * will be delivered to the target window and as parameters to the command itself. 5325 * 5326 * @param client The remote client to sent the result, if any, to. 5327 * @param command The command to execute. 5328 * @param parameters The command parameters. 5329 * 5330 * @return True if the command was successfully delivered, false otherwise. This does 5331 * not indicate whether the command itself was successful. 5332 */ 5333 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 5334 if (isSystemSecure()) { 5335 return false; 5336 } 5337 5338 boolean success = true; 5339 Parcel data = null; 5340 Parcel reply = null; 5341 5342 BufferedWriter out = null; 5343 5344 // Any uncaught exception will crash the system process 5345 try { 5346 // Find the hashcode of the window 5347 int index = parameters.indexOf(' '); 5348 if (index == -1) { 5349 index = parameters.length(); 5350 } 5351 final String code = parameters.substring(0, index); 5352 int hashCode = (int) Long.parseLong(code, 16); 5353 5354 // Extract the command's parameter after the window description 5355 if (index < parameters.length()) { 5356 parameters = parameters.substring(index + 1); 5357 } else { 5358 parameters = ""; 5359 } 5360 5361 final WindowState window = findWindow(hashCode); 5362 if (window == null) { 5363 return false; 5364 } 5365 5366 data = Parcel.obtain(); 5367 data.writeInterfaceToken("android.view.IWindow"); 5368 data.writeString(command); 5369 data.writeString(parameters); 5370 data.writeInt(1); 5371 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 5372 5373 reply = Parcel.obtain(); 5374 5375 final IBinder binder = window.mClient.asBinder(); 5376 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 5377 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 5378 5379 reply.readException(); 5380 5381 if (!client.isOutputShutdown()) { 5382 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 5383 out.write("DONE\n"); 5384 out.flush(); 5385 } 5386 5387 } catch (Exception e) { 5388 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); 5389 success = false; 5390 } finally { 5391 if (data != null) { 5392 data.recycle(); 5393 } 5394 if (reply != null) { 5395 reply.recycle(); 5396 } 5397 if (out != null) { 5398 try { 5399 out.close(); 5400 } catch (IOException e) { 5401 5402 } 5403 } 5404 } 5405 5406 return success; 5407 } 5408 5409 public void addWindowChangeListener(WindowChangeListener listener) { 5410 synchronized(mWindowMap) { 5411 mWindowChangeListeners.add(listener); 5412 } 5413 } 5414 5415 public void removeWindowChangeListener(WindowChangeListener listener) { 5416 synchronized(mWindowMap) { 5417 mWindowChangeListeners.remove(listener); 5418 } 5419 } 5420 5421 private void notifyWindowsChanged() { 5422 WindowChangeListener[] windowChangeListeners; 5423 synchronized(mWindowMap) { 5424 if(mWindowChangeListeners.isEmpty()) { 5425 return; 5426 } 5427 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 5428 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 5429 } 5430 int N = windowChangeListeners.length; 5431 for(int i = 0; i < N; i++) { 5432 windowChangeListeners[i].windowsChanged(); 5433 } 5434 } 5435 5436 private void notifyFocusChanged() { 5437 WindowChangeListener[] windowChangeListeners; 5438 synchronized(mWindowMap) { 5439 if(mWindowChangeListeners.isEmpty()) { 5440 return; 5441 } 5442 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 5443 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 5444 } 5445 int N = windowChangeListeners.length; 5446 for(int i = 0; i < N; i++) { 5447 windowChangeListeners[i].focusChanged(); 5448 } 5449 } 5450 5451 private WindowState findWindow(int hashCode) { 5452 if (hashCode == -1) { 5453 return getFocusedWindow(); 5454 } 5455 5456 synchronized (mWindowMap) { 5457 final ArrayList<WindowState> windows = mWindows; 5458 final int count = windows.size(); 5459 5460 for (int i = 0; i < count; i++) { 5461 WindowState w = windows.get(i); 5462 if (System.identityHashCode(w) == hashCode) { 5463 return w; 5464 } 5465 } 5466 } 5467 5468 return null; 5469 } 5470 5471 /* 5472 * Instruct the Activity Manager to fetch the current configuration and broadcast 5473 * that to config-changed listeners if appropriate. 5474 */ 5475 void sendNewConfiguration() { 5476 try { 5477 mActivityManager.updateConfiguration(null); 5478 } catch (RemoteException e) { 5479 } 5480 } 5481 5482 public Configuration computeNewConfiguration() { 5483 synchronized (mWindowMap) { 5484 Configuration config = computeNewConfigurationLocked(); 5485 if (config == null && mWaitingForConfig) { 5486 // Nothing changed but we are waiting for something... stop that! 5487 mWaitingForConfig = false; 5488 performLayoutAndPlaceSurfacesLocked(); 5489 } 5490 return config; 5491 } 5492 } 5493 5494 Configuration computeNewConfigurationLocked() { 5495 Configuration config = new Configuration(); 5496 if (!computeNewConfigurationLocked(config)) { 5497 return null; 5498 } 5499 return config; 5500 } 5501 5502 boolean computeNewConfigurationLocked(Configuration config) { 5503 if (mDisplay == null) { 5504 return false; 5505 } 5506 5507 mInputManager.getInputConfiguration(config); 5508 5509 // Use the effective "visual" dimensions based on current rotation 5510 final boolean rotated = (mRotation == Surface.ROTATION_90 5511 || mRotation == Surface.ROTATION_270); 5512 final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; 5513 final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; 5514 5515 if (mAltOrientation) { 5516 mCurDisplayWidth = realdw; 5517 mCurDisplayHeight = realdh; 5518 if (realdw > realdh) { 5519 // Turn landscape into portrait. 5520 int maxw = (int)(realdh/1.3f); 5521 if (maxw < realdw) { 5522 mCurDisplayWidth = maxw; 5523 } 5524 } else { 5525 // Turn portrait into landscape. 5526 int maxh = (int)(realdw/1.3f); 5527 if (maxh < realdh) { 5528 mCurDisplayHeight = maxh; 5529 } 5530 } 5531 } else { 5532 mCurDisplayWidth = realdw; 5533 mCurDisplayHeight = realdh; 5534 } 5535 5536 final int dw = mCurDisplayWidth; 5537 final int dh = mCurDisplayHeight; 5538 5539 int orientation = Configuration.ORIENTATION_SQUARE; 5540 if (dw < dh) { 5541 orientation = Configuration.ORIENTATION_PORTRAIT; 5542 } else if (dw > dh) { 5543 orientation = Configuration.ORIENTATION_LANDSCAPE; 5544 } 5545 config.orientation = orientation; 5546 5547 DisplayMetrics dm = new DisplayMetrics(); 5548 mDisplay.getRealMetrics(dm); 5549 5550 // Override display width and height with what we are computing, 5551 // to be sure they remain consistent. 5552 dm.widthPixels = mPolicy.getNonDecorDisplayWidth(dw); 5553 dm.heightPixels = mPolicy.getNonDecorDisplayHeight(dh); 5554 5555 mCompatibleScreenScale = CompatibilityInfo.updateCompatibleScreenFrame( 5556 dm, mCompatibleScreenFrame, null); 5557 5558 config.screenWidthDp = (int)(dm.widthPixels / dm.density); 5559 config.screenHeightDp = (int)(dm.heightPixels / dm.density); 5560 5561 // Compute the screen layout size class. 5562 int screenLayout; 5563 int longSize = dw; 5564 int shortSize = dh; 5565 if (longSize < shortSize) { 5566 int tmp = longSize; 5567 longSize = shortSize; 5568 shortSize = tmp; 5569 } 5570 longSize = (int)(longSize/dm.density); 5571 shortSize = (int)(shortSize/dm.density); 5572 5573 // These semi-magic numbers define our compatibility modes for 5574 // applications with different screens. These are guarantees to 5575 // app developers about the space they can expect for a particular 5576 // configuration. DO NOT CHANGE! 5577 if (longSize < 470) { 5578 // This is shorter than an HVGA normal density screen (which 5579 // is 480 pixels on its long side). 5580 screenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL 5581 | Configuration.SCREENLAYOUT_LONG_NO; 5582 } else { 5583 // What size is this screen screen? 5584 if (longSize >= 960 && shortSize >= 720) { 5585 // 1.5xVGA or larger screens at medium density are the point 5586 // at which we consider it to be an extra large screen. 5587 screenLayout = Configuration.SCREENLAYOUT_SIZE_XLARGE; 5588 } else if (longSize >= 640 && shortSize >= 480) { 5589 // VGA or larger screens at medium density are the point 5590 // at which we consider it to be a large screen. 5591 screenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE; 5592 } else { 5593 screenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL; 5594 } 5595 5596 // If this screen is wider than normal HVGA, or taller 5597 // than FWVGA, then for old apps we want to run in size 5598 // compatibility mode. 5599 if (shortSize > 321 || longSize > 570) { 5600 screenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED; 5601 } 5602 5603 // Is this a long screen? 5604 if (((longSize*3)/5) >= (shortSize-1)) { 5605 // Anything wider than WVGA (5:3) is considering to be long. 5606 screenLayout |= Configuration.SCREENLAYOUT_LONG_YES; 5607 } else { 5608 screenLayout |= Configuration.SCREENLAYOUT_LONG_NO; 5609 } 5610 } 5611 config.screenLayout = screenLayout; 5612 5613 // Determine whether a hard keyboard is available and enabled. 5614 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 5615 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 5616 mHardKeyboardAvailable = hardKeyboardAvailable; 5617 mHardKeyboardEnabled = hardKeyboardAvailable; 5618 5619 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 5620 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 5621 } 5622 if (!mHardKeyboardEnabled) { 5623 config.keyboard = Configuration.KEYBOARD_NOKEYS; 5624 } 5625 5626 // Update value of keyboardHidden, hardKeyboardHidden and navigationHidden 5627 // based on whether a hard or soft keyboard is present, whether navigation keys 5628 // are present and the lid switch state. 5629 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 5630 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 5631 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 5632 mPolicy.adjustConfigurationLw(config); 5633 return true; 5634 } 5635 5636 public boolean isHardKeyboardAvailable() { 5637 synchronized (mWindowMap) { 5638 return mHardKeyboardAvailable; 5639 } 5640 } 5641 5642 public boolean isHardKeyboardEnabled() { 5643 synchronized (mWindowMap) { 5644 return mHardKeyboardEnabled; 5645 } 5646 } 5647 5648 public void setHardKeyboardEnabled(boolean enabled) { 5649 synchronized (mWindowMap) { 5650 if (mHardKeyboardEnabled != enabled) { 5651 mHardKeyboardEnabled = enabled; 5652 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 5653 } 5654 } 5655 } 5656 5657 public void setOnHardKeyboardStatusChangeListener( 5658 OnHardKeyboardStatusChangeListener listener) { 5659 synchronized (mWindowMap) { 5660 mHardKeyboardStatusChangeListener = listener; 5661 } 5662 } 5663 5664 void notifyHardKeyboardStatusChange() { 5665 final boolean available, enabled; 5666 final OnHardKeyboardStatusChangeListener listener; 5667 synchronized (mWindowMap) { 5668 listener = mHardKeyboardStatusChangeListener; 5669 available = mHardKeyboardAvailable; 5670 enabled = mHardKeyboardEnabled; 5671 } 5672 if (listener != null) { 5673 listener.onHardKeyboardStatusChange(available, enabled); 5674 } 5675 } 5676 5677 // ------------------------------------------------------------- 5678 // Drag and drop 5679 // ------------------------------------------------------------- 5680 5681 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 5682 int flags, int width, int height, Surface outSurface) { 5683 if (DEBUG_DRAG) { 5684 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 5685 + " flags=" + Integer.toHexString(flags) + " win=" + window 5686 + " asbinder=" + window.asBinder()); 5687 } 5688 5689 final int callerPid = Binder.getCallingPid(); 5690 final long origId = Binder.clearCallingIdentity(); 5691 IBinder token = null; 5692 5693 try { 5694 synchronized (mWindowMap) { 5695 try { 5696 if (mDragState == null) { 5697 Surface surface = new Surface(session, callerPid, "drag surface", 0, 5698 width, height, PixelFormat.TRANSLUCENT, Surface.HIDDEN); 5699 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 5700 + surface + ": CREATE"); 5701 outSurface.copyFrom(surface); 5702 final IBinder winBinder = window.asBinder(); 5703 token = new Binder(); 5704 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 5705 mDragState.mSurface = surface; 5706 token = mDragState.mToken = new Binder(); 5707 5708 // 5 second timeout for this window to actually begin the drag 5709 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 5710 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 5711 mH.sendMessageDelayed(msg, 5000); 5712 } else { 5713 Slog.w(TAG, "Drag already in progress"); 5714 } 5715 } catch (Surface.OutOfResourcesException e) { 5716 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 5717 if (mDragState != null) { 5718 mDragState.reset(); 5719 mDragState = null; 5720 } 5721 } 5722 } 5723 } finally { 5724 Binder.restoreCallingIdentity(origId); 5725 } 5726 5727 return token; 5728 } 5729 5730 // ------------------------------------------------------------- 5731 // Input Events and Focus Management 5732 // ------------------------------------------------------------- 5733 5734 final InputMonitor mInputMonitor = new InputMonitor(this); 5735 5736 public void pauseKeyDispatching(IBinder _token) { 5737 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 5738 "pauseKeyDispatching()")) { 5739 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 5740 } 5741 5742 synchronized (mWindowMap) { 5743 WindowToken token = mTokenMap.get(_token); 5744 if (token != null) { 5745 mInputMonitor.pauseDispatchingLw(token); 5746 } 5747 } 5748 } 5749 5750 public void resumeKeyDispatching(IBinder _token) { 5751 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 5752 "resumeKeyDispatching()")) { 5753 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 5754 } 5755 5756 synchronized (mWindowMap) { 5757 WindowToken token = mTokenMap.get(_token); 5758 if (token != null) { 5759 mInputMonitor.resumeDispatchingLw(token); 5760 } 5761 } 5762 } 5763 5764 public void setEventDispatching(boolean enabled) { 5765 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 5766 "resumeKeyDispatching()")) { 5767 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 5768 } 5769 5770 synchronized (mWindowMap) { 5771 mInputMonitor.setEventDispatchingLw(enabled); 5772 } 5773 } 5774 5775 /** 5776 * Injects a keystroke event into the UI. 5777 * Even when sync is false, this method may block while waiting for current 5778 * input events to be dispatched. 5779 * 5780 * @param ev A motion event describing the keystroke action. (Be sure to use 5781 * {@link SystemClock#uptimeMillis()} as the timebase.) 5782 * @param sync If true, wait for the event to be completed before returning to the caller. 5783 * @return Returns true if event was dispatched, false if it was dropped for any reason 5784 */ 5785 public boolean injectKeyEvent(KeyEvent ev, boolean sync) { 5786 long downTime = ev.getDownTime(); 5787 long eventTime = ev.getEventTime(); 5788 5789 int action = ev.getAction(); 5790 int code = ev.getKeyCode(); 5791 int repeatCount = ev.getRepeatCount(); 5792 int metaState = ev.getMetaState(); 5793 int deviceId = ev.getDeviceId(); 5794 int scancode = ev.getScanCode(); 5795 int source = ev.getSource(); 5796 int flags = ev.getFlags(); 5797 5798 if (source == InputDevice.SOURCE_UNKNOWN) { 5799 source = InputDevice.SOURCE_KEYBOARD; 5800 } 5801 5802 if (eventTime == 0) eventTime = SystemClock.uptimeMillis(); 5803 if (downTime == 0) downTime = eventTime; 5804 5805 KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState, 5806 deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source); 5807 5808 final int pid = Binder.getCallingPid(); 5809 final int uid = Binder.getCallingUid(); 5810 final long ident = Binder.clearCallingIdentity(); 5811 5812 final int result = mInputManager.injectInputEvent(newEvent, pid, uid, 5813 sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH 5814 : InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 5815 INJECTION_TIMEOUT_MILLIS); 5816 5817 Binder.restoreCallingIdentity(ident); 5818 return reportInjectionResult(result); 5819 } 5820 5821 /** 5822 * Inject a pointer (touch) event into the UI. 5823 * Even when sync is false, this method may block while waiting for current 5824 * input events to be dispatched. 5825 * 5826 * @param ev A motion event describing the pointer (touch) action. (As noted in 5827 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use 5828 * {@link SystemClock#uptimeMillis()} as the timebase.) 5829 * @param sync If true, wait for the event to be completed before returning to the caller. 5830 * @return Returns true if event was dispatched, false if it was dropped for any reason 5831 */ 5832 public boolean injectPointerEvent(MotionEvent ev, boolean sync) { 5833 final int pid = Binder.getCallingPid(); 5834 final int uid = Binder.getCallingUid(); 5835 final long ident = Binder.clearCallingIdentity(); 5836 5837 MotionEvent newEvent = MotionEvent.obtain(ev); 5838 if ((newEvent.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) { 5839 newEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN); 5840 } 5841 5842 final int result = mInputManager.injectInputEvent(newEvent, pid, uid, 5843 sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH 5844 : InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 5845 INJECTION_TIMEOUT_MILLIS); 5846 5847 Binder.restoreCallingIdentity(ident); 5848 return reportInjectionResult(result); 5849 } 5850 5851 /** 5852 * Inject a trackball (navigation device) event into the UI. 5853 * Even when sync is false, this method may block while waiting for current 5854 * input events to be dispatched. 5855 * 5856 * @param ev A motion event describing the trackball action. (As noted in 5857 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use 5858 * {@link SystemClock#uptimeMillis()} as the timebase.) 5859 * @param sync If true, wait for the event to be completed before returning to the caller. 5860 * @return Returns true if event was dispatched, false if it was dropped for any reason 5861 */ 5862 public boolean injectTrackballEvent(MotionEvent ev, boolean sync) { 5863 final int pid = Binder.getCallingPid(); 5864 final int uid = Binder.getCallingUid(); 5865 final long ident = Binder.clearCallingIdentity(); 5866 5867 MotionEvent newEvent = MotionEvent.obtain(ev); 5868 if ((newEvent.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) { 5869 newEvent.setSource(InputDevice.SOURCE_TRACKBALL); 5870 } 5871 5872 final int result = mInputManager.injectInputEvent(newEvent, pid, uid, 5873 sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH 5874 : InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 5875 INJECTION_TIMEOUT_MILLIS); 5876 5877 Binder.restoreCallingIdentity(ident); 5878 return reportInjectionResult(result); 5879 } 5880 5881 /** 5882 * Inject an input event into the UI without waiting for dispatch to commence. 5883 * This variant is useful for fire-and-forget input event injection. It does not 5884 * block any longer than it takes to enqueue the input event. 5885 * 5886 * @param ev An input event. (Be sure to set the input source correctly.) 5887 * @return Returns true if event was dispatched, false if it was dropped for any reason 5888 */ 5889 public boolean injectInputEventNoWait(InputEvent ev) { 5890 final int pid = Binder.getCallingPid(); 5891 final int uid = Binder.getCallingUid(); 5892 final long ident = Binder.clearCallingIdentity(); 5893 5894 final int result = mInputManager.injectInputEvent(ev, pid, uid, 5895 InputManager.INPUT_EVENT_INJECTION_SYNC_NONE, 5896 INJECTION_TIMEOUT_MILLIS); 5897 5898 Binder.restoreCallingIdentity(ident); 5899 return reportInjectionResult(result); 5900 } 5901 5902 private boolean reportInjectionResult(int result) { 5903 switch (result) { 5904 case InputManager.INPUT_EVENT_INJECTION_PERMISSION_DENIED: 5905 Slog.w(TAG, "Input event injection permission denied."); 5906 throw new SecurityException( 5907 "Injecting to another application requires INJECT_EVENTS permission"); 5908 case InputManager.INPUT_EVENT_INJECTION_SUCCEEDED: 5909 //Slog.v(TAG, "Input event injection succeeded."); 5910 return true; 5911 case InputManager.INPUT_EVENT_INJECTION_TIMED_OUT: 5912 Slog.w(TAG, "Input event injection timed out."); 5913 return false; 5914 case InputManager.INPUT_EVENT_INJECTION_FAILED: 5915 default: 5916 Slog.w(TAG, "Input event injection failed."); 5917 return false; 5918 } 5919 } 5920 5921 private WindowState getFocusedWindow() { 5922 synchronized (mWindowMap) { 5923 return getFocusedWindowLocked(); 5924 } 5925 } 5926 5927 private WindowState getFocusedWindowLocked() { 5928 return mCurrentFocus; 5929 } 5930 5931 public boolean detectSafeMode() { 5932 if (!mInputMonitor.waitForInputDevicesReady( 5933 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 5934 Slog.w(TAG, "Devices still not ready after waiting " 5935 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 5936 + " milliseconds before attempting to detect safe mode."); 5937 } 5938 5939 mSafeMode = mPolicy.detectSafeMode(); 5940 return mSafeMode; 5941 } 5942 5943 public void systemReady() { 5944 synchronized(mWindowMap) { 5945 if (mDisplay != null) { 5946 throw new IllegalStateException("Display already initialized"); 5947 } 5948 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); 5949 mDisplay = wm.getDefaultDisplay(); 5950 mInitialDisplayWidth = mDisplay.getRealWidth(); 5951 mInitialDisplayHeight = mDisplay.getRealHeight(); 5952 int rot = mDisplay.getRotation(); 5953 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 5954 // If the screen is currently rotated, we need to swap the 5955 // initial width and height to get the true natural values. 5956 int tmp = mInitialDisplayWidth; 5957 mInitialDisplayWidth = mInitialDisplayHeight; 5958 mInitialDisplayHeight = tmp; 5959 } 5960 mBaseDisplayWidth = mCurDisplayWidth = mInitialDisplayWidth; 5961 mBaseDisplayHeight = mCurDisplayHeight = mInitialDisplayHeight; 5962 mInputManager.setDisplaySize(0, mDisplay.getRawWidth(), mDisplay.getRawHeight()); 5963 mPolicy.setInitialDisplaySize(mInitialDisplayWidth, mInitialDisplayHeight); 5964 } 5965 5966 try { 5967 mActivityManager.updateConfiguration(null); 5968 } catch (RemoteException e) { 5969 } 5970 5971 mPolicy.systemReady(); 5972 } 5973 5974 // This is an animation that does nothing: it just immediately finishes 5975 // itself every time it is called. It is used as a stub animation in cases 5976 // where we want to synchronize multiple things that may be animating. 5977 static final class DummyAnimation extends Animation { 5978 public boolean getTransformation(long currentTime, Transformation outTransformation) { 5979 return false; 5980 } 5981 } 5982 static final Animation sDummyAnimation = new DummyAnimation(); 5983 5984 // ------------------------------------------------------------- 5985 // Async Handler 5986 // ------------------------------------------------------------- 5987 5988 final class H extends Handler { 5989 public static final int REPORT_FOCUS_CHANGE = 2; 5990 public static final int REPORT_LOSING_FOCUS = 3; 5991 public static final int ANIMATE = 4; 5992 public static final int ADD_STARTING = 5; 5993 public static final int REMOVE_STARTING = 6; 5994 public static final int FINISHED_STARTING = 7; 5995 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 5996 public static final int WINDOW_FREEZE_TIMEOUT = 11; 5997 public static final int HOLD_SCREEN_CHANGED = 12; 5998 public static final int APP_TRANSITION_TIMEOUT = 13; 5999 public static final int PERSIST_ANIMATION_SCALE = 14; 6000 public static final int FORCE_GC = 15; 6001 public static final int ENABLE_SCREEN = 16; 6002 public static final int APP_FREEZE_TIMEOUT = 17; 6003 public static final int SEND_NEW_CONFIGURATION = 18; 6004 public static final int REPORT_WINDOWS_CHANGE = 19; 6005 public static final int DRAG_START_TIMEOUT = 20; 6006 public static final int DRAG_END_TIMEOUT = 21; 6007 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 6008 6009 private Session mLastReportedHold; 6010 6011 public H() { 6012 } 6013 6014 @Override 6015 public void handleMessage(Message msg) { 6016 switch (msg.what) { 6017 case REPORT_FOCUS_CHANGE: { 6018 WindowState lastFocus; 6019 WindowState newFocus; 6020 6021 synchronized(mWindowMap) { 6022 lastFocus = mLastFocus; 6023 newFocus = mCurrentFocus; 6024 if (lastFocus == newFocus) { 6025 // Focus is not changing, so nothing to do. 6026 return; 6027 } 6028 mLastFocus = newFocus; 6029 //Slog.i(TAG, "Focus moving from " + lastFocus 6030 // + " to " + newFocus); 6031 if (newFocus != null && lastFocus != null 6032 && !newFocus.isDisplayedLw()) { 6033 //Slog.i(TAG, "Delaying loss of focus..."); 6034 mLosingFocus.add(lastFocus); 6035 lastFocus = null; 6036 } 6037 } 6038 6039 if (lastFocus != newFocus) { 6040 //System.out.println("Changing focus from " + lastFocus 6041 // + " to " + newFocus); 6042 if (newFocus != null) { 6043 try { 6044 //Slog.i(TAG, "Gaining focus: " + newFocus); 6045 newFocus.mClient.windowFocusChanged(true, mInTouchMode); 6046 } catch (RemoteException e) { 6047 // Ignore if process has died. 6048 } 6049 notifyFocusChanged(); 6050 } 6051 6052 if (lastFocus != null) { 6053 try { 6054 //Slog.i(TAG, "Losing focus: " + lastFocus); 6055 lastFocus.mClient.windowFocusChanged(false, mInTouchMode); 6056 } catch (RemoteException e) { 6057 // Ignore if process has died. 6058 } 6059 } 6060 6061 mPolicy.focusChanged(lastFocus, newFocus); 6062 } 6063 } break; 6064 6065 case REPORT_LOSING_FOCUS: { 6066 ArrayList<WindowState> losers; 6067 6068 synchronized(mWindowMap) { 6069 losers = mLosingFocus; 6070 mLosingFocus = new ArrayList<WindowState>(); 6071 } 6072 6073 final int N = losers.size(); 6074 for (int i=0; i<N; i++) { 6075 try { 6076 //Slog.i(TAG, "Losing delayed focus: " + losers.get(i)); 6077 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode); 6078 } catch (RemoteException e) { 6079 // Ignore if process has died. 6080 } 6081 } 6082 } break; 6083 6084 case ANIMATE: { 6085 synchronized(mWindowMap) { 6086 mAnimationPending = false; 6087 performLayoutAndPlaceSurfacesLocked(); 6088 } 6089 } break; 6090 6091 case ADD_STARTING: { 6092 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 6093 final StartingData sd = wtoken.startingData; 6094 6095 if (sd == null) { 6096 // Animation has been canceled... do nothing. 6097 return; 6098 } 6099 6100 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 6101 + wtoken + ": pkg=" + sd.pkg); 6102 6103 View view = null; 6104 try { 6105 view = mPolicy.addStartingWindow( 6106 wtoken.token, sd.pkg, 6107 sd.theme, sd.nonLocalizedLabel, sd.labelRes, 6108 sd.icon, sd.windowFlags); 6109 } catch (Exception e) { 6110 Slog.w(TAG, "Exception when adding starting window", e); 6111 } 6112 6113 if (view != null) { 6114 boolean abort = false; 6115 6116 synchronized(mWindowMap) { 6117 if (wtoken.removed || wtoken.startingData == null) { 6118 // If the window was successfully added, then 6119 // we need to remove it. 6120 if (wtoken.startingWindow != null) { 6121 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 6122 "Aborted starting " + wtoken 6123 + ": removed=" + wtoken.removed 6124 + " startingData=" + wtoken.startingData); 6125 wtoken.startingWindow = null; 6126 wtoken.startingData = null; 6127 abort = true; 6128 } 6129 } else { 6130 wtoken.startingView = view; 6131 } 6132 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 6133 "Added starting " + wtoken 6134 + ": startingWindow=" 6135 + wtoken.startingWindow + " startingView=" 6136 + wtoken.startingView); 6137 } 6138 6139 if (abort) { 6140 try { 6141 mPolicy.removeStartingWindow(wtoken.token, view); 6142 } catch (Exception e) { 6143 Slog.w(TAG, "Exception when removing starting window", e); 6144 } 6145 } 6146 } 6147 } break; 6148 6149 case REMOVE_STARTING: { 6150 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 6151 IBinder token = null; 6152 View view = null; 6153 synchronized (mWindowMap) { 6154 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 6155 + wtoken + ": startingWindow=" 6156 + wtoken.startingWindow + " startingView=" 6157 + wtoken.startingView); 6158 if (wtoken.startingWindow != null) { 6159 view = wtoken.startingView; 6160 token = wtoken.token; 6161 wtoken.startingData = null; 6162 wtoken.startingView = null; 6163 wtoken.startingWindow = null; 6164 } 6165 } 6166 if (view != null) { 6167 try { 6168 mPolicy.removeStartingWindow(token, view); 6169 } catch (Exception e) { 6170 Slog.w(TAG, "Exception when removing starting window", e); 6171 } 6172 } 6173 } break; 6174 6175 case FINISHED_STARTING: { 6176 IBinder token = null; 6177 View view = null; 6178 while (true) { 6179 synchronized (mWindowMap) { 6180 final int N = mFinishedStarting.size(); 6181 if (N <= 0) { 6182 break; 6183 } 6184 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 6185 6186 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 6187 "Finished starting " + wtoken 6188 + ": startingWindow=" + wtoken.startingWindow 6189 + " startingView=" + wtoken.startingView); 6190 6191 if (wtoken.startingWindow == null) { 6192 continue; 6193 } 6194 6195 view = wtoken.startingView; 6196 token = wtoken.token; 6197 wtoken.startingData = null; 6198 wtoken.startingView = null; 6199 wtoken.startingWindow = null; 6200 } 6201 6202 try { 6203 mPolicy.removeStartingWindow(token, view); 6204 } catch (Exception e) { 6205 Slog.w(TAG, "Exception when removing starting window", e); 6206 } 6207 } 6208 } break; 6209 6210 case REPORT_APPLICATION_TOKEN_WINDOWS: { 6211 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 6212 6213 boolean nowVisible = msg.arg1 != 0; 6214 boolean nowGone = msg.arg2 != 0; 6215 6216 try { 6217 if (DEBUG_VISIBILITY) Slog.v( 6218 TAG, "Reporting visible in " + wtoken 6219 + " visible=" + nowVisible 6220 + " gone=" + nowGone); 6221 if (nowVisible) { 6222 wtoken.appToken.windowsVisible(); 6223 } else { 6224 wtoken.appToken.windowsGone(); 6225 } 6226 } catch (RemoteException ex) { 6227 } 6228 } break; 6229 6230 case WINDOW_FREEZE_TIMEOUT: { 6231 synchronized (mWindowMap) { 6232 Slog.w(TAG, "Window freeze timeout expired."); 6233 int i = mWindows.size(); 6234 while (i > 0) { 6235 i--; 6236 WindowState w = mWindows.get(i); 6237 if (w.mOrientationChanging) { 6238 w.mOrientationChanging = false; 6239 Slog.w(TAG, "Force clearing orientation change: " + w); 6240 } 6241 } 6242 performLayoutAndPlaceSurfacesLocked(); 6243 } 6244 break; 6245 } 6246 6247 case HOLD_SCREEN_CHANGED: { 6248 Session oldHold; 6249 Session newHold; 6250 synchronized (mWindowMap) { 6251 oldHold = mLastReportedHold; 6252 newHold = (Session)msg.obj; 6253 mLastReportedHold = newHold; 6254 } 6255 6256 if (oldHold != newHold) { 6257 try { 6258 if (oldHold != null) { 6259 mBatteryStats.noteStopWakelock(oldHold.mUid, -1, 6260 "window", 6261 BatteryStats.WAKE_TYPE_WINDOW); 6262 } 6263 if (newHold != null) { 6264 mBatteryStats.noteStartWakelock(newHold.mUid, -1, 6265 "window", 6266 BatteryStats.WAKE_TYPE_WINDOW); 6267 } 6268 } catch (RemoteException e) { 6269 } 6270 } 6271 break; 6272 } 6273 6274 case APP_TRANSITION_TIMEOUT: { 6275 synchronized (mWindowMap) { 6276 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 6277 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 6278 "*** APP TRANSITION TIMEOUT"); 6279 mAppTransitionReady = true; 6280 mAppTransitionTimeout = true; 6281 performLayoutAndPlaceSurfacesLocked(); 6282 } 6283 } 6284 break; 6285 } 6286 6287 case PERSIST_ANIMATION_SCALE: { 6288 Settings.System.putFloat(mContext.getContentResolver(), 6289 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); 6290 Settings.System.putFloat(mContext.getContentResolver(), 6291 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); 6292 break; 6293 } 6294 6295 case FORCE_GC: { 6296 synchronized(mWindowMap) { 6297 if (mAnimationPending) { 6298 // If we are animating, don't do the gc now but 6299 // delay a bit so we don't interrupt the animation. 6300 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 6301 2000); 6302 return; 6303 } 6304 // If we are currently rotating the display, it will 6305 // schedule a new message when done. 6306 if (mDisplayFrozen) { 6307 return; 6308 } 6309 mFreezeGcPending = 0; 6310 } 6311 Runtime.getRuntime().gc(); 6312 break; 6313 } 6314 6315 case ENABLE_SCREEN: { 6316 performEnableScreen(); 6317 break; 6318 } 6319 6320 case APP_FREEZE_TIMEOUT: { 6321 synchronized (mWindowMap) { 6322 Slog.w(TAG, "App freeze timeout expired."); 6323 int i = mAppTokens.size(); 6324 while (i > 0) { 6325 i--; 6326 AppWindowToken tok = mAppTokens.get(i); 6327 if (tok.freezingScreen) { 6328 Slog.w(TAG, "Force clearing freeze: " + tok); 6329 unsetAppFreezingScreenLocked(tok, true, true); 6330 } 6331 } 6332 } 6333 break; 6334 } 6335 6336 case SEND_NEW_CONFIGURATION: { 6337 removeMessages(SEND_NEW_CONFIGURATION); 6338 sendNewConfiguration(); 6339 break; 6340 } 6341 6342 case REPORT_WINDOWS_CHANGE: { 6343 if (mWindowsChanged) { 6344 synchronized (mWindowMap) { 6345 mWindowsChanged = false; 6346 } 6347 notifyWindowsChanged(); 6348 } 6349 break; 6350 } 6351 6352 case DRAG_START_TIMEOUT: { 6353 IBinder win = (IBinder)msg.obj; 6354 if (DEBUG_DRAG) { 6355 Slog.w(TAG, "Timeout starting drag by win " + win); 6356 } 6357 synchronized (mWindowMap) { 6358 // !!! TODO: ANR the app that has failed to start the drag in time 6359 if (mDragState != null) { 6360 mDragState.unregister(); 6361 mInputMonitor.updateInputWindowsLw(true /*force*/); 6362 mDragState.reset(); 6363 mDragState = null; 6364 } 6365 } 6366 break; 6367 } 6368 6369 case DRAG_END_TIMEOUT: { 6370 IBinder win = (IBinder)msg.obj; 6371 if (DEBUG_DRAG) { 6372 Slog.w(TAG, "Timeout ending drag to win " + win); 6373 } 6374 synchronized (mWindowMap) { 6375 // !!! TODO: ANR the drag-receiving app 6376 mDragState.mDragResult = false; 6377 mDragState.endDragLw(); 6378 } 6379 break; 6380 } 6381 6382 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 6383 notifyHardKeyboardStatusChange(); 6384 break; 6385 } 6386 } 6387 } 6388 } 6389 6390 // ------------------------------------------------------------- 6391 // IWindowManager API 6392 // ------------------------------------------------------------- 6393 6394 public IWindowSession openSession(IInputMethodClient client, 6395 IInputContext inputContext) { 6396 if (client == null) throw new IllegalArgumentException("null client"); 6397 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 6398 Session session = new Session(this, client, inputContext); 6399 return session; 6400 } 6401 6402 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 6403 synchronized (mWindowMap) { 6404 // The focus for the client is the window immediately below 6405 // where we would place the input method window. 6406 int idx = findDesiredInputMethodWindowIndexLocked(false); 6407 WindowState imFocus; 6408 if (idx > 0) { 6409 imFocus = mWindows.get(idx-1); 6410 //Log.i(TAG, "Desired input method target: " + imFocus); 6411 //Log.i(TAG, "Current focus: " + this.mCurrentFocus); 6412 //Log.i(TAG, "Last focus: " + this.mLastFocus); 6413 if (imFocus != null) { 6414 // This may be a starting window, in which case we still want 6415 // to count it as okay. 6416 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 6417 && imFocus.mAppToken != null) { 6418 // The client has definitely started, so it really should 6419 // have a window in this app token. Let's look for it. 6420 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 6421 WindowState w = imFocus.mAppToken.windows.get(i); 6422 if (w != imFocus) { 6423 //Log.i(TAG, "Switching to real app window: " + w); 6424 imFocus = w; 6425 break; 6426 } 6427 } 6428 } 6429 //Log.i(TAG, "IM target client: " + imFocus.mSession.mClient); 6430 //if (imFocus.mSession.mClient != null) { 6431 // Log.i(TAG, "IM target client binder: " + imFocus.mSession.mClient.asBinder()); 6432 // Log.i(TAG, "Requesting client binder: " + client.asBinder()); 6433 //} 6434 if (imFocus.mSession.mClient != null && 6435 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 6436 return true; 6437 } 6438 6439 // Okay, how about this... what is the current focus? 6440 // It seems in some cases we may not have moved the IM 6441 // target window, such as when it was in a pop-up window, 6442 // so let's also look at the current focus. (An example: 6443 // go to Gmail, start searching so the keyboard goes up, 6444 // press home. Sometimes the IME won't go down.) 6445 // Would be nice to fix this more correctly, but it's 6446 // way at the end of a release, and this should be good enough. 6447 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null && 6448 mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 6449 return true; 6450 } 6451 } 6452 } 6453 } 6454 return false; 6455 } 6456 6457 public void getDisplaySize(Point size) { 6458 synchronized(mWindowMap) { 6459 size.x = mCurDisplayWidth; 6460 size.y = mCurDisplayHeight; 6461 } 6462 } 6463 6464 public int getMaximumSizeDimension() { 6465 synchronized(mWindowMap) { 6466 // Do this based on the raw screen size, until we are smarter. 6467 return mBaseDisplayWidth > mBaseDisplayHeight 6468 ? mBaseDisplayWidth : mBaseDisplayHeight; 6469 } 6470 } 6471 6472 public void setForcedDisplaySize(int longDimen, int shortDimen) { 6473 synchronized(mWindowMap) { 6474 int width, height; 6475 if (mInitialDisplayWidth < mInitialDisplayHeight) { 6476 width = shortDimen < mInitialDisplayWidth 6477 ? shortDimen : mInitialDisplayWidth; 6478 height = longDimen < mInitialDisplayHeight 6479 ? longDimen : mInitialDisplayHeight; 6480 } else { 6481 width = longDimen < mInitialDisplayWidth 6482 ? longDimen : mInitialDisplayWidth; 6483 height = shortDimen < mInitialDisplayHeight 6484 ? shortDimen : mInitialDisplayHeight; 6485 } 6486 setForcedDisplaySizeLocked(width, height); 6487 } 6488 } 6489 6490 private void rebuildBlackFrame(boolean inTransaction) { 6491 if (!inTransaction) { 6492 if (SHOW_TRANSACTIONS) Slog.i(TAG, 6493 ">>> OPEN TRANSACTION rebuildBlackFrame"); 6494 Surface.openTransaction(); 6495 } 6496 try { 6497 if (mBlackFrame != null) { 6498 mBlackFrame.kill(); 6499 mBlackFrame = null; 6500 } 6501 if (mBaseDisplayWidth < mInitialDisplayWidth 6502 || mBaseDisplayHeight < mInitialDisplayHeight) { 6503 Rect outer = new Rect(0, 0, mInitialDisplayWidth, mInitialDisplayHeight); 6504 Rect inner = new Rect(0, 0, mBaseDisplayWidth, mBaseDisplayHeight); 6505 try { 6506 mBlackFrame = new BlackFrame(mFxSession, outer, inner, MASK_LAYER); 6507 } catch (Surface.OutOfResourcesException e) { 6508 } 6509 } 6510 } finally { 6511 if (!inTransaction) { 6512 Surface.closeTransaction(); 6513 if (SHOW_TRANSACTIONS) Slog.i(TAG, 6514 "<<< CLOSE TRANSACTION rebuildBlackFrame"); 6515 } 6516 } 6517 } 6518 6519 private void setForcedDisplaySizeLocked(int width, int height) { 6520 mBaseDisplayWidth = width; 6521 mBaseDisplayHeight = height; 6522 mPolicy.setInitialDisplaySize(mBaseDisplayWidth, mBaseDisplayHeight); 6523 6524 mLayoutNeeded = true; 6525 6526 boolean configChanged = updateOrientationFromAppTokensLocked(false); 6527 mTempConfiguration.setToDefaults(); 6528 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 6529 if (computeNewConfigurationLocked(mTempConfiguration)) { 6530 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 6531 configChanged = true; 6532 } 6533 } 6534 6535 if (configChanged) { 6536 mWaitingForConfig = true; 6537 startFreezingDisplayLocked(false); 6538 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6539 } 6540 6541 rebuildBlackFrame(false); 6542 6543 performLayoutAndPlaceSurfacesLocked(); 6544 } 6545 6546 public void clearForcedDisplaySize() { 6547 synchronized(mWindowMap) { 6548 setForcedDisplaySizeLocked(mInitialDisplayWidth, mInitialDisplayHeight); 6549 } 6550 } 6551 6552 // ------------------------------------------------------------- 6553 // Internals 6554 // ------------------------------------------------------------- 6555 6556 final WindowState windowForClientLocked(Session session, IWindow client, 6557 boolean throwOnError) { 6558 return windowForClientLocked(session, client.asBinder(), throwOnError); 6559 } 6560 6561 final WindowState windowForClientLocked(Session session, IBinder client, 6562 boolean throwOnError) { 6563 WindowState win = mWindowMap.get(client); 6564 if (localLOGV) Slog.v( 6565 TAG, "Looking up client " + client + ": " + win); 6566 if (win == null) { 6567 RuntimeException ex = new IllegalArgumentException( 6568 "Requested window " + client + " does not exist"); 6569 if (throwOnError) { 6570 throw ex; 6571 } 6572 Slog.w(TAG, "Failed looking up window", ex); 6573 return null; 6574 } 6575 if (session != null && win.mSession != session) { 6576 RuntimeException ex = new IllegalArgumentException( 6577 "Requested window " + client + " is in session " + 6578 win.mSession + ", not " + session); 6579 if (throwOnError) { 6580 throw ex; 6581 } 6582 Slog.w(TAG, "Failed looking up window", ex); 6583 return null; 6584 } 6585 6586 return win; 6587 } 6588 6589 final void rebuildAppWindowListLocked() { 6590 int NW = mWindows.size(); 6591 int i; 6592 int lastWallpaper = -1; 6593 int numRemoved = 0; 6594 6595 if (mRebuildTmp.length < NW) { 6596 mRebuildTmp = new WindowState[NW+10]; 6597 } 6598 6599 // First remove all existing app windows. 6600 i=0; 6601 while (i < NW) { 6602 WindowState w = mWindows.get(i); 6603 if (w.mAppToken != null) { 6604 WindowState win = mWindows.remove(i); 6605 win.mRebuilding = true; 6606 mRebuildTmp[numRemoved] = win; 6607 mWindowsChanged = true; 6608 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 6609 "Rebuild removing window: " + win); 6610 NW--; 6611 numRemoved++; 6612 continue; 6613 } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER 6614 && lastWallpaper == i-1) { 6615 lastWallpaper = i; 6616 } 6617 i++; 6618 } 6619 6620 // The wallpaper window(s) typically live at the bottom of the stack, 6621 // so skip them before adding app tokens. 6622 lastWallpaper++; 6623 i = lastWallpaper; 6624 6625 // First add all of the exiting app tokens... these are no longer 6626 // in the main app list, but still have windows shown. We put them 6627 // in the back because now that the animation is over we no longer 6628 // will care about them. 6629 int NT = mExitingAppTokens.size(); 6630 for (int j=0; j<NT; j++) { 6631 i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j)); 6632 } 6633 6634 // And add in the still active app tokens in Z order. 6635 NT = mAppTokens.size(); 6636 for (int j=0; j<NT; j++) { 6637 i = reAddAppWindowsLocked(i, mAppTokens.get(j)); 6638 } 6639 6640 i -= lastWallpaper; 6641 if (i != numRemoved) { 6642 Slog.w(TAG, "Rebuild removed " + numRemoved 6643 + " windows but added " + i); 6644 for (i=0; i<numRemoved; i++) { 6645 WindowState ws = mRebuildTmp[i]; 6646 if (ws.mRebuilding) { 6647 StringWriter sw = new StringWriter(); 6648 PrintWriter pw = new PrintWriter(sw); 6649 ws.dump(pw, ""); 6650 pw.flush(); 6651 Slog.w(TAG, "This window was lost: " + ws); 6652 Slog.w(TAG, sw.toString()); 6653 } 6654 } 6655 Slog.w(TAG, "Current app token list:"); 6656 dumpAppTokensLocked(); 6657 Slog.w(TAG, "Final window list:"); 6658 dumpWindowsLocked(); 6659 } 6660 } 6661 6662 private final void assignLayersLocked() { 6663 int N = mWindows.size(); 6664 int curBaseLayer = 0; 6665 int curLayer = 0; 6666 int i; 6667 6668 if (DEBUG_LAYERS) { 6669 RuntimeException here = new RuntimeException("here"); 6670 here.fillInStackTrace(); 6671 Log.v(TAG, "Assigning layers", here); 6672 } 6673 6674 for (i=0; i<N; i++) { 6675 WindowState w = mWindows.get(i); 6676 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 6677 || (i > 0 && w.mIsWallpaper)) { 6678 curLayer += WINDOW_LAYER_MULTIPLIER; 6679 w.mLayer = curLayer; 6680 } else { 6681 curBaseLayer = curLayer = w.mBaseLayer; 6682 w.mLayer = curLayer; 6683 } 6684 if (w.mTargetAppToken != null) { 6685 w.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment; 6686 } else if (w.mAppToken != null) { 6687 w.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment; 6688 } else { 6689 w.mAnimLayer = w.mLayer; 6690 } 6691 if (w.mIsImWindow) { 6692 w.mAnimLayer += mInputMethodAnimLayerAdjustment; 6693 } else if (w.mIsWallpaper) { 6694 w.mAnimLayer += mWallpaperAnimLayerAdjustment; 6695 } 6696 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 6697 + w.mAnimLayer); 6698 //System.out.println( 6699 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 6700 } 6701 } 6702 6703 private boolean mInLayout = false; 6704 private final void performLayoutAndPlaceSurfacesLocked() { 6705 if (mInLayout) { 6706 if (DEBUG) { 6707 throw new RuntimeException("Recursive call!"); 6708 } 6709 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout"); 6710 return; 6711 } 6712 6713 if (mWaitingForConfig) { 6714 // Our configuration has changed (most likely rotation), but we 6715 // don't yet have the complete configuration to report to 6716 // applications. Don't do any window layout until we have it. 6717 return; 6718 } 6719 6720 if (mDisplay == null) { 6721 // Not yet initialized, nothing to do. 6722 return; 6723 } 6724 6725 mInLayout = true; 6726 boolean recoveringMemory = false; 6727 6728 try { 6729 if (mForceRemoves != null) { 6730 recoveringMemory = true; 6731 // Wait a little bit for things to settle down, and off we go. 6732 for (int i=0; i<mForceRemoves.size(); i++) { 6733 WindowState ws = mForceRemoves.get(i); 6734 Slog.i(TAG, "Force removing: " + ws); 6735 removeWindowInnerLocked(ws.mSession, ws); 6736 } 6737 mForceRemoves = null; 6738 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 6739 Object tmp = new Object(); 6740 synchronized (tmp) { 6741 try { 6742 tmp.wait(250); 6743 } catch (InterruptedException e) { 6744 } 6745 } 6746 } 6747 } catch (RuntimeException e) { 6748 Slog.e(TAG, "Unhandled exception while force removing for memory", e); 6749 } 6750 6751 try { 6752 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 6753 6754 int N = mPendingRemove.size(); 6755 if (N > 0) { 6756 if (mPendingRemoveTmp.length < N) { 6757 mPendingRemoveTmp = new WindowState[N+10]; 6758 } 6759 mPendingRemove.toArray(mPendingRemoveTmp); 6760 mPendingRemove.clear(); 6761 for (int i=0; i<N; i++) { 6762 WindowState w = mPendingRemoveTmp[i]; 6763 removeWindowInnerLocked(w.mSession, w); 6764 } 6765 6766 mInLayout = false; 6767 assignLayersLocked(); 6768 mLayoutNeeded = true; 6769 performLayoutAndPlaceSurfacesLocked(); 6770 6771 } else { 6772 mInLayout = false; 6773 if (mLayoutNeeded) { 6774 requestAnimationLocked(0); 6775 } 6776 } 6777 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 6778 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 6779 mH.sendMessage(mH.obtainMessage(H.REPORT_WINDOWS_CHANGE)); 6780 } 6781 } catch (RuntimeException e) { 6782 mInLayout = false; 6783 Slog.e(TAG, "Unhandled exception while layout out windows", e); 6784 } 6785 } 6786 6787 private final int performLayoutLockedInner(boolean initial, boolean updateInputWindows) { 6788 if (!mLayoutNeeded) { 6789 return 0; 6790 } 6791 6792 mLayoutNeeded = false; 6793 6794 final int dw = mCurDisplayWidth; 6795 final int dh = mCurDisplayHeight; 6796 6797 final int innerDw = mPolicy.getNonDecorDisplayWidth(dw); 6798 final int innerDh = mPolicy.getNonDecorDisplayHeight(dh); 6799 6800 final int N = mWindows.size(); 6801 int i; 6802 6803 if (DEBUG_LAYOUT) Slog.v(TAG, "performLayout: needed=" 6804 + mLayoutNeeded + " dw=" + dw + " dh=" + dh); 6805 6806 mPolicy.beginLayoutLw(dw, dh); 6807 6808 int seq = mLayoutSeq+1; 6809 if (seq < 0) seq = 0; 6810 mLayoutSeq = seq; 6811 6812 // First perform layout of any root windows (not attached 6813 // to another window). 6814 int topAttached = -1; 6815 for (i = N-1; i >= 0; i--) { 6816 WindowState win = mWindows.get(i); 6817 6818 // Don't do layout of a window if it is not visible, or 6819 // soon won't be visible, to avoid wasting time and funky 6820 // changes while a window is animating away. 6821 final AppWindowToken atoken = win.mAppToken; 6822 final boolean gone = win.mViewVisibility == View.GONE 6823 || !win.mRelayoutCalled 6824 || (atoken == null && win.mRootToken.hidden) 6825 || (atoken != null && atoken.hiddenRequested) 6826 || win.mAttachedHidden 6827 || win.mExiting || win.mDestroying; 6828 6829 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 6830 Slog.v(TAG, "First pass " + win 6831 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 6832 + " mLayoutAttached=" + win.mLayoutAttached); 6833 if (gone) Slog.v(TAG, " (mViewVisibility=" 6834 + win.mViewVisibility + " mRelayoutCalled=" 6835 + win.mRelayoutCalled + " hidden=" 6836 + win.mRootToken.hidden + " hiddenRequested=" 6837 + (atoken != null && atoken.hiddenRequested) 6838 + " mAttachedHidden=" + win.mAttachedHidden); 6839 } 6840 6841 // If this view is GONE, then skip it -- keep the current 6842 // frame, and let the caller know so they can ignore it 6843 // if they want. (We do the normal layout for INVISIBLE 6844 // windows, since that means "perform layout as normal, 6845 // just don't display"). 6846 if (!gone || !win.mHaveFrame) { 6847 if (!win.mLayoutAttached) { 6848 if (initial) { 6849 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 6850 win.mContentChanged = false; 6851 } 6852 win.prelayout(); 6853 mPolicy.layoutWindowLw(win, win.mAttrs, null); 6854 win.evalNeedsBackgroundFiller(innerDw, innerDh); 6855 win.mLayoutSeq = seq; 6856 if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame=" 6857 + win.mFrame + " mContainingFrame=" 6858 + win.mContainingFrame + " mDisplayFrame=" 6859 + win.mDisplayFrame); 6860 } else { 6861 if (topAttached < 0) topAttached = i; 6862 } 6863 } 6864 } 6865 6866 // Now perform layout of attached windows, which usually 6867 // depend on the position of the window they are attached to. 6868 // XXX does not deal with windows that are attached to windows 6869 // that are themselves attached. 6870 for (i = topAttached; i >= 0; i--) { 6871 WindowState win = mWindows.get(i); 6872 6873 if (win.mLayoutAttached) { 6874 if (DEBUG_LAYOUT) Slog.v(TAG, "Second pass " + win 6875 + " mHaveFrame=" + win.mHaveFrame 6876 + " mViewVisibility=" + win.mViewVisibility 6877 + " mRelayoutCalled=" + win.mRelayoutCalled); 6878 // If this view is GONE, then skip it -- keep the current 6879 // frame, and let the caller know so they can ignore it 6880 // if they want. (We do the normal layout for INVISIBLE 6881 // windows, since that means "perform layout as normal, 6882 // just don't display"). 6883 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 6884 || !win.mHaveFrame) { 6885 if (initial) { 6886 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 6887 win.mContentChanged = false; 6888 } 6889 win.prelayout(); 6890 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 6891 win.evalNeedsBackgroundFiller(innerDw, innerDh); 6892 win.mLayoutSeq = seq; 6893 if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame=" 6894 + win.mFrame + " mContainingFrame=" 6895 + win.mContainingFrame + " mDisplayFrame=" 6896 + win.mDisplayFrame); 6897 } 6898 } 6899 } 6900 6901 // Window frames may have changed. Tell the input dispatcher about it. 6902 mInputMonitor.setUpdateInputWindowsNeededLw(); 6903 if (updateInputWindows) { 6904 mInputMonitor.updateInputWindowsLw(false /*force*/); 6905 } 6906 6907 return mPolicy.finishLayoutLw(); 6908 } 6909 6910 // "Something has changed! Let's make it correct now." 6911 private final void performLayoutAndPlaceSurfacesLockedInner( 6912 boolean recoveringMemory) { 6913 if (mDisplay == null) { 6914 Slog.i(TAG, "skipping performLayoutAndPlaceSurfacesLockedInner with no mDisplay"); 6915 return; 6916 } 6917 6918 final long currentTime = SystemClock.uptimeMillis(); 6919 final int dw = mCurDisplayWidth; 6920 final int dh = mCurDisplayHeight; 6921 6922 final int innerDw = mPolicy.getNonDecorDisplayWidth(dw); 6923 final int innerDh = mPolicy.getNonDecorDisplayHeight(dh); 6924 6925 int i; 6926 6927 if (mFocusMayChange) { 6928 mFocusMayChange = false; 6929 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 6930 false /*updateInputWindows*/); 6931 } 6932 6933 // Initialize state of exiting tokens. 6934 for (i=mExitingTokens.size()-1; i>=0; i--) { 6935 mExitingTokens.get(i).hasVisible = false; 6936 } 6937 6938 // Initialize state of exiting applications. 6939 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 6940 mExitingAppTokens.get(i).hasVisible = false; 6941 } 6942 6943 boolean orientationChangeComplete = true; 6944 Session holdScreen = null; 6945 float screenBrightness = -1; 6946 float buttonBrightness = -1; 6947 boolean focusDisplayed = false; 6948 boolean animating = false; 6949 boolean createWatermark = false; 6950 boolean updateRotation = false; 6951 boolean screenRotationFinished = false; 6952 6953 if (mFxSession == null) { 6954 mFxSession = new SurfaceSession(); 6955 createWatermark = true; 6956 } 6957 6958 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 6959 6960 Surface.openTransaction(); 6961 6962 if (createWatermark) { 6963 createWatermark(); 6964 } 6965 if (mWatermark != null) { 6966 mWatermark.positionSurface(dw, dh); 6967 } 6968 if (mStrictModeFlash != null) { 6969 mStrictModeFlash.positionSurface(dw, dh); 6970 } 6971 6972 try { 6973 boolean wallpaperForceHidingChanged = false; 6974 int repeats = 0; 6975 int changes = 0; 6976 6977 do { 6978 repeats++; 6979 if (repeats > 6) { 6980 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 6981 mLayoutNeeded = false; 6982 break; 6983 } 6984 6985 if ((changes&(WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER 6986 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG 6987 | WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT)) != 0) { 6988 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) { 6989 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 6990 assignLayersLocked(); 6991 mLayoutNeeded = true; 6992 } 6993 } 6994 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 6995 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 6996 if (updateOrientationFromAppTokensLocked(true)) { 6997 mLayoutNeeded = true; 6998 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6999 } 7000 } 7001 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 7002 mLayoutNeeded = true; 7003 } 7004 } 7005 7006 // FIRST LOOP: Perform a layout, if needed. 7007 if (repeats < 4) { 7008 changes = performLayoutLockedInner(repeats == 0, false /*updateInputWindows*/); 7009 if (changes != 0) { 7010 continue; 7011 } 7012 } else { 7013 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 7014 changes = 0; 7015 } 7016 7017 final int transactionSequence = ++mTransactionSequence; 7018 7019 // Update animations of all applications, including those 7020 // associated with exiting/removed apps 7021 boolean tokensAnimating = false; 7022 final int NAT = mAppTokens.size(); 7023 for (i=0; i<NAT; i++) { 7024 if (mAppTokens.get(i).stepAnimationLocked(currentTime, 7025 innerDw, innerDh)) { 7026 tokensAnimating = true; 7027 } 7028 } 7029 final int NEAT = mExitingAppTokens.size(); 7030 for (i=0; i<NEAT; i++) { 7031 if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime, 7032 innerDw, innerDh)) { 7033 tokensAnimating = true; 7034 } 7035 } 7036 7037 // SECOND LOOP: Execute animations and update visibility of windows. 7038 7039 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq=" 7040 + transactionSequence + " tokensAnimating=" 7041 + tokensAnimating); 7042 7043 animating = tokensAnimating; 7044 7045 if (mScreenRotationAnimation != null) { 7046 if (mScreenRotationAnimation.isAnimating()) { 7047 if (mScreenRotationAnimation.stepAnimation(currentTime)) { 7048 animating = true; 7049 } else { 7050 screenRotationFinished = true; 7051 updateRotation = true; 7052 } 7053 } 7054 } 7055 7056 boolean tokenMayBeDrawn = false; 7057 boolean wallpaperMayChange = false; 7058 boolean forceHiding = false; 7059 WindowState windowDetachedWallpaper = null; 7060 WindowState windowAnimationBackground = null; 7061 int windowAnimationBackgroundColor = 0; 7062 7063 mPolicy.beginAnimationLw(dw, dh); 7064 7065 final int N = mWindows.size(); 7066 7067 for (i=N-1; i>=0; i--) { 7068 WindowState w = mWindows.get(i); 7069 7070 final WindowManager.LayoutParams attrs = w.mAttrs; 7071 7072 if (w.mSurface != null) { 7073 // Take care of the window being ready to display. 7074 if (w.commitFinishDrawingLocked(currentTime)) { 7075 if ((w.mAttrs.flags 7076 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { 7077 if (DEBUG_WALLPAPER) Slog.v(TAG, 7078 "First draw done in potential wallpaper target " + w); 7079 wallpaperMayChange = true; 7080 } 7081 } 7082 7083 final boolean wasAnimating = w.mAnimating; 7084 7085 int animDw = innerDw; 7086 int animDh = innerDh; 7087 7088 // If the window has moved due to its containing 7089 // content frame changing, then we'd like to animate 7090 // it. The checks here are ordered by what is least 7091 // likely to be true first. 7092 if (w.shouldAnimateMove()) { 7093 // Frame has moved, containing content frame 7094 // has also moved, and we're not currently animating... 7095 // let's do something. 7096 Animation a = AnimationUtils.loadAnimation(mContext, 7097 com.android.internal.R.anim.window_move_from_decor); 7098 w.setAnimation(a); 7099 animDw = w.mLastFrame.left - w.mFrame.left; 7100 animDh = w.mLastFrame.top - w.mFrame.top; 7101 } 7102 7103 // Execute animation. 7104 final boolean nowAnimating = w.stepAnimationLocked(currentTime, 7105 animDw, animDh); 7106 7107 // If this window is animating, make a note that we have 7108 // an animating window and take care of a request to run 7109 // a detached wallpaper animation. 7110 if (nowAnimating) { 7111 if (w.mAnimation != null) { 7112 if (w.mAnimation.getDetachWallpaper()) { 7113 windowDetachedWallpaper = w; 7114 } 7115 if (w.mAnimation.getBackgroundColor() != 0) { 7116 windowAnimationBackground = w; 7117 windowAnimationBackgroundColor = 7118 w.mAnimation.getBackgroundColor(); 7119 } 7120 } 7121 animating = true; 7122 } 7123 7124 // If this window's app token is running a detached wallpaper 7125 // animation, make a note so we can ensure the wallpaper is 7126 // displayed behind it. 7127 if (w.mAppToken != null && w.mAppToken.animation != null) { 7128 if (w.mAppToken.animation.getDetachWallpaper()) { 7129 windowDetachedWallpaper = w; 7130 } 7131 if (w.mAppToken.animation.getBackgroundColor() != 0) { 7132 windowAnimationBackground = w; 7133 windowAnimationBackgroundColor = 7134 w.mAppToken.animation.getBackgroundColor(); 7135 } 7136 } 7137 7138 if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) { 7139 wallpaperMayChange = true; 7140 } 7141 7142 if (mPolicy.doesForceHide(w, attrs)) { 7143 if (!wasAnimating && nowAnimating) { 7144 if (DEBUG_VISIBILITY) Slog.v(TAG, 7145 "Animation started that could impact force hide: " 7146 + w); 7147 wallpaperForceHidingChanged = true; 7148 mFocusMayChange = true; 7149 } else if (w.isReadyForDisplay() && w.mAnimation == null) { 7150 forceHiding = true; 7151 } 7152 } else if (mPolicy.canBeForceHidden(w, attrs)) { 7153 boolean changed; 7154 if (forceHiding) { 7155 changed = w.hideLw(false, false); 7156 if (DEBUG_VISIBILITY && changed) Slog.v(TAG, 7157 "Now policy hidden: " + w); 7158 } else { 7159 changed = w.showLw(false, false); 7160 if (DEBUG_VISIBILITY && changed) Slog.v(TAG, 7161 "Now policy shown: " + w); 7162 if (changed) { 7163 if (wallpaperForceHidingChanged 7164 && w.isVisibleNow() /*w.isReadyForDisplay()*/) { 7165 // Assume we will need to animate. If 7166 // we don't (because the wallpaper will 7167 // stay with the lock screen), then we will 7168 // clean up later. 7169 Animation a = mPolicy.createForceHideEnterAnimation(); 7170 if (a != null) { 7171 w.setAnimation(a); 7172 } 7173 } 7174 if (mCurrentFocus == null || 7175 mCurrentFocus.mLayer < w.mLayer) { 7176 // We are showing on to of the current 7177 // focus, so re-evaluate focus to make 7178 // sure it is correct. 7179 mFocusMayChange = true; 7180 } 7181 } 7182 } 7183 if (changed && (attrs.flags 7184 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { 7185 wallpaperMayChange = true; 7186 } 7187 } 7188 7189 mPolicy.animatingWindowLw(w, attrs); 7190 } 7191 7192 final AppWindowToken atoken = w.mAppToken; 7193 if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) { 7194 if (atoken.lastTransactionSequence != transactionSequence) { 7195 atoken.lastTransactionSequence = transactionSequence; 7196 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 7197 atoken.startingDisplayed = false; 7198 } 7199 if ((w.isOnScreen() || w.mAttrs.type 7200 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION) 7201 && !w.mExiting && !w.mDestroying) { 7202 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 7203 Slog.v(TAG, "Eval win " + w + ": isDrawn=" 7204 + w.isDrawnLw() 7205 + ", isAnimating=" + w.isAnimating()); 7206 if (!w.isDrawnLw()) { 7207 Slog.v(TAG, "Not displayed: s=" + w.mSurface 7208 + " pv=" + w.mPolicyVisibility 7209 + " dp=" + w.mDrawPending 7210 + " cdp=" + w.mCommitDrawPending 7211 + " ah=" + w.mAttachedHidden 7212 + " th=" + atoken.hiddenRequested 7213 + " a=" + w.mAnimating); 7214 } 7215 } 7216 if (w != atoken.startingWindow) { 7217 if (!atoken.freezingScreen || !w.mAppFreezing) { 7218 atoken.numInterestingWindows++; 7219 if (w.isDrawnLw()) { 7220 atoken.numDrawnWindows++; 7221 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 7222 "tokenMayBeDrawn: " + atoken 7223 + " freezingScreen=" + atoken.freezingScreen 7224 + " mAppFreezing=" + w.mAppFreezing); 7225 tokenMayBeDrawn = true; 7226 } 7227 } 7228 } else if (w.isDrawnLw()) { 7229 atoken.startingDisplayed = true; 7230 } 7231 } 7232 } else if (w.mReadyToShow) { 7233 w.performShowLocked(); 7234 } 7235 } 7236 7237 changes |= mPolicy.finishAnimationLw(); 7238 7239 if (tokenMayBeDrawn) { 7240 // See if any windows have been drawn, so they (and others 7241 // associated with them) can now be shown. 7242 final int NT = mAppTokens.size(); 7243 for (i=0; i<NT; i++) { 7244 AppWindowToken wtoken = mAppTokens.get(i); 7245 if (wtoken.freezingScreen) { 7246 int numInteresting = wtoken.numInterestingWindows; 7247 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 7248 if (DEBUG_VISIBILITY) Slog.v(TAG, 7249 "allDrawn: " + wtoken 7250 + " interesting=" + numInteresting 7251 + " drawn=" + wtoken.numDrawnWindows); 7252 wtoken.showAllWindowsLocked(); 7253 unsetAppFreezingScreenLocked(wtoken, false, true); 7254 orientationChangeComplete = true; 7255 } 7256 } else if (!wtoken.allDrawn) { 7257 int numInteresting = wtoken.numInterestingWindows; 7258 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 7259 if (DEBUG_VISIBILITY) Slog.v(TAG, 7260 "allDrawn: " + wtoken 7261 + " interesting=" + numInteresting 7262 + " drawn=" + wtoken.numDrawnWindows); 7263 wtoken.allDrawn = true; 7264 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 7265 7266 // We can now show all of the drawn windows! 7267 if (!mOpeningApps.contains(wtoken)) { 7268 wtoken.showAllWindowsLocked(); 7269 } 7270 } 7271 } 7272 } 7273 } 7274 7275 // If we are ready to perform an app transition, check through 7276 // all of the app tokens to be shown and see if they are ready 7277 // to go. 7278 if (mAppTransitionReady) { 7279 int NN = mOpeningApps.size(); 7280 boolean goodToGo = true; 7281 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7282 "Checking " + NN + " opening apps (frozen=" 7283 + mDisplayFrozen + " timeout=" 7284 + mAppTransitionTimeout + ")..."); 7285 if (!mDisplayFrozen && !mAppTransitionTimeout) { 7286 // If the display isn't frozen, wait to do anything until 7287 // all of the apps are ready. Otherwise just go because 7288 // we'll unfreeze the display when everyone is ready. 7289 for (i=0; i<NN && goodToGo; i++) { 7290 AppWindowToken wtoken = mOpeningApps.get(i); 7291 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7292 "Check opening app" + wtoken + ": allDrawn=" 7293 + wtoken.allDrawn + " startingDisplayed=" 7294 + wtoken.startingDisplayed); 7295 if (!wtoken.allDrawn && !wtoken.startingDisplayed 7296 && !wtoken.startingMoved) { 7297 goodToGo = false; 7298 } 7299 } 7300 } 7301 if (goodToGo) { 7302 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 7303 int transit = mNextAppTransition; 7304 if (mSkipAppTransitionAnimation) { 7305 transit = WindowManagerPolicy.TRANSIT_UNSET; 7306 } 7307 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 7308 mAppTransitionReady = false; 7309 mAppTransitionRunning = true; 7310 mAppTransitionTimeout = false; 7311 mStartingIconInTransition = false; 7312 mSkipAppTransitionAnimation = false; 7313 7314 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 7315 7316 // If there are applications waiting to come to the 7317 // top of the stack, now is the time to move their windows. 7318 // (Note that we don't do apps going to the bottom 7319 // here -- we want to keep their windows in the old 7320 // Z-order until the animation completes.) 7321 if (mToTopApps.size() > 0) { 7322 NN = mAppTokens.size(); 7323 for (i=0; i<NN; i++) { 7324 AppWindowToken wtoken = mAppTokens.get(i); 7325 if (wtoken.sendingToTop) { 7326 wtoken.sendingToTop = false; 7327 moveAppWindowsLocked(wtoken, NN, false); 7328 } 7329 } 7330 mToTopApps.clear(); 7331 } 7332 7333 WindowState oldWallpaper = mWallpaperTarget; 7334 7335 adjustWallpaperWindowsLocked(); 7336 wallpaperMayChange = false; 7337 7338 // The top-most window will supply the layout params, 7339 // and we will determine it below. 7340 LayoutParams animLp = null; 7341 int bestAnimLayer = -1; 7342 boolean fullscreenAnim = false; 7343 boolean needBgFiller = false; 7344 7345 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7346 "New wallpaper target=" + mWallpaperTarget 7347 + ", lower target=" + mLowerWallpaperTarget 7348 + ", upper target=" + mUpperWallpaperTarget); 7349 int foundWallpapers = 0; 7350 // Do a first pass through the tokens for two 7351 // things: 7352 // (1) Determine if both the closing and opening 7353 // app token sets are wallpaper targets, in which 7354 // case special animations are needed 7355 // (since the wallpaper needs to stay static 7356 // behind them). 7357 // (2) Find the layout params of the top-most 7358 // application window in the tokens, which is 7359 // what will control the animation theme. 7360 final int NC = mClosingApps.size(); 7361 NN = NC + mOpeningApps.size(); 7362 for (i=0; i<NN; i++) { 7363 AppWindowToken wtoken; 7364 int mode; 7365 if (i < NC) { 7366 wtoken = mClosingApps.get(i); 7367 mode = 1; 7368 } else { 7369 wtoken = mOpeningApps.get(i-NC); 7370 mode = 2; 7371 } 7372 if (mLowerWallpaperTarget != null) { 7373 if (mLowerWallpaperTarget.mAppToken == wtoken 7374 || mUpperWallpaperTarget.mAppToken == wtoken) { 7375 foundWallpapers |= mode; 7376 } 7377 } 7378 if (wtoken.appFullscreen) { 7379 WindowState ws = wtoken.findMainWindow(); 7380 if (ws != null) { 7381 // If this is a compatibility mode 7382 // window, we will always use its anim. 7383 if (ws.mNeedsBackgroundFiller) { 7384 animLp = ws.mAttrs; 7385 bestAnimLayer = Integer.MAX_VALUE; 7386 needBgFiller = true; 7387 } else if (!fullscreenAnim || ws.mLayer > bestAnimLayer) { 7388 animLp = ws.mAttrs; 7389 bestAnimLayer = ws.mLayer; 7390 } 7391 fullscreenAnim = true; 7392 } 7393 } else if (!fullscreenAnim) { 7394 WindowState ws = wtoken.findMainWindow(); 7395 if (ws != null) { 7396 if (ws.mLayer > bestAnimLayer) { 7397 animLp = ws.mAttrs; 7398 bestAnimLayer = ws.mLayer; 7399 } 7400 } 7401 } 7402 } 7403 7404 if (foundWallpapers == 3) { 7405 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7406 "Wallpaper animation!"); 7407 switch (transit) { 7408 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: 7409 case WindowManagerPolicy.TRANSIT_TASK_OPEN: 7410 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: 7411 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN; 7412 break; 7413 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: 7414 case WindowManagerPolicy.TRANSIT_TASK_CLOSE: 7415 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: 7416 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE; 7417 break; 7418 } 7419 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7420 "New transit: " + transit); 7421 } else if (oldWallpaper != null) { 7422 // We are transitioning from an activity with 7423 // a wallpaper to one without. 7424 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE; 7425 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7426 "New transit away from wallpaper: " + transit); 7427 } else if (mWallpaperTarget != null) { 7428 // We are transitioning from an activity without 7429 // a wallpaper to now showing the wallpaper 7430 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN; 7431 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7432 "New transit into wallpaper: " + transit); 7433 } 7434 7435 // If all closing windows are obscured, then there is 7436 // no need to do an animation. This is the case, for 7437 // example, when this transition is being done behind 7438 // the lock screen. 7439 if (!mPolicy.allowAppAnimationsLw()) { 7440 animLp = null; 7441 } 7442 7443 NN = mOpeningApps.size(); 7444 for (i=0; i<NN; i++) { 7445 AppWindowToken wtoken = mOpeningApps.get(i); 7446 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7447 "Now opening app" + wtoken); 7448 wtoken.reportedVisible = false; 7449 wtoken.inPendingTransaction = false; 7450 wtoken.animation = null; 7451 setTokenVisibilityLocked(wtoken, animLp, true, 7452 transit, false, needBgFiller); 7453 wtoken.updateReportedVisibilityLocked(); 7454 wtoken.waitingToShow = false; 7455 wtoken.showAllWindowsLocked(); 7456 } 7457 NN = mClosingApps.size(); 7458 for (i=0; i<NN; i++) { 7459 AppWindowToken wtoken = mClosingApps.get(i); 7460 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7461 "Now closing app" + wtoken); 7462 wtoken.inPendingTransaction = false; 7463 wtoken.animation = null; 7464 setTokenVisibilityLocked(wtoken, animLp, false, 7465 transit, false, needBgFiller); 7466 wtoken.updateReportedVisibilityLocked(); 7467 wtoken.waitingToHide = false; 7468 // Force the allDrawn flag, because we want to start 7469 // this guy's animations regardless of whether it's 7470 // gotten drawn. 7471 wtoken.allDrawn = true; 7472 } 7473 7474 mNextAppTransitionPackage = null; 7475 7476 mOpeningApps.clear(); 7477 mClosingApps.clear(); 7478 7479 // This has changed the visibility of windows, so perform 7480 // a new layout to get them all up-to-date. 7481 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT 7482 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 7483 mLayoutNeeded = true; 7484 if (!moveInputMethodWindowsIfNeededLocked(true)) { 7485 assignLayersLocked(); 7486 } 7487 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 7488 false /*updateInputWindows*/); 7489 mFocusMayChange = false; 7490 } 7491 } 7492 7493 int adjResult = 0; 7494 7495 if (!animating && mAppTransitionRunning) { 7496 // We have finished the animation of an app transition. To do 7497 // this, we have delayed a lot of operations like showing and 7498 // hiding apps, moving apps in Z-order, etc. The app token list 7499 // reflects the correct Z-order, but the window list may now 7500 // be out of sync with it. So here we will just rebuild the 7501 // entire app window list. Fun! 7502 mAppTransitionRunning = false; 7503 // Clear information about apps that were moving. 7504 mToBottomApps.clear(); 7505 7506 rebuildAppWindowListLocked(); 7507 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 7508 adjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED; 7509 moveInputMethodWindowsIfNeededLocked(false); 7510 wallpaperMayChange = true; 7511 // Since the window list has been rebuilt, focus might 7512 // have to be recomputed since the actual order of windows 7513 // might have changed again. 7514 mFocusMayChange = true; 7515 } 7516 7517 if (wallpaperForceHidingChanged && changes == 0 && !mAppTransitionReady) { 7518 // At this point, there was a window with a wallpaper that 7519 // was force hiding other windows behind it, but now it 7520 // is going away. This may be simple -- just animate 7521 // away the wallpaper and its window -- or it may be 7522 // hard -- the wallpaper now needs to be shown behind 7523 // something that was hidden. 7524 WindowState oldWallpaper = mWallpaperTarget; 7525 if (mLowerWallpaperTarget != null 7526 && mLowerWallpaperTarget.mAppToken != null) { 7527 if (DEBUG_WALLPAPER) Slog.v(TAG, 7528 "wallpaperForceHiding changed with lower=" 7529 + mLowerWallpaperTarget); 7530 if (DEBUG_WALLPAPER) Slog.v(TAG, 7531 "hidden=" + mLowerWallpaperTarget.mAppToken.hidden + 7532 " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested); 7533 if (mLowerWallpaperTarget.mAppToken.hidden) { 7534 // The lower target has become hidden before we 7535 // actually started the animation... let's completely 7536 // re-evaluate everything. 7537 mLowerWallpaperTarget = mUpperWallpaperTarget = null; 7538 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 7539 } 7540 } 7541 adjResult |= adjustWallpaperWindowsLocked(); 7542 wallpaperMayChange = false; 7543 wallpaperForceHidingChanged = false; 7544 if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper 7545 + " NEW: " + mWallpaperTarget 7546 + " LOWER: " + mLowerWallpaperTarget); 7547 if (mLowerWallpaperTarget == null) { 7548 // Whoops, we don't need a special wallpaper animation. 7549 // Clear them out. 7550 forceHiding = false; 7551 for (i=N-1; i>=0; i--) { 7552 WindowState w = mWindows.get(i); 7553 if (w.mSurface != null) { 7554 final WindowManager.LayoutParams attrs = w.mAttrs; 7555 if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) { 7556 if (DEBUG_FOCUS) Slog.i(TAG, "win=" + w + " force hides other windows"); 7557 forceHiding = true; 7558 } else if (mPolicy.canBeForceHidden(w, attrs)) { 7559 if (!w.mAnimating) { 7560 // We set the animation above so it 7561 // is not yet running. 7562 w.clearAnimation(); 7563 } 7564 } 7565 } 7566 } 7567 } 7568 } 7569 7570 if (mWindowDetachedWallpaper != windowDetachedWallpaper) { 7571 if (DEBUG_WALLPAPER) Slog.v(TAG, 7572 "Detached wallpaper changed from " + mWindowDetachedWallpaper 7573 + windowDetachedWallpaper); 7574 mWindowDetachedWallpaper = windowDetachedWallpaper; 7575 wallpaperMayChange = true; 7576 } 7577 7578 if (windowAnimationBackgroundColor != 0) { 7579 if (mWindowAnimationBackgroundSurface == null) { 7580 mWindowAnimationBackgroundSurface = new DimSurface(mFxSession); 7581 } 7582 mWindowAnimationBackgroundSurface.show(dw, dh, 7583 windowAnimationBackground.mAnimLayer - LAYER_OFFSET_DIM, 7584 windowAnimationBackgroundColor); 7585 } else if (mWindowAnimationBackgroundSurface != null) { 7586 mWindowAnimationBackgroundSurface.hide(); 7587 } 7588 7589 if (wallpaperMayChange) { 7590 if (DEBUG_WALLPAPER) Slog.v(TAG, 7591 "Wallpaper may change! Adjusting"); 7592 adjResult |= adjustWallpaperWindowsLocked(); 7593 } 7594 7595 if ((adjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 7596 if (DEBUG_WALLPAPER) Slog.v(TAG, 7597 "Wallpaper layer changed: assigning layers + relayout"); 7598 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 7599 assignLayersLocked(); 7600 } else if ((adjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) { 7601 if (DEBUG_WALLPAPER) Slog.v(TAG, 7602 "Wallpaper visibility changed: relayout"); 7603 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 7604 } 7605 7606 if (mFocusMayChange) { 7607 mFocusMayChange = false; 7608 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 7609 false /*updateInputWindows*/)) { 7610 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 7611 adjResult = 0; 7612 } 7613 } 7614 7615 if (mLayoutNeeded) { 7616 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 7617 } 7618 7619 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x" 7620 + Integer.toHexString(changes)); 7621 } while (changes != 0); 7622 7623 // THIRD LOOP: Update the surfaces of all windows. 7624 7625 final boolean someoneLosingFocus = mLosingFocus.size() != 0; 7626 7627 boolean obscured = false; 7628 boolean blurring = false; 7629 boolean dimming = false; 7630 boolean covered = false; 7631 boolean syswin = false; 7632 boolean backgroundFillerWasShown = mBackgroundFillerTarget != null; 7633 mBackgroundFillerTarget = null; 7634 7635 final int N = mWindows.size(); 7636 7637 for (i=N-1; i>=0; i--) { 7638 WindowState w = mWindows.get(i); 7639 7640 boolean displayed = false; 7641 final WindowManager.LayoutParams attrs = w.mAttrs; 7642 final int attrFlags = attrs.flags; 7643 7644 if (w.mSurface != null) { 7645 // XXX NOTE: The logic here could be improved. We have 7646 // the decision about whether to resize a window separated 7647 // from whether to hide the surface. This can cause us to 7648 // resize a surface even if we are going to hide it. You 7649 // can see this by (1) holding device in landscape mode on 7650 // home screen; (2) tapping browser icon (device will rotate 7651 // to landscape; (3) tap home. The wallpaper will be resized 7652 // in step 2 but then immediately hidden, causing us to 7653 // have to resize and then redraw it again in step 3. It 7654 // would be nice to figure out how to avoid this, but it is 7655 // difficult because we do need to resize surfaces in some 7656 // cases while they are hidden such as when first showing a 7657 // window. 7658 7659 w.computeShownFrameLocked(); 7660 if (localLOGV) Slog.v( 7661 TAG, "Placing surface #" + i + " " + w.mSurface 7662 + ": new=" + w.mShownFrame + ", old=" 7663 + w.mLastShownFrame); 7664 7665 int width, height; 7666 if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) { 7667 // for a scaled surface, we just want to use 7668 // the requested size. 7669 width = w.mRequestedWidth; 7670 height = w.mRequestedHeight; 7671 w.mLastRequestedWidth = width; 7672 w.mLastRequestedHeight = height; 7673 w.mLastShownFrame.set(w.mShownFrame); 7674 } else { 7675 width = w.mShownFrame.width(); 7676 height = w.mShownFrame.height(); 7677 w.mLastShownFrame.set(w.mShownFrame); 7678 } 7679 7680 if (w.mSurface != null) { 7681 if (w.mSurfaceX != w.mShownFrame.left 7682 || w.mSurfaceY != w.mShownFrame.top) { 7683 try { 7684 if (SHOW_TRANSACTIONS) logSurface(w, 7685 "POS " + w.mShownFrame.left 7686 + ", " + w.mShownFrame.top, null); 7687 w.mSurfaceX = w.mShownFrame.left; 7688 w.mSurfaceY = w.mShownFrame.top; 7689 w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top); 7690 } catch (RuntimeException e) { 7691 Slog.w(TAG, "Error positioning surface of " + w 7692 + " pos=(" + w.mShownFrame.left 7693 + "," + w.mShownFrame.top + ")", e); 7694 if (!recoveringMemory) { 7695 reclaimSomeSurfaceMemoryLocked(w, "position", true); 7696 } 7697 } 7698 } 7699 7700 if (width < 1) { 7701 width = 1; 7702 } 7703 if (height < 1) { 7704 height = 1; 7705 } 7706 7707 if (w.mSurfaceW != width || w.mSurfaceH != height) { 7708 try { 7709 if (SHOW_TRANSACTIONS) logSurface(w, 7710 "SIZE " + w.mShownFrame.width() + "x" 7711 + w.mShownFrame.height(), null); 7712 w.mSurfaceResized = true; 7713 w.mSurfaceW = width; 7714 w.mSurfaceH = height; 7715 w.mSurface.setSize(width, height); 7716 } catch (RuntimeException e) { 7717 // If something goes wrong with the surface (such 7718 // as running out of memory), don't take down the 7719 // entire system. 7720 Slog.e(TAG, "Error resizing surface of " + w 7721 + " size=(" + width + "x" + height + ")", e); 7722 if (!recoveringMemory) { 7723 reclaimSomeSurfaceMemoryLocked(w, "size", true); 7724 } 7725 } 7726 } 7727 } 7728 7729 if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) { 7730 w.mContentInsetsChanged = 7731 !w.mLastContentInsets.equals(w.mContentInsets); 7732 w.mVisibleInsetsChanged = 7733 !w.mLastVisibleInsets.equals(w.mVisibleInsets); 7734 boolean configChanged = 7735 w.mConfiguration != mCurConfiguration 7736 && (w.mConfiguration == null 7737 || mCurConfiguration.diff(w.mConfiguration) != 0); 7738 if (DEBUG_CONFIGURATION && configChanged) { 7739 Slog.v(TAG, "Win " + w + " config changed: " 7740 + mCurConfiguration); 7741 } 7742 if (localLOGV) Slog.v(TAG, "Resizing " + w 7743 + ": configChanged=" + configChanged 7744 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 7745 boolean frameChanged = !w.mLastFrame.equals(w.mFrame); 7746 if (frameChanged 7747 || w.mContentInsetsChanged 7748 || w.mVisibleInsetsChanged 7749 || w.mSurfaceResized 7750 || configChanged) { 7751 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 7752 Slog.v(TAG, "Resize reasons: " 7753 + "frameChanged=" + frameChanged 7754 + " contentInsetsChanged=" + w.mContentInsetsChanged 7755 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 7756 + " surfaceResized=" + w.mSurfaceResized 7757 + " configChanged=" + configChanged); 7758 } 7759 7760 w.mLastFrame.set(w.mFrame); 7761 w.mLastContentInsets.set(w.mContentInsets); 7762 w.mLastVisibleInsets.set(w.mVisibleInsets); 7763 // If the screen is currently frozen, then keep 7764 // it frozen until this window draws at its new 7765 // orientation. 7766 if (mDisplayFrozen) { 7767 if (DEBUG_ORIENTATION) Slog.v(TAG, 7768 "Resizing while display frozen: " + w); 7769 w.mOrientationChanging = true; 7770 if (!mWindowsFreezingScreen) { 7771 mWindowsFreezingScreen = true; 7772 // XXX should probably keep timeout from 7773 // when we first froze the display. 7774 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 7775 mH.sendMessageDelayed(mH.obtainMessage( 7776 H.WINDOW_FREEZE_TIMEOUT), 2000); 7777 } 7778 } 7779 // If the orientation is changing, then we need to 7780 // hold off on unfreezing the display until this 7781 // window has been redrawn; to do that, we need 7782 // to go through the process of getting informed 7783 // by the application when it has finished drawing. 7784 if (w.mOrientationChanging) { 7785 if (DEBUG_ORIENTATION) Slog.v(TAG, 7786 "Orientation start waiting for draw in " 7787 + w + ", surface " + w.mSurface); 7788 w.mDrawPending = true; 7789 w.mCommitDrawPending = false; 7790 w.mReadyToShow = false; 7791 if (w.mAppToken != null) { 7792 w.mAppToken.allDrawn = false; 7793 } 7794 } 7795 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 7796 "Resizing window " + w + " to " + w.mFrame); 7797 mResizingWindows.add(w); 7798 } else if (w.mOrientationChanging) { 7799 if (!w.mDrawPending && !w.mCommitDrawPending) { 7800 if (DEBUG_ORIENTATION) Slog.v(TAG, 7801 "Orientation not waiting for draw in " 7802 + w + ", surface " + w.mSurface); 7803 w.mOrientationChanging = false; 7804 } 7805 } 7806 } 7807 7808 if (w.mAttachedHidden || !w.isReadyForDisplay()) { 7809 if (!w.mLastHidden) { 7810 //dump(); 7811 w.mLastHidden = true; 7812 if (SHOW_TRANSACTIONS) logSurface(w, 7813 "HIDE (performLayout)", null); 7814 if (w.mSurface != null) { 7815 w.mSurfaceShown = false; 7816 try { 7817 w.mSurface.hide(); 7818 } catch (RuntimeException e) { 7819 Slog.w(TAG, "Exception hiding surface in " + w); 7820 } 7821 } 7822 } 7823 // If we are waiting for this window to handle an 7824 // orientation change, well, it is hidden, so 7825 // doesn't really matter. Note that this does 7826 // introduce a potential glitch if the window 7827 // becomes unhidden before it has drawn for the 7828 // new orientation. 7829 if (w.mOrientationChanging) { 7830 w.mOrientationChanging = false; 7831 if (DEBUG_ORIENTATION) Slog.v(TAG, 7832 "Orientation change skips hidden " + w); 7833 } 7834 } else if (w.mLastLayer != w.mAnimLayer 7835 || w.mLastAlpha != w.mShownAlpha 7836 || w.mLastDsDx != w.mDsDx 7837 || w.mLastDtDx != w.mDtDx 7838 || w.mLastDsDy != w.mDsDy 7839 || w.mLastDtDy != w.mDtDy 7840 || w.mLastHScale != w.mHScale 7841 || w.mLastVScale != w.mVScale 7842 || w.mLastHidden) { 7843 displayed = true; 7844 w.mLastAlpha = w.mShownAlpha; 7845 w.mLastLayer = w.mAnimLayer; 7846 w.mLastDsDx = w.mDsDx; 7847 w.mLastDtDx = w.mDtDx; 7848 w.mLastDsDy = w.mDsDy; 7849 w.mLastDtDy = w.mDtDy; 7850 w.mLastHScale = w.mHScale; 7851 w.mLastVScale = w.mVScale; 7852 if (SHOW_TRANSACTIONS) logSurface(w, 7853 "alpha=" + w.mShownAlpha + " layer=" + w.mAnimLayer 7854 + " matrix=[" + (w.mDsDx*w.mHScale) 7855 + "," + (w.mDtDx*w.mVScale) 7856 + "][" + (w.mDsDy*w.mHScale) 7857 + "," + (w.mDtDy*w.mVScale) + "]", null); 7858 if (w.mSurface != null) { 7859 try { 7860 w.mSurfaceAlpha = w.mShownAlpha; 7861 w.mSurface.setAlpha(w.mShownAlpha); 7862 w.mSurfaceLayer = w.mAnimLayer; 7863 w.mSurface.setLayer(w.mAnimLayer); 7864 w.mSurface.setMatrix( 7865 w.mDsDx*w.mHScale, w.mDtDx*w.mVScale, 7866 w.mDsDy*w.mHScale, w.mDtDy*w.mVScale); 7867 } catch (RuntimeException e) { 7868 Slog.w(TAG, "Error updating surface in " + w, e); 7869 if (!recoveringMemory) { 7870 reclaimSomeSurfaceMemoryLocked(w, "update", true); 7871 } 7872 } 7873 } 7874 7875 if (w.mLastHidden && !w.mDrawPending 7876 && !w.mCommitDrawPending 7877 && !w.mReadyToShow) { 7878 if (SHOW_TRANSACTIONS) logSurface(w, 7879 "SHOW (performLayout)", null); 7880 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w 7881 + " during relayout"); 7882 if (showSurfaceRobustlyLocked(w)) { 7883 w.mHasDrawn = true; 7884 w.mLastHidden = false; 7885 } else { 7886 w.mOrientationChanging = false; 7887 } 7888 } 7889 if (w.mSurface != null) { 7890 w.mToken.hasVisible = true; 7891 } 7892 } else { 7893 displayed = true; 7894 } 7895 7896 if (displayed) { 7897 if (!covered) { 7898 if (attrs.width == LayoutParams.MATCH_PARENT 7899 && attrs.height == LayoutParams.MATCH_PARENT) { 7900 covered = true; 7901 } 7902 } 7903 if (w.mOrientationChanging) { 7904 if (w.mDrawPending || w.mCommitDrawPending) { 7905 orientationChangeComplete = false; 7906 if (DEBUG_ORIENTATION) Slog.v(TAG, 7907 "Orientation continue waiting for draw in " + w); 7908 } else { 7909 w.mOrientationChanging = false; 7910 if (DEBUG_ORIENTATION) Slog.v(TAG, 7911 "Orientation change complete in " + w); 7912 } 7913 } 7914 w.mToken.hasVisible = true; 7915 } 7916 } else if (w.mOrientationChanging) { 7917 if (DEBUG_ORIENTATION) Slog.v(TAG, 7918 "Orientation change skips hidden " + w); 7919 w.mOrientationChanging = false; 7920 } 7921 7922 if (w.mContentChanged) { 7923 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 7924 w.mContentChanged = false; 7925 } 7926 7927 final boolean canBeSeen = w.isDisplayedLw(); 7928 7929 if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) { 7930 focusDisplayed = true; 7931 } 7932 7933 final boolean obscuredChanged = w.mObscured != obscured; 7934 7935 if (mBackgroundFillerTarget != null) { 7936 if (w.isAnimating()) { 7937 // Background filler is below all other windows that 7938 // are animating. 7939 mBackgroundFillerTarget = w; 7940 } else if (w.mIsWallpaper) { 7941 mBackgroundFillerTarget = w; 7942 } 7943 } 7944 7945 // Update effect. 7946 if (!(w.mObscured=obscured)) { 7947 if (w.mSurface != null) { 7948 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 7949 holdScreen = w.mSession; 7950 } 7951 if (!syswin && w.mAttrs.screenBrightness >= 0 7952 && screenBrightness < 0) { 7953 screenBrightness = w.mAttrs.screenBrightness; 7954 } 7955 if (!syswin && w.mAttrs.buttonBrightness >= 0 7956 && buttonBrightness < 0) { 7957 buttonBrightness = w.mAttrs.buttonBrightness; 7958 } 7959 if (canBeSeen 7960 && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG 7961 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD 7962 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) { 7963 syswin = true; 7964 } 7965 } 7966 7967 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 7968 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 7969 // This window completely covers everything behind it, 7970 // so we want to leave all of them as unblurred (for 7971 // performance reasons). 7972 obscured = true; 7973 } else if (w.mNeedsBackgroundFiller && w.mHasDrawn 7974 && w.mViewVisibility == View.VISIBLE 7975 && (canBeSeen || w.isAnimating())) { 7976 // This window is in compatibility mode, and needs background filler. 7977 obscured = true; 7978 mBackgroundFillerTarget = w; 7979 } else if (canBeSeen && !obscured && 7980 (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) { 7981 if (localLOGV) Slog.v(TAG, "Win " + w 7982 + ": blurring=" + blurring 7983 + " obscured=" + obscured 7984 + " displayed=" + displayed); 7985 if ((attrFlags&FLAG_DIM_BEHIND) != 0) { 7986 if (!dimming) { 7987 //Slog.i(TAG, "DIM BEHIND: " + w); 7988 dimming = true; 7989 if (mDimAnimator == null) { 7990 mDimAnimator = new DimAnimator(mFxSession); 7991 } 7992 mDimAnimator.show(dw, dh); 7993 mDimAnimator.updateParameters(mContext.getResources(), 7994 w, currentTime); 7995 } 7996 } 7997 if ((attrFlags&FLAG_BLUR_BEHIND) != 0) { 7998 if (!blurring) { 7999 //Slog.i(TAG, "BLUR BEHIND: " + w); 8000 blurring = true; 8001 if (mBlurSurface == null) { 8002 try { 8003 mBlurSurface = new Surface(mFxSession, 0, 8004 "BlurSurface", 8005 -1, 16, 16, 8006 PixelFormat.OPAQUE, 8007 Surface.FX_SURFACE_BLUR); 8008 } catch (Exception e) { 8009 Slog.e(TAG, "Exception creating Blur surface", e); 8010 } 8011 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " 8012 + mBlurSurface + ": CREATE"); 8013 } 8014 if (mBlurSurface != null) { 8015 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " 8016 + mBlurSurface + ": pos=(0,0) (" + 8017 dw + "x" + dh + "), layer=" + (w.mAnimLayer-1)); 8018 mBlurSurface.setPosition(0, 0); 8019 mBlurSurface.setSize(dw, dh); 8020 mBlurSurface.setLayer(w.mAnimLayer-LAYER_OFFSET_BLUR); 8021 if (!mBlurShown) { 8022 try { 8023 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " 8024 + mBlurSurface + ": SHOW"); 8025 mBlurSurface.show(); 8026 } catch (RuntimeException e) { 8027 Slog.w(TAG, "Failure showing blur surface", e); 8028 } 8029 mBlurShown = true; 8030 } 8031 } 8032 } 8033 } 8034 } 8035 } 8036 8037 if (obscuredChanged && mWallpaperTarget == w) { 8038 // This is the wallpaper target and its obscured state 8039 // changed... make sure the current wallaper's visibility 8040 // has been updated accordingly. 8041 updateWallpaperVisibilityLocked(); 8042 } 8043 } 8044 8045 if (mBackgroundFillerTarget != null) { 8046 if (mBackgroundFillerSurface == null) { 8047 try { 8048 mBackgroundFillerSurface = new Surface(mFxSession, 0, 8049 "BackGroundFiller", 8050 0, dw, dh, 8051 PixelFormat.OPAQUE, 8052 Surface.FX_SURFACE_NORMAL); 8053 } catch (Exception e) { 8054 Slog.e(TAG, "Exception creating filler surface", e); 8055 } 8056 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BG FILLER " 8057 + mBackgroundFillerSurface + ": CREATE"); 8058 } 8059 try { 8060 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BG FILLER " 8061 + mBackgroundFillerSurface + " SHOW: pos=(0,0) (" 8062 + dw + "x" + dh + ") layer=" 8063 + (mBackgroundFillerTarget.mLayer - 1)); 8064 mBackgroundFillerSurface.setPosition(0, 0); 8065 mBackgroundFillerSurface.setSize(dw, dh); 8066 // Using the same layer as Dim because they will never be shown at the 8067 // same time. NOTE: we do NOT use mAnimLayer, because we don't 8068 // want this surface dragged up in front of stuff that is animating. 8069 mBackgroundFillerSurface.setLayer(mBackgroundFillerTarget.mLayer 8070 - LAYER_OFFSET_DIM); 8071 mBackgroundFillerSurface.show(); 8072 } catch (RuntimeException e) { 8073 Slog.e(TAG, "Exception showing filler surface"); 8074 } 8075 } else if (backgroundFillerWasShown) { 8076 mBackgroundFillerTarget = null; 8077 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BG FILLER " 8078 + mBackgroundFillerSurface + " HIDE"); 8079 try { 8080 mBackgroundFillerSurface.hide(); 8081 } catch (RuntimeException e) { 8082 Slog.e(TAG, "Exception hiding filler surface", e); 8083 } 8084 } 8085 8086 if (mDimAnimator != null && mDimAnimator.mDimShown) { 8087 animating |= mDimAnimator.updateSurface(dimming, currentTime, 8088 mDisplayFrozen || !mPolicy.isScreenOn()); 8089 } 8090 8091 if (!blurring && mBlurShown) { 8092 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " + mBlurSurface 8093 + ": HIDE"); 8094 try { 8095 mBlurSurface.hide(); 8096 } catch (IllegalArgumentException e) { 8097 Slog.w(TAG, "Illegal argument exception hiding blur surface"); 8098 } 8099 mBlurShown = false; 8100 } 8101 8102 if (mBlackFrame != null) { 8103 if (mScreenRotationAnimation != null) { 8104 mBlackFrame.setMatrix( 8105 mScreenRotationAnimation.getEnterTransformation().getMatrix()); 8106 } else { 8107 mBlackFrame.clearMatrix(); 8108 } 8109 } 8110 } catch (RuntimeException e) { 8111 Slog.e(TAG, "Unhandled exception in Window Manager", e); 8112 } 8113 8114 Surface.closeTransaction(); 8115 8116 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 8117 8118 if (mWatermark != null) { 8119 mWatermark.drawIfNeeded(); 8120 } 8121 8122 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 8123 "With display frozen, orientationChangeComplete=" 8124 + orientationChangeComplete); 8125 if (orientationChangeComplete) { 8126 if (mWindowsFreezingScreen) { 8127 mWindowsFreezingScreen = false; 8128 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8129 } 8130 stopFreezingDisplayLocked(); 8131 } 8132 8133 i = mResizingWindows.size(); 8134 if (i > 0) { 8135 do { 8136 i--; 8137 WindowState win = mResizingWindows.get(i); 8138 try { 8139 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8140 "Reporting new frame to " + win + ": " + win.mFrame); 8141 int diff = 0; 8142 boolean configChanged = 8143 win.mConfiguration != mCurConfiguration 8144 && (win.mConfiguration == null 8145 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0); 8146 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) 8147 && configChanged) { 8148 Slog.i(TAG, "Sending new config to window " + win + ": " 8149 + win.mFrame.width() + "x" + win.mFrame.height() 8150 + " / " + mCurConfiguration + " / 0x" 8151 + Integer.toHexString(diff)); 8152 } 8153 win.mConfiguration = mCurConfiguration; 8154 win.mClient.resized(win.mFrame.width(), 8155 win.mFrame.height(), win.mLastContentInsets, 8156 win.mLastVisibleInsets, win.mDrawPending, 8157 configChanged ? win.mConfiguration : null); 8158 win.mContentInsetsChanged = false; 8159 win.mVisibleInsetsChanged = false; 8160 win.mSurfaceResized = false; 8161 } catch (RemoteException e) { 8162 win.mOrientationChanging = false; 8163 } 8164 } while (i > 0); 8165 mResizingWindows.clear(); 8166 } 8167 8168 // Destroy the surface of any windows that are no longer visible. 8169 boolean wallpaperDestroyed = false; 8170 i = mDestroySurface.size(); 8171 if (i > 0) { 8172 do { 8173 i--; 8174 WindowState win = mDestroySurface.get(i); 8175 win.mDestroying = false; 8176 if (mInputMethodWindow == win) { 8177 mInputMethodWindow = null; 8178 } 8179 if (win == mWallpaperTarget) { 8180 wallpaperDestroyed = true; 8181 } 8182 win.destroySurfaceLocked(); 8183 } while (i > 0); 8184 mDestroySurface.clear(); 8185 } 8186 8187 // Time to remove any exiting tokens? 8188 for (i=mExitingTokens.size()-1; i>=0; i--) { 8189 WindowToken token = mExitingTokens.get(i); 8190 if (!token.hasVisible) { 8191 mExitingTokens.remove(i); 8192 if (token.windowType == TYPE_WALLPAPER) { 8193 mWallpaperTokens.remove(token); 8194 } 8195 } 8196 } 8197 8198 // Time to remove any exiting applications? 8199 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 8200 AppWindowToken token = mExitingAppTokens.get(i); 8201 if (!token.hasVisible && !mClosingApps.contains(token)) { 8202 // Make sure there is no animation running on this token, 8203 // so any windows associated with it will be removed as 8204 // soon as their animations are complete 8205 token.animation = null; 8206 token.animating = false; 8207 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 8208 "performLayout: App token exiting now removed" + token); 8209 mAppTokens.remove(token); 8210 mExitingAppTokens.remove(i); 8211 } 8212 } 8213 8214 boolean needRelayout = false; 8215 8216 if (!animating && mAppTransitionRunning) { 8217 // We have finished the animation of an app transition. To do 8218 // this, we have delayed a lot of operations like showing and 8219 // hiding apps, moving apps in Z-order, etc. The app token list 8220 // reflects the correct Z-order, but the window list may now 8221 // be out of sync with it. So here we will just rebuild the 8222 // entire app window list. Fun! 8223 mAppTransitionRunning = false; 8224 needRelayout = true; 8225 rebuildAppWindowListLocked(); 8226 assignLayersLocked(); 8227 // Clear information about apps that were moving. 8228 mToBottomApps.clear(); 8229 } 8230 8231 if (focusDisplayed) { 8232 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 8233 } 8234 if (wallpaperDestroyed) { 8235 needRelayout = adjustWallpaperWindowsLocked() != 0; 8236 } 8237 if (needRelayout) { 8238 requestAnimationLocked(0); 8239 } else if (animating) { 8240 requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis()); 8241 } 8242 8243 // Finally update all input windows now that the window changes have stabilized. 8244 mInputMonitor.updateInputWindowsLw(true /*force*/); 8245 8246 setHoldScreenLocked(holdScreen != null); 8247 if (!mDisplayFrozen) { 8248 if (screenBrightness < 0 || screenBrightness > 1.0f) { 8249 mPowerManager.setScreenBrightnessOverride(-1); 8250 } else { 8251 mPowerManager.setScreenBrightnessOverride((int) 8252 (screenBrightness * Power.BRIGHTNESS_ON)); 8253 } 8254 if (buttonBrightness < 0 || buttonBrightness > 1.0f) { 8255 mPowerManager.setButtonBrightnessOverride(-1); 8256 } else { 8257 mPowerManager.setButtonBrightnessOverride((int) 8258 (buttonBrightness * Power.BRIGHTNESS_ON)); 8259 } 8260 } 8261 if (holdScreen != mHoldingScreenOn) { 8262 mHoldingScreenOn = holdScreen; 8263 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen); 8264 mH.sendMessage(m); 8265 } 8266 8267 if (mTurnOnScreen) { 8268 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 8269 mPowerManager.userActivity(SystemClock.uptimeMillis(), false, 8270 LocalPowerManager.BUTTON_EVENT, true); 8271 mTurnOnScreen = false; 8272 } 8273 8274 if (screenRotationFinished && mScreenRotationAnimation != null) { 8275 mScreenRotationAnimation.kill(); 8276 mScreenRotationAnimation = null; 8277 } 8278 8279 if (updateRotation) { 8280 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 8281 boolean changed = setRotationUncheckedLocked( 8282 WindowManagerPolicy.USE_LAST_ROTATION, 0, false); 8283 if (changed) { 8284 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8285 } 8286 } 8287 8288 // Check to see if we are now in a state where the screen should 8289 // be enabled, because the window obscured flags have changed. 8290 enableScreenIfNeededLocked(); 8291 } 8292 8293 /** 8294 * Must be called with the main window manager lock held. 8295 */ 8296 void setHoldScreenLocked(boolean holding) { 8297 boolean state = mHoldingScreenWakeLock.isHeld(); 8298 if (holding != state) { 8299 if (holding) { 8300 mHoldingScreenWakeLock.acquire(); 8301 } else { 8302 mPolicy.screenOnStoppedLw(); 8303 mHoldingScreenWakeLock.release(); 8304 } 8305 } 8306 } 8307 8308 void requestAnimationLocked(long delay) { 8309 if (!mAnimationPending) { 8310 mAnimationPending = true; 8311 mH.sendMessageDelayed(mH.obtainMessage(H.ANIMATE), delay); 8312 } 8313 } 8314 8315 /** 8316 * Have the surface flinger show a surface, robustly dealing with 8317 * error conditions. In particular, if there is not enough memory 8318 * to show the surface, then we will try to get rid of other surfaces 8319 * in order to succeed. 8320 * 8321 * @return Returns true if the surface was successfully shown. 8322 */ 8323 boolean showSurfaceRobustlyLocked(WindowState win) { 8324 try { 8325 if (win.mSurface != null) { 8326 win.mSurfaceShown = true; 8327 win.mSurface.show(); 8328 if (win.mTurnOnScreen) { 8329 if (DEBUG_VISIBILITY) Slog.v(TAG, 8330 "Show surface turning screen on: " + win); 8331 win.mTurnOnScreen = false; 8332 mTurnOnScreen = true; 8333 } 8334 } 8335 return true; 8336 } catch (RuntimeException e) { 8337 Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win, e); 8338 } 8339 8340 reclaimSomeSurfaceMemoryLocked(win, "show", true); 8341 8342 return false; 8343 } 8344 8345 boolean reclaimSomeSurfaceMemoryLocked(WindowState win, String operation, boolean secure) { 8346 final Surface surface = win.mSurface; 8347 boolean leakedSurface = false; 8348 boolean killedApps = false; 8349 8350 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, win.toString(), 8351 win.mSession.mPid, operation); 8352 8353 if (mForceRemoves == null) { 8354 mForceRemoves = new ArrayList<WindowState>(); 8355 } 8356 8357 long callingIdentity = Binder.clearCallingIdentity(); 8358 try { 8359 // There was some problem... first, do a sanity check of the 8360 // window list to make sure we haven't left any dangling surfaces 8361 // around. 8362 int N = mWindows.size(); 8363 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 8364 for (int i=0; i<N; i++) { 8365 WindowState ws = mWindows.get(i); 8366 if (ws.mSurface != null) { 8367 if (!mSessions.contains(ws.mSession)) { 8368 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 8369 + ws + " surface=" + ws.mSurface 8370 + " token=" + win.mToken 8371 + " pid=" + ws.mSession.mPid 8372 + " uid=" + ws.mSession.mUid); 8373 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 8374 ws.mSurface.destroy(); 8375 ws.mSurfaceShown = false; 8376 ws.mSurface = null; 8377 mForceRemoves.add(ws); 8378 i--; 8379 N--; 8380 leakedSurface = true; 8381 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 8382 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 8383 + ws + " surface=" + ws.mSurface 8384 + " token=" + win.mAppToken); 8385 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 8386 ws.mSurface.destroy(); 8387 ws.mSurfaceShown = false; 8388 ws.mSurface = null; 8389 leakedSurface = true; 8390 } 8391 } 8392 } 8393 8394 if (!leakedSurface) { 8395 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 8396 SparseIntArray pidCandidates = new SparseIntArray(); 8397 for (int i=0; i<N; i++) { 8398 WindowState ws = mWindows.get(i); 8399 if (ws.mSurface != null) { 8400 pidCandidates.append(ws.mSession.mPid, ws.mSession.mPid); 8401 } 8402 } 8403 if (pidCandidates.size() > 0) { 8404 int[] pids = new int[pidCandidates.size()]; 8405 for (int i=0; i<pids.length; i++) { 8406 pids[i] = pidCandidates.keyAt(i); 8407 } 8408 try { 8409 if (mActivityManager.killPids(pids, "Free memory", secure)) { 8410 killedApps = true; 8411 } 8412 } catch (RemoteException e) { 8413 } 8414 } 8415 } 8416 8417 if (leakedSurface || killedApps) { 8418 // We managed to reclaim some memory, so get rid of the trouble 8419 // surface and ask the app to request another one. 8420 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 8421 if (surface != null) { 8422 if (SHOW_TRANSACTIONS) logSurface(win, "RECOVER DESTROY", null); 8423 surface.destroy(); 8424 win.mSurfaceShown = false; 8425 win.mSurface = null; 8426 } 8427 8428 try { 8429 win.mClient.dispatchGetNewSurface(); 8430 } catch (RemoteException e) { 8431 } 8432 } 8433 } finally { 8434 Binder.restoreCallingIdentity(callingIdentity); 8435 } 8436 8437 return leakedSurface || killedApps; 8438 } 8439 8440 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 8441 WindowState newFocus = computeFocusedWindowLocked(); 8442 if (mCurrentFocus != newFocus) { 8443 // This check makes sure that we don't already have the focus 8444 // change message pending. 8445 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 8446 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 8447 if (localLOGV) Slog.v( 8448 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus); 8449 final WindowState oldFocus = mCurrentFocus; 8450 mCurrentFocus = newFocus; 8451 mLosingFocus.remove(newFocus); 8452 8453 final WindowState imWindow = mInputMethodWindow; 8454 if (newFocus != imWindow && oldFocus != imWindow) { 8455 if (moveInputMethodWindowsIfNeededLocked( 8456 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS && 8457 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) { 8458 mLayoutNeeded = true; 8459 } 8460 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 8461 performLayoutLockedInner(true /*initial*/, updateInputWindows); 8462 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 8463 // Client will do the layout, but we need to assign layers 8464 // for handleNewWindowLocked() below. 8465 assignLayersLocked(); 8466 } 8467 } 8468 8469 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 8470 // If we defer assigning layers, then the caller is responsible for 8471 // doing this part. 8472 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 8473 } 8474 return true; 8475 } 8476 return false; 8477 } 8478 8479 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 8480 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 8481 } 8482 8483 private WindowState computeFocusedWindowLocked() { 8484 WindowState result = null; 8485 WindowState win; 8486 8487 int i = mWindows.size() - 1; 8488 int nextAppIndex = mAppTokens.size()-1; 8489 WindowToken nextApp = nextAppIndex >= 0 8490 ? mAppTokens.get(nextAppIndex) : null; 8491 8492 while (i >= 0) { 8493 win = mWindows.get(i); 8494 8495 if (localLOGV || DEBUG_FOCUS) Slog.v( 8496 TAG, "Looking for focus: " + i 8497 + " = " + win 8498 + ", flags=" + win.mAttrs.flags 8499 + ", canReceive=" + win.canReceiveKeys()); 8500 8501 AppWindowToken thisApp = win.mAppToken; 8502 8503 // If this window's application has been removed, just skip it. 8504 if (thisApp != null && thisApp.removed) { 8505 i--; 8506 continue; 8507 } 8508 8509 // If there is a focused app, don't allow focus to go to any 8510 // windows below it. If this is an application window, step 8511 // through the app tokens until we find its app. 8512 if (thisApp != null && nextApp != null && thisApp != nextApp 8513 && win.mAttrs.type != TYPE_APPLICATION_STARTING) { 8514 int origAppIndex = nextAppIndex; 8515 while (nextAppIndex > 0) { 8516 if (nextApp == mFocusedApp) { 8517 // Whoops, we are below the focused app... no focus 8518 // for you! 8519 if (localLOGV || DEBUG_FOCUS) Slog.v( 8520 TAG, "Reached focused app: " + mFocusedApp); 8521 return null; 8522 } 8523 nextAppIndex--; 8524 nextApp = mAppTokens.get(nextAppIndex); 8525 if (nextApp == thisApp) { 8526 break; 8527 } 8528 } 8529 if (thisApp != nextApp) { 8530 // Uh oh, the app token doesn't exist! This shouldn't 8531 // happen, but if it does we can get totally hosed... 8532 // so restart at the original app. 8533 nextAppIndex = origAppIndex; 8534 nextApp = mAppTokens.get(nextAppIndex); 8535 } 8536 } 8537 8538 // Dispatch to this window if it is wants key events. 8539 if (win.canReceiveKeys()) { 8540 if (DEBUG_FOCUS) Slog.v( 8541 TAG, "Found focus @ " + i + " = " + win); 8542 result = win; 8543 break; 8544 } 8545 8546 i--; 8547 } 8548 8549 return result; 8550 } 8551 8552 private void startFreezingDisplayLocked(boolean inTransaction) { 8553 if (mDisplayFrozen) { 8554 return; 8555 } 8556 8557 mScreenFrozenLock.acquire(); 8558 8559 long now = SystemClock.uptimeMillis(); 8560 //Slog.i(TAG, "Freezing, gc pending: " + mFreezeGcPending + ", now " + now); 8561 if (mFreezeGcPending != 0) { 8562 if (now > (mFreezeGcPending+1000)) { 8563 //Slog.i(TAG, "Gc! " + now + " > " + (mFreezeGcPending+1000)); 8564 mH.removeMessages(H.FORCE_GC); 8565 Runtime.getRuntime().gc(); 8566 mFreezeGcPending = now; 8567 } 8568 } else { 8569 mFreezeGcPending = now; 8570 } 8571 8572 mDisplayFrozen = true; 8573 8574 mInputMonitor.freezeInputDispatchingLw(); 8575 8576 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 8577 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 8578 mNextAppTransitionPackage = null; 8579 mAppTransitionReady = true; 8580 } 8581 8582 if (PROFILE_ORIENTATION) { 8583 File file = new File("/data/system/frozen"); 8584 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 8585 } 8586 8587 if (CUSTOM_SCREEN_ROTATION) { 8588 if (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating()) { 8589 mScreenRotationAnimation.kill(); 8590 mScreenRotationAnimation = null; 8591 } 8592 if (mScreenRotationAnimation == null) { 8593 mScreenRotationAnimation = new ScreenRotationAnimation(mContext, 8594 mDisplay, mFxSession, inTransaction); 8595 } 8596 if (!mScreenRotationAnimation.hasScreenshot()) { 8597 Surface.freezeDisplay(0); 8598 } 8599 } else { 8600 Surface.freezeDisplay(0); 8601 } 8602 } 8603 8604 private void stopFreezingDisplayLocked() { 8605 if (!mDisplayFrozen) { 8606 return; 8607 } 8608 8609 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) { 8610 return; 8611 } 8612 8613 mDisplayFrozen = false; 8614 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 8615 if (PROFILE_ORIENTATION) { 8616 Debug.stopMethodTracing(); 8617 } 8618 8619 boolean updateRotation = false; 8620 8621 if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null 8622 && mScreenRotationAnimation.hasScreenshot()) { 8623 if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 8624 mTransitionAnimationScale)) { 8625 requestAnimationLocked(0); 8626 } else { 8627 mScreenRotationAnimation = null; 8628 updateRotation = true; 8629 } 8630 } else { 8631 if (mScreenRotationAnimation != null) { 8632 mScreenRotationAnimation.kill(); 8633 mScreenRotationAnimation = null; 8634 } 8635 updateRotation = true; 8636 Surface.unfreezeDisplay(0); 8637 } 8638 8639 mInputMonitor.thawInputDispatchingLw(); 8640 8641 boolean configChanged; 8642 8643 // While the display is frozen we don't re-compute the orientation 8644 // to avoid inconsistent states. However, something interesting 8645 // could have actually changed during that time so re-evaluate it 8646 // now to catch that. 8647 configChanged = updateOrientationFromAppTokensLocked(false); 8648 8649 // A little kludge: a lot could have happened while the 8650 // display was frozen, so now that we are coming back we 8651 // do a gc so that any remote references the system 8652 // processes holds on others can be released if they are 8653 // no longer needed. 8654 mH.removeMessages(H.FORCE_GC); 8655 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 8656 2000); 8657 8658 mScreenFrozenLock.release(); 8659 8660 if (updateRotation) { 8661 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 8662 configChanged |= setRotationUncheckedLocked( 8663 WindowManagerPolicy.USE_LAST_ROTATION, 0, false); 8664 } 8665 8666 if (configChanged) { 8667 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8668 } 8669 } 8670 8671 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 8672 DisplayMetrics dm) { 8673 if (index < tokens.length) { 8674 String str = tokens[index]; 8675 if (str != null && str.length() > 0) { 8676 try { 8677 int val = Integer.parseInt(str); 8678 return val; 8679 } catch (Exception e) { 8680 } 8681 } 8682 } 8683 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 8684 return defDps; 8685 } 8686 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 8687 return val; 8688 } 8689 8690 void createWatermark() { 8691 if (mWatermark != null) { 8692 return; 8693 } 8694 8695 File file = new File("/system/etc/setup.conf"); 8696 FileInputStream in = null; 8697 try { 8698 in = new FileInputStream(file); 8699 DataInputStream ind = new DataInputStream(in); 8700 String line = ind.readLine(); 8701 if (line != null) { 8702 String[] toks = line.split("%"); 8703 if (toks != null && toks.length > 0) { 8704 mWatermark = new Watermark(mDisplay, mFxSession, toks); 8705 } 8706 } 8707 } catch (FileNotFoundException e) { 8708 } catch (IOException e) { 8709 } finally { 8710 if (in != null) { 8711 try { 8712 in.close(); 8713 } catch (IOException e) { 8714 } 8715 } 8716 } 8717 } 8718 8719 @Override 8720 public void statusBarVisibilityChanged(int visibility) { 8721 mInputManager.setSystemUiVisibility(visibility); 8722 synchronized (mWindowMap) { 8723 final int N = mWindows.size(); 8724 for (int i = 0; i < N; i++) { 8725 WindowState ws = mWindows.get(i); 8726 try { 8727 if (ws.getAttrs().hasSystemUiListeners) { 8728 ws.mClient.dispatchSystemUiVisibilityChanged(visibility); 8729 } 8730 } catch (RemoteException e) { 8731 // so sorry 8732 } 8733 } 8734 } 8735 } 8736 8737 @Override 8738 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 8739 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 8740 != PackageManager.PERMISSION_GRANTED) { 8741 pw.println("Permission Denial: can't dump WindowManager from from pid=" 8742 + Binder.getCallingPid() 8743 + ", uid=" + Binder.getCallingUid()); 8744 return; 8745 } 8746 8747 mInputManager.dump(pw); 8748 pw.println(" "); 8749 8750 synchronized(mWindowMap) { 8751 pw.println("Current Window Manager state:"); 8752 for (int i=mWindows.size()-1; i>=0; i--) { 8753 WindowState w = mWindows.get(i); 8754 pw.print(" Window #"); pw.print(i); pw.print(' '); 8755 pw.print(w); pw.println(":"); 8756 w.dump(pw, " "); 8757 } 8758 if (mInputMethodDialogs.size() > 0) { 8759 pw.println(" "); 8760 pw.println(" Input method dialogs:"); 8761 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 8762 WindowState w = mInputMethodDialogs.get(i); 8763 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 8764 } 8765 } 8766 if (mPendingRemove.size() > 0) { 8767 pw.println(" "); 8768 pw.println(" Remove pending for:"); 8769 for (int i=mPendingRemove.size()-1; i>=0; i--) { 8770 WindowState w = mPendingRemove.get(i); 8771 pw.print(" Remove #"); pw.print(i); pw.print(' '); 8772 pw.print(w); pw.println(":"); 8773 w.dump(pw, " "); 8774 } 8775 } 8776 if (mForceRemoves != null && mForceRemoves.size() > 0) { 8777 pw.println(" "); 8778 pw.println(" Windows force removing:"); 8779 for (int i=mForceRemoves.size()-1; i>=0; i--) { 8780 WindowState w = mForceRemoves.get(i); 8781 pw.print(" Removing #"); pw.print(i); pw.print(' '); 8782 pw.print(w); pw.println(":"); 8783 w.dump(pw, " "); 8784 } 8785 } 8786 if (mDestroySurface.size() > 0) { 8787 pw.println(" "); 8788 pw.println(" Windows waiting to destroy their surface:"); 8789 for (int i=mDestroySurface.size()-1; i>=0; i--) { 8790 WindowState w = mDestroySurface.get(i); 8791 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 8792 pw.print(w); pw.println(":"); 8793 w.dump(pw, " "); 8794 } 8795 } 8796 if (mLosingFocus.size() > 0) { 8797 pw.println(" "); 8798 pw.println(" Windows losing focus:"); 8799 for (int i=mLosingFocus.size()-1; i>=0; i--) { 8800 WindowState w = mLosingFocus.get(i); 8801 pw.print(" Losing #"); pw.print(i); pw.print(' '); 8802 pw.print(w); pw.println(":"); 8803 w.dump(pw, " "); 8804 } 8805 } 8806 if (mResizingWindows.size() > 0) { 8807 pw.println(" "); 8808 pw.println(" Windows waiting to resize:"); 8809 for (int i=mResizingWindows.size()-1; i>=0; i--) { 8810 WindowState w = mResizingWindows.get(i); 8811 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 8812 pw.print(w); pw.println(":"); 8813 w.dump(pw, " "); 8814 } 8815 } 8816 if (mSessions.size() > 0) { 8817 pw.println(" "); 8818 pw.println(" All active sessions:"); 8819 Iterator<Session> it = mSessions.iterator(); 8820 while (it.hasNext()) { 8821 Session s = it.next(); 8822 pw.print(" Session "); pw.print(s); pw.println(':'); 8823 s.dump(pw, " "); 8824 } 8825 } 8826 if (mTokenMap.size() > 0) { 8827 pw.println(" "); 8828 pw.println(" All tokens:"); 8829 Iterator<WindowToken> it = mTokenMap.values().iterator(); 8830 while (it.hasNext()) { 8831 WindowToken token = it.next(); 8832 pw.print(" Token "); pw.print(token.token); pw.println(':'); 8833 token.dump(pw, " "); 8834 } 8835 } 8836 if (mWallpaperTokens.size() > 0) { 8837 pw.println(" "); 8838 pw.println(" Wallpaper tokens:"); 8839 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 8840 WindowToken token = mWallpaperTokens.get(i); 8841 pw.print(" Wallpaper #"); pw.print(i); 8842 pw.print(' '); pw.print(token); pw.println(':'); 8843 token.dump(pw, " "); 8844 } 8845 } 8846 if (mAppTokens.size() > 0) { 8847 pw.println(" "); 8848 pw.println(" Application tokens in Z order:"); 8849 for (int i=mAppTokens.size()-1; i>=0; i--) { 8850 pw.print(" App #"); pw.print(i); pw.print(": "); 8851 pw.println(mAppTokens.get(i)); 8852 } 8853 } 8854 if (mFinishedStarting.size() > 0) { 8855 pw.println(" "); 8856 pw.println(" Finishing start of application tokens:"); 8857 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 8858 WindowToken token = mFinishedStarting.get(i); 8859 pw.print(" Finished Starting #"); pw.print(i); 8860 pw.print(' '); pw.print(token); pw.println(':'); 8861 token.dump(pw, " "); 8862 } 8863 } 8864 if (mExitingTokens.size() > 0) { 8865 pw.println(" "); 8866 pw.println(" Exiting tokens:"); 8867 for (int i=mExitingTokens.size()-1; i>=0; i--) { 8868 WindowToken token = mExitingTokens.get(i); 8869 pw.print(" Exiting #"); pw.print(i); 8870 pw.print(' '); pw.print(token); pw.println(':'); 8871 token.dump(pw, " "); 8872 } 8873 } 8874 if (mExitingAppTokens.size() > 0) { 8875 pw.println(" "); 8876 pw.println(" Exiting application tokens:"); 8877 for (int i=mExitingAppTokens.size()-1; i>=0; i--) { 8878 WindowToken token = mExitingAppTokens.get(i); 8879 pw.print(" Exiting App #"); pw.print(i); 8880 pw.print(' '); pw.print(token); pw.println(':'); 8881 token.dump(pw, " "); 8882 } 8883 } 8884 pw.println(" "); 8885 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 8886 pw.print(" mLastFocus="); pw.println(mLastFocus); 8887 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 8888 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 8889 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 8890 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 8891 if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) { 8892 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 8893 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 8894 } 8895 if (mWindowDetachedWallpaper != null) { 8896 pw.print(" mWindowDetachedWallpaper="); pw.println(mWindowDetachedWallpaper); 8897 } 8898 if (mWindowAnimationBackgroundSurface != null) { 8899 pw.println(" mWindowAnimationBackgroundSurface:"); 8900 mWindowAnimationBackgroundSurface.printTo(" ", pw); 8901 } 8902 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 8903 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 8904 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 8905 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 8906 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 8907 pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded); 8908 pw.print(" mBlurShown="); pw.println(mBlurShown); 8909 if (mDimAnimator != null) { 8910 pw.println(" mDimAnimator:"); 8911 mDimAnimator.printTo(" ", pw); 8912 } else { 8913 pw.println( " no DimAnimator "); 8914 } 8915 pw.print(" mInputMethodAnimLayerAdjustment="); 8916 pw.print(mInputMethodAnimLayerAdjustment); 8917 pw.print(" mWallpaperAnimLayerAdjustment="); 8918 pw.println(mWallpaperAnimLayerAdjustment); 8919 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 8920 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 8921 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 8922 pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen); 8923 pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen); 8924 pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig); 8925 pw.print(" mRotation="); pw.print(mRotation); 8926 pw.print(" mForcedAppOrientation="); pw.print(mForcedAppOrientation); 8927 pw.print(" mRequestedRotation="); pw.print(mRequestedRotation); 8928 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 8929 pw.print(" mDeferredRotation="); pw.print(mDeferredRotation); 8930 pw.print(", mDeferredRotationAnimFlags="); pw.println(mDeferredRotationAnimFlags); 8931 pw.print(" mAnimationPending="); pw.print(mAnimationPending); 8932 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); 8933 pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale); 8934 pw.print(" mNextAppTransition=0x"); 8935 pw.print(Integer.toHexString(mNextAppTransition)); 8936 pw.print(" mAppTransitionReady="); pw.println(mAppTransitionReady); 8937 pw.print(" mAppTransitionRunning="); pw.print(mAppTransitionRunning); 8938 pw.print(" mAppTransitionTimeout="); pw.println( mAppTransitionTimeout); 8939 if (mNextAppTransitionPackage != null) { 8940 pw.print(" mNextAppTransitionPackage="); 8941 pw.print(mNextAppTransitionPackage); 8942 pw.print(" mNextAppTransitionEnter=0x"); 8943 pw.print(Integer.toHexString(mNextAppTransitionEnter)); 8944 pw.print(" mNextAppTransitionExit=0x"); 8945 pw.print(Integer.toHexString(mNextAppTransitionExit)); 8946 } 8947 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 8948 pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 8949 if (mOpeningApps.size() > 0) { 8950 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 8951 } 8952 if (mClosingApps.size() > 0) { 8953 pw.print(" mClosingApps="); pw.println(mClosingApps); 8954 } 8955 if (mToTopApps.size() > 0) { 8956 pw.print(" mToTopApps="); pw.println(mToTopApps); 8957 } 8958 if (mToBottomApps.size() > 0) { 8959 pw.print(" mToBottomApps="); pw.println(mToBottomApps); 8960 } 8961 if (mDisplay != null) { 8962 pw.print(" Display: init="); pw.print(mInitialDisplayWidth); pw.print("x"); 8963 pw.print(mInitialDisplayHeight); pw.print(" base="); 8964 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); 8965 pw.print(" cur="); 8966 pw.print(mCurDisplayWidth); pw.print("x"); pw.print(mCurDisplayHeight); 8967 pw.print(" real="); pw.print(mDisplay.getRealWidth()); 8968 pw.print("x"); pw.print(mDisplay.getRealHeight()); 8969 pw.print(" raw="); pw.print(mDisplay.getRawWidth()); 8970 pw.print("x"); pw.println(mDisplay.getRawHeight()); 8971 } else { 8972 pw.println(" NO DISPLAY"); 8973 } 8974 pw.println(" Policy:"); 8975 mPolicy.dump(" ", fd, pw, args); 8976 } 8977 } 8978 8979 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 8980 public void monitor() { 8981 synchronized (mWindowMap) { } 8982 synchronized (mKeyguardTokenWatcher) { } 8983 } 8984 8985 public interface OnHardKeyboardStatusChangeListener { 8986 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 8987 } 8988} 8989