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