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