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 // If this screen is wider than normal HVGA, or taller 5034 // than FWVGA, then for old apps we want to run in size 5035 // compatibility mode. 5036 if (shortSize > 321 || longSize > 570) { 5037 mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED; 5038 } 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 keyCode, boolean down, 5254 int policyFlags, boolean isScreenOn) { 5255 return mPolicy.interceptKeyBeforeQueueing(whenNanos, 5256 keyCode, down, 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 metaState, int repeatCount, 5263 int policyFlags) { 5264 WindowState windowState = getWindowStateForInputChannel(focus); 5265 return mPolicy.interceptKeyBeforeDispatching(windowState, action, flags, 5266 keyCode, 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 WindowState(Session s, IWindow c, WindowToken token, 6007 WindowState attachedWindow, WindowManager.LayoutParams a, 6008 int viewVisibility) { 6009 mSession = s; 6010 mClient = c; 6011 mToken = token; 6012 mAttrs.copyFrom(a); 6013 mViewVisibility = viewVisibility; 6014 DeathRecipient deathRecipient = new DeathRecipient(); 6015 mAlpha = a.alpha; 6016 if (localLOGV) Slog.v( 6017 TAG, "Window " + this + " client=" + c.asBinder() 6018 + " token=" + token + " (" + mAttrs.token + ")"); 6019 try { 6020 c.asBinder().linkToDeath(deathRecipient, 0); 6021 } catch (RemoteException e) { 6022 mDeathRecipient = null; 6023 mAttachedWindow = null; 6024 mLayoutAttached = false; 6025 mIsImWindow = false; 6026 mIsWallpaper = false; 6027 mIsFloatingLayer = false; 6028 mBaseLayer = 0; 6029 mSubLayer = 0; 6030 return; 6031 } 6032 mDeathRecipient = deathRecipient; 6033 6034 if ((mAttrs.type >= FIRST_SUB_WINDOW && 6035 mAttrs.type <= LAST_SUB_WINDOW)) { 6036 // The multiplier here is to reserve space for multiple 6037 // windows in the same type layer. 6038 mBaseLayer = mPolicy.windowTypeToLayerLw( 6039 attachedWindow.mAttrs.type) * TYPE_LAYER_MULTIPLIER 6040 + TYPE_LAYER_OFFSET; 6041 mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type); 6042 mAttachedWindow = attachedWindow; 6043 mAttachedWindow.mChildWindows.add(this); 6044 mLayoutAttached = mAttrs.type != 6045 WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 6046 mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD 6047 || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG; 6048 mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER; 6049 mIsFloatingLayer = mIsImWindow || mIsWallpaper; 6050 } else { 6051 // The multiplier here is to reserve space for multiple 6052 // windows in the same type layer. 6053 mBaseLayer = mPolicy.windowTypeToLayerLw(a.type) 6054 * TYPE_LAYER_MULTIPLIER 6055 + TYPE_LAYER_OFFSET; 6056 mSubLayer = 0; 6057 mAttachedWindow = null; 6058 mLayoutAttached = false; 6059 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD 6060 || mAttrs.type == TYPE_INPUT_METHOD_DIALOG; 6061 mIsWallpaper = mAttrs.type == TYPE_WALLPAPER; 6062 mIsFloatingLayer = mIsImWindow || mIsWallpaper; 6063 } 6064 6065 WindowState appWin = this; 6066 while (appWin.mAttachedWindow != null) { 6067 appWin = mAttachedWindow; 6068 } 6069 WindowToken appToken = appWin.mToken; 6070 while (appToken.appWindowToken == null) { 6071 WindowToken parent = mTokenMap.get(appToken.token); 6072 if (parent == null || appToken == parent) { 6073 break; 6074 } 6075 appToken = parent; 6076 } 6077 mRootToken = appToken; 6078 mAppToken = appToken.appWindowToken; 6079 6080 mSurface = null; 6081 mRequestedWidth = 0; 6082 mRequestedHeight = 0; 6083 mLastRequestedWidth = 0; 6084 mLastRequestedHeight = 0; 6085 mXOffset = 0; 6086 mYOffset = 0; 6087 mLayer = 0; 6088 mAnimLayer = 0; 6089 mLastLayer = 0; 6090 } 6091 6092 void attach() { 6093 if (localLOGV) Slog.v( 6094 TAG, "Attaching " + this + " token=" + mToken 6095 + ", list=" + mToken.windows); 6096 mSession.windowAddedLocked(); 6097 } 6098 6099 public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) { 6100 mHaveFrame = true; 6101 6102 final Rect container = mContainingFrame; 6103 container.set(pf); 6104 6105 final Rect display = mDisplayFrame; 6106 display.set(df); 6107 6108 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) { 6109 container.intersect(mCompatibleScreenFrame); 6110 if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) { 6111 display.intersect(mCompatibleScreenFrame); 6112 } 6113 } 6114 6115 final int pw = container.right - container.left; 6116 final int ph = container.bottom - container.top; 6117 6118 int w,h; 6119 if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) { 6120 w = mAttrs.width < 0 ? pw : mAttrs.width; 6121 h = mAttrs.height< 0 ? ph : mAttrs.height; 6122 } else { 6123 w = mAttrs.width == mAttrs.MATCH_PARENT ? pw : mRequestedWidth; 6124 h = mAttrs.height== mAttrs.MATCH_PARENT ? ph : mRequestedHeight; 6125 } 6126 6127 final Rect content = mContentFrame; 6128 content.set(cf); 6129 6130 final Rect visible = mVisibleFrame; 6131 visible.set(vf); 6132 6133 final Rect frame = mFrame; 6134 final int fw = frame.width(); 6135 final int fh = frame.height(); 6136 6137 //System.out.println("In: w=" + w + " h=" + h + " container=" + 6138 // container + " x=" + mAttrs.x + " y=" + mAttrs.y); 6139 6140 Gravity.apply(mAttrs.gravity, w, h, container, 6141 (int) (mAttrs.x + mAttrs.horizontalMargin * pw), 6142 (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame); 6143 6144 //System.out.println("Out: " + mFrame); 6145 6146 // Now make sure the window fits in the overall display. 6147 Gravity.applyDisplay(mAttrs.gravity, df, frame); 6148 6149 // Make sure the content and visible frames are inside of the 6150 // final window frame. 6151 if (content.left < frame.left) content.left = frame.left; 6152 if (content.top < frame.top) content.top = frame.top; 6153 if (content.right > frame.right) content.right = frame.right; 6154 if (content.bottom > frame.bottom) content.bottom = frame.bottom; 6155 if (visible.left < frame.left) visible.left = frame.left; 6156 if (visible.top < frame.top) visible.top = frame.top; 6157 if (visible.right > frame.right) visible.right = frame.right; 6158 if (visible.bottom > frame.bottom) visible.bottom = frame.bottom; 6159 6160 final Rect contentInsets = mContentInsets; 6161 contentInsets.left = content.left-frame.left; 6162 contentInsets.top = content.top-frame.top; 6163 contentInsets.right = frame.right-content.right; 6164 contentInsets.bottom = frame.bottom-content.bottom; 6165 6166 final Rect visibleInsets = mVisibleInsets; 6167 visibleInsets.left = visible.left-frame.left; 6168 visibleInsets.top = visible.top-frame.top; 6169 visibleInsets.right = frame.right-visible.right; 6170 visibleInsets.bottom = frame.bottom-visible.bottom; 6171 6172 if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) { 6173 updateWallpaperOffsetLocked(this, mDisplay.getWidth(), 6174 mDisplay.getHeight(), false); 6175 } 6176 6177 if (localLOGV) { 6178 //if ("com.google.android.youtube".equals(mAttrs.packageName) 6179 // && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { 6180 Slog.v(TAG, "Resolving (mRequestedWidth=" 6181 + mRequestedWidth + ", mRequestedheight=" 6182 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph 6183 + "): frame=" + mFrame.toShortString() 6184 + " ci=" + contentInsets.toShortString() 6185 + " vi=" + visibleInsets.toShortString()); 6186 //} 6187 } 6188 } 6189 6190 public Rect getFrameLw() { 6191 return mFrame; 6192 } 6193 6194 public Rect getShownFrameLw() { 6195 return mShownFrame; 6196 } 6197 6198 public Rect getDisplayFrameLw() { 6199 return mDisplayFrame; 6200 } 6201 6202 public Rect getContentFrameLw() { 6203 return mContentFrame; 6204 } 6205 6206 public Rect getVisibleFrameLw() { 6207 return mVisibleFrame; 6208 } 6209 6210 public boolean getGivenInsetsPendingLw() { 6211 return mGivenInsetsPending; 6212 } 6213 6214 public Rect getGivenContentInsetsLw() { 6215 return mGivenContentInsets; 6216 } 6217 6218 public Rect getGivenVisibleInsetsLw() { 6219 return mGivenVisibleInsets; 6220 } 6221 6222 public WindowManager.LayoutParams getAttrs() { 6223 return mAttrs; 6224 } 6225 6226 public int getSurfaceLayer() { 6227 return mLayer; 6228 } 6229 6230 public IApplicationToken getAppToken() { 6231 return mAppToken != null ? mAppToken.appToken : null; 6232 } 6233 6234 public long getInputDispatchingTimeoutNanos() { 6235 return mAppToken != null 6236 ? mAppToken.inputDispatchingTimeoutNanos 6237 : DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 6238 } 6239 6240 public boolean hasAppShownWindows() { 6241 return mAppToken != null ? mAppToken.firstWindowDrawn : false; 6242 } 6243 6244 public void setAnimation(Animation anim) { 6245 if (localLOGV) Slog.v( 6246 TAG, "Setting animation in " + this + ": " + anim); 6247 mAnimating = false; 6248 mLocalAnimating = false; 6249 mAnimation = anim; 6250 mAnimation.restrictDuration(MAX_ANIMATION_DURATION); 6251 mAnimation.scaleCurrentDuration(mWindowAnimationScale); 6252 } 6253 6254 public void clearAnimation() { 6255 if (mAnimation != null) { 6256 mAnimating = true; 6257 mLocalAnimating = false; 6258 mAnimation = null; 6259 } 6260 } 6261 6262 Surface createSurfaceLocked() { 6263 if (mSurface == null) { 6264 mReportDestroySurface = false; 6265 mSurfacePendingDestroy = false; 6266 mDrawPending = true; 6267 mCommitDrawPending = false; 6268 mReadyToShow = false; 6269 if (mAppToken != null) { 6270 mAppToken.allDrawn = false; 6271 } 6272 6273 int flags = 0; 6274 if (mAttrs.memoryType == MEMORY_TYPE_PUSH_BUFFERS) { 6275 flags |= Surface.PUSH_BUFFERS; 6276 } 6277 6278 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) { 6279 flags |= Surface.SECURE; 6280 } 6281 if (DEBUG_VISIBILITY) Slog.v( 6282 TAG, "Creating surface in session " 6283 + mSession.mSurfaceSession + " window " + this 6284 + " w=" + mFrame.width() 6285 + " h=" + mFrame.height() + " format=" 6286 + mAttrs.format + " flags=" + flags); 6287 6288 int w = mFrame.width(); 6289 int h = mFrame.height(); 6290 if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) { 6291 // for a scaled surface, we always want the requested 6292 // size. 6293 w = mRequestedWidth; 6294 h = mRequestedHeight; 6295 } 6296 6297 // Something is wrong and SurfaceFlinger will not like this, 6298 // try to revert to sane values 6299 if (w <= 0) w = 1; 6300 if (h <= 0) h = 1; 6301 6302 mSurfaceShown = false; 6303 mSurfaceLayer = 0; 6304 mSurfaceAlpha = 1; 6305 mSurfaceX = 0; 6306 mSurfaceY = 0; 6307 mSurfaceW = w; 6308 mSurfaceH = h; 6309 try { 6310 mSurface = new Surface( 6311 mSession.mSurfaceSession, mSession.mPid, 6312 mAttrs.getTitle().toString(), 6313 0, w, h, mAttrs.format, flags); 6314 if (SHOW_TRANSACTIONS) Slog.i(TAG, " CREATE SURFACE " 6315 + mSurface + " IN SESSION " 6316 + mSession.mSurfaceSession 6317 + ": pid=" + mSession.mPid + " format=" 6318 + mAttrs.format + " flags=0x" 6319 + Integer.toHexString(flags) 6320 + " / " + this); 6321 } catch (Surface.OutOfResourcesException e) { 6322 Slog.w(TAG, "OutOfResourcesException creating surface"); 6323 reclaimSomeSurfaceMemoryLocked(this, "create"); 6324 return null; 6325 } catch (Exception e) { 6326 Slog.e(TAG, "Exception creating surface", e); 6327 return null; 6328 } 6329 6330 if (localLOGV) Slog.v( 6331 TAG, "Got surface: " + mSurface 6332 + ", set left=" + mFrame.left + " top=" + mFrame.top 6333 + ", animLayer=" + mAnimLayer); 6334 if (SHOW_TRANSACTIONS) { 6335 Slog.i(TAG, ">>> OPEN TRANSACTION"); 6336 if (SHOW_TRANSACTIONS) logSurface(this, 6337 "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" + 6338 mFrame.width() + "x" + mFrame.height() + "), layer=" + 6339 mAnimLayer + " HIDE", null); 6340 } 6341 Surface.openTransaction(); 6342 try { 6343 try { 6344 mSurfaceX = mFrame.left + mXOffset; 6345 mSurfaceY = mFrame.top + mYOffset; 6346 mSurface.setPosition(mSurfaceX, mSurfaceY); 6347 mSurfaceLayer = mAnimLayer; 6348 mSurface.setLayer(mAnimLayer); 6349 mSurfaceShown = false; 6350 mSurface.hide(); 6351 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) { 6352 if (SHOW_TRANSACTIONS) logSurface(this, "DITHER", null); 6353 mSurface.setFlags(Surface.SURFACE_DITHER, 6354 Surface.SURFACE_DITHER); 6355 } 6356 } catch (RuntimeException e) { 6357 Slog.w(TAG, "Error creating surface in " + w, e); 6358 reclaimSomeSurfaceMemoryLocked(this, "create-init"); 6359 } 6360 mLastHidden = true; 6361 } finally { 6362 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION"); 6363 Surface.closeTransaction(); 6364 } 6365 if (localLOGV) Slog.v( 6366 TAG, "Created surface " + this); 6367 } 6368 return mSurface; 6369 } 6370 6371 void destroySurfaceLocked() { 6372 if (mAppToken != null && this == mAppToken.startingWindow) { 6373 mAppToken.startingDisplayed = false; 6374 } 6375 6376 if (mSurface != null) { 6377 mDrawPending = false; 6378 mCommitDrawPending = false; 6379 mReadyToShow = false; 6380 6381 int i = mChildWindows.size(); 6382 while (i > 0) { 6383 i--; 6384 WindowState c = mChildWindows.get(i); 6385 c.mAttachedHidden = true; 6386 } 6387 6388 if (mReportDestroySurface) { 6389 mReportDestroySurface = false; 6390 mSurfacePendingDestroy = true; 6391 try { 6392 mClient.dispatchGetNewSurface(); 6393 // We'll really destroy on the next time around. 6394 return; 6395 } catch (RemoteException e) { 6396 } 6397 } 6398 6399 try { 6400 if (DEBUG_VISIBILITY) { 6401 RuntimeException e = null; 6402 if (!HIDE_STACK_CRAWLS) { 6403 e = new RuntimeException(); 6404 e.fillInStackTrace(); 6405 } 6406 Slog.w(TAG, "Window " + this + " destroying surface " 6407 + mSurface + ", session " + mSession, e); 6408 } 6409 if (SHOW_TRANSACTIONS) { 6410 RuntimeException e = null; 6411 if (!HIDE_STACK_CRAWLS) { 6412 e = new RuntimeException(); 6413 e.fillInStackTrace(); 6414 } 6415 if (SHOW_TRANSACTIONS) logSurface(this, "DESTROY", e); 6416 } 6417 mSurface.destroy(); 6418 } catch (RuntimeException e) { 6419 Slog.w(TAG, "Exception thrown when destroying Window " + this 6420 + " surface " + mSurface + " session " + mSession 6421 + ": " + e.toString()); 6422 } 6423 6424 mSurfaceShown = false; 6425 mSurface = null; 6426 } 6427 } 6428 6429 boolean finishDrawingLocked() { 6430 if (mDrawPending) { 6431 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Slog.v( 6432 TAG, "finishDrawingLocked: " + mSurface); 6433 mCommitDrawPending = true; 6434 mDrawPending = false; 6435 return true; 6436 } 6437 return false; 6438 } 6439 6440 // This must be called while inside a transaction. 6441 boolean commitFinishDrawingLocked(long currentTime) { 6442 //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface); 6443 if (!mCommitDrawPending) { 6444 return false; 6445 } 6446 mCommitDrawPending = false; 6447 mReadyToShow = true; 6448 final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING; 6449 final AppWindowToken atoken = mAppToken; 6450 if (atoken == null || atoken.allDrawn || starting) { 6451 performShowLocked(); 6452 } 6453 return true; 6454 } 6455 6456 // This must be called while inside a transaction. 6457 boolean performShowLocked() { 6458 if (DEBUG_VISIBILITY) { 6459 RuntimeException e = null; 6460 if (!HIDE_STACK_CRAWLS) { 6461 e = new RuntimeException(); 6462 e.fillInStackTrace(); 6463 } 6464 Slog.v(TAG, "performShow on " + this 6465 + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay() 6466 + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e); 6467 } 6468 if (mReadyToShow && isReadyForDisplay()) { 6469 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) logSurface(this, 6470 "SHOW (performShowLocked)", null); 6471 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this 6472 + " during animation: policyVis=" + mPolicyVisibility 6473 + " attHidden=" + mAttachedHidden 6474 + " tok.hiddenRequested=" 6475 + (mAppToken != null ? mAppToken.hiddenRequested : false) 6476 + " tok.hidden=" 6477 + (mAppToken != null ? mAppToken.hidden : false) 6478 + " animating=" + mAnimating 6479 + " tok animating=" 6480 + (mAppToken != null ? mAppToken.animating : false)); 6481 if (!showSurfaceRobustlyLocked(this)) { 6482 return false; 6483 } 6484 mLastAlpha = -1; 6485 mHasDrawn = true; 6486 mLastHidden = false; 6487 mReadyToShow = false; 6488 enableScreenIfNeededLocked(); 6489 6490 applyEnterAnimationLocked(this); 6491 6492 int i = mChildWindows.size(); 6493 while (i > 0) { 6494 i--; 6495 WindowState c = mChildWindows.get(i); 6496 if (c.mAttachedHidden) { 6497 c.mAttachedHidden = false; 6498 if (c.mSurface != null) { 6499 c.performShowLocked(); 6500 // It hadn't been shown, which means layout not 6501 // performed on it, so now we want to make sure to 6502 // do a layout. If called from within the transaction 6503 // loop, this will cause it to restart with a new 6504 // layout. 6505 mLayoutNeeded = true; 6506 } 6507 } 6508 } 6509 6510 if (mAttrs.type != TYPE_APPLICATION_STARTING 6511 && mAppToken != null) { 6512 mAppToken.firstWindowDrawn = true; 6513 6514 if (mAppToken.startingData != null) { 6515 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, 6516 "Finish starting " + mToken 6517 + ": first real window is shown, no animation"); 6518 // If this initial window is animating, stop it -- we 6519 // will do an animation to reveal it from behind the 6520 // starting window, so there is no need for it to also 6521 // be doing its own stuff. 6522 if (mAnimation != null) { 6523 mAnimation = null; 6524 // Make sure we clean up the animation. 6525 mAnimating = true; 6526 } 6527 mFinishedStarting.add(mAppToken); 6528 mH.sendEmptyMessage(H.FINISHED_STARTING); 6529 } 6530 mAppToken.updateReportedVisibilityLocked(); 6531 } 6532 } 6533 return true; 6534 } 6535 6536 // This must be called while inside a transaction. Returns true if 6537 // there is more animation to run. 6538 boolean stepAnimationLocked(long currentTime, int dw, int dh) { 6539 if (!mDisplayFrozen && mPolicy.isScreenOn()) { 6540 // We will run animations as long as the display isn't frozen. 6541 6542 if (!mDrawPending && !mCommitDrawPending && mAnimation != null) { 6543 mHasTransformation = true; 6544 mHasLocalTransformation = true; 6545 if (!mLocalAnimating) { 6546 if (DEBUG_ANIM) Slog.v( 6547 TAG, "Starting animation in " + this + 6548 " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() + 6549 " dw=" + dw + " dh=" + dh + " scale=" + mWindowAnimationScale); 6550 mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh); 6551 mAnimation.setStartTime(currentTime); 6552 mLocalAnimating = true; 6553 mAnimating = true; 6554 } 6555 mTransformation.clear(); 6556 final boolean more = mAnimation.getTransformation( 6557 currentTime, mTransformation); 6558 if (DEBUG_ANIM) Slog.v( 6559 TAG, "Stepped animation in " + this + 6560 ": more=" + more + ", xform=" + mTransformation); 6561 if (more) { 6562 // we're not done! 6563 return true; 6564 } 6565 if (DEBUG_ANIM) Slog.v( 6566 TAG, "Finished animation in " + this + 6567 " @ " + currentTime); 6568 mAnimation = null; 6569 //WindowManagerService.this.dump(); 6570 } 6571 mHasLocalTransformation = false; 6572 if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null 6573 && mAppToken.animation != null) { 6574 // When our app token is animating, we kind-of pretend like 6575 // we are as well. Note the mLocalAnimating mAnimationIsEntrance 6576 // part of this check means that we will only do this if 6577 // our window is not currently exiting, or it is not 6578 // locally animating itself. The idea being that one that 6579 // is exiting and doing a local animation should be removed 6580 // once that animation is done. 6581 mAnimating = true; 6582 mHasTransformation = true; 6583 mTransformation.clear(); 6584 return false; 6585 } else if (mHasTransformation) { 6586 // Little trick to get through the path below to act like 6587 // we have finished an animation. 6588 mAnimating = true; 6589 } else if (isAnimating()) { 6590 mAnimating = true; 6591 } 6592 } else if (mAnimation != null) { 6593 // If the display is frozen, and there is a pending animation, 6594 // clear it and make sure we run the cleanup code. 6595 mAnimating = true; 6596 mLocalAnimating = true; 6597 mAnimation = null; 6598 } 6599 6600 if (!mAnimating && !mLocalAnimating) { 6601 return false; 6602 } 6603 6604 if (DEBUG_ANIM) Slog.v( 6605 TAG, "Animation done in " + this + ": exiting=" + mExiting 6606 + ", reportedVisible=" 6607 + (mAppToken != null ? mAppToken.reportedVisible : false)); 6608 6609 mAnimating = false; 6610 mLocalAnimating = false; 6611 mAnimation = null; 6612 mAnimLayer = mLayer; 6613 if (mIsImWindow) { 6614 mAnimLayer += mInputMethodAnimLayerAdjustment; 6615 } else if (mIsWallpaper) { 6616 mAnimLayer += mWallpaperAnimLayerAdjustment; 6617 } 6618 if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this 6619 + " anim layer: " + mAnimLayer); 6620 mHasTransformation = false; 6621 mHasLocalTransformation = false; 6622 if (mPolicyVisibility != mPolicyVisibilityAfterAnim) { 6623 if (DEBUG_VISIBILITY) { 6624 Slog.v(TAG, "Policy visibility changing after anim in " + this + ": " 6625 + mPolicyVisibilityAfterAnim); 6626 } 6627 mPolicyVisibility = mPolicyVisibilityAfterAnim; 6628 if (!mPolicyVisibility) { 6629 if (mCurrentFocus == this) { 6630 mFocusMayChange = true; 6631 } 6632 // Window is no longer visible -- make sure if we were waiting 6633 // for it to be displayed before enabling the display, that 6634 // we allow the display to be enabled now. 6635 enableScreenIfNeededLocked(); 6636 } 6637 } 6638 mTransformation.clear(); 6639 if (mHasDrawn 6640 && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING 6641 && mAppToken != null 6642 && mAppToken.firstWindowDrawn 6643 && mAppToken.startingData != null) { 6644 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting " 6645 + mToken + ": first real window done animating"); 6646 mFinishedStarting.add(mAppToken); 6647 mH.sendEmptyMessage(H.FINISHED_STARTING); 6648 } 6649 6650 finishExit(); 6651 6652 if (mAppToken != null) { 6653 mAppToken.updateReportedVisibilityLocked(); 6654 } 6655 6656 return false; 6657 } 6658 6659 void finishExit() { 6660 if (DEBUG_ANIM) Slog.v( 6661 TAG, "finishExit in " + this 6662 + ": exiting=" + mExiting 6663 + " remove=" + mRemoveOnExit 6664 + " windowAnimating=" + isWindowAnimating()); 6665 6666 final int N = mChildWindows.size(); 6667 for (int i=0; i<N; i++) { 6668 mChildWindows.get(i).finishExit(); 6669 } 6670 6671 if (!mExiting) { 6672 return; 6673 } 6674 6675 if (isWindowAnimating()) { 6676 return; 6677 } 6678 6679 if (localLOGV) Slog.v( 6680 TAG, "Exit animation finished in " + this 6681 + ": remove=" + mRemoveOnExit); 6682 if (mSurface != null) { 6683 mDestroySurface.add(this); 6684 mDestroying = true; 6685 if (SHOW_TRANSACTIONS) logSurface(this, "HIDE (finishExit)", null); 6686 mSurfaceShown = false; 6687 try { 6688 mSurface.hide(); 6689 } catch (RuntimeException e) { 6690 Slog.w(TAG, "Error hiding surface in " + this, e); 6691 } 6692 mLastHidden = true; 6693 } 6694 mExiting = false; 6695 if (mRemoveOnExit) { 6696 mPendingRemove.add(this); 6697 mRemoveOnExit = false; 6698 } 6699 } 6700 6701 boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { 6702 if (dsdx < .99999f || dsdx > 1.00001f) return false; 6703 if (dtdy < .99999f || dtdy > 1.00001f) return false; 6704 if (dtdx < -.000001f || dtdx > .000001f) return false; 6705 if (dsdy < -.000001f || dsdy > .000001f) return false; 6706 return true; 6707 } 6708 6709 void computeShownFrameLocked() { 6710 final boolean selfTransformation = mHasLocalTransformation; 6711 Transformation attachedTransformation = 6712 (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation) 6713 ? mAttachedWindow.mTransformation : null; 6714 Transformation appTransformation = 6715 (mAppToken != null && mAppToken.hasTransformation) 6716 ? mAppToken.transformation : null; 6717 6718 // Wallpapers are animated based on the "real" window they 6719 // are currently targeting. 6720 if (mAttrs.type == TYPE_WALLPAPER && mLowerWallpaperTarget == null 6721 && mWallpaperTarget != null) { 6722 if (mWallpaperTarget.mHasLocalTransformation && 6723 mWallpaperTarget.mAnimation != null && 6724 !mWallpaperTarget.mAnimation.getDetachWallpaper()) { 6725 attachedTransformation = mWallpaperTarget.mTransformation; 6726 if (DEBUG_WALLPAPER && attachedTransformation != null) { 6727 Slog.v(TAG, "WP target attached xform: " + attachedTransformation); 6728 } 6729 } 6730 if (mWallpaperTarget.mAppToken != null && 6731 mWallpaperTarget.mAppToken.hasTransformation && 6732 mWallpaperTarget.mAppToken.animation != null && 6733 !mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) { 6734 appTransformation = mWallpaperTarget.mAppToken.transformation; 6735 if (DEBUG_WALLPAPER && appTransformation != null) { 6736 Slog.v(TAG, "WP target app xform: " + appTransformation); 6737 } 6738 } 6739 } 6740 6741 if (selfTransformation || attachedTransformation != null 6742 || appTransformation != null) { 6743 // cache often used attributes locally 6744 final Rect frame = mFrame; 6745 final float tmpFloats[] = mTmpFloats; 6746 final Matrix tmpMatrix = mTmpMatrix; 6747 6748 // Compute the desired transformation. 6749 tmpMatrix.setTranslate(0, 0); 6750 if (selfTransformation) { 6751 tmpMatrix.postConcat(mTransformation.getMatrix()); 6752 } 6753 tmpMatrix.postTranslate(frame.left, frame.top); 6754 if (attachedTransformation != null) { 6755 tmpMatrix.postConcat(attachedTransformation.getMatrix()); 6756 } 6757 if (appTransformation != null) { 6758 tmpMatrix.postConcat(appTransformation.getMatrix()); 6759 } 6760 6761 // "convert" it into SurfaceFlinger's format 6762 // (a 2x2 matrix + an offset) 6763 // Here we must not transform the position of the surface 6764 // since it is already included in the transformation. 6765 //Slog.i(TAG, "Transform: " + matrix); 6766 6767 tmpMatrix.getValues(tmpFloats); 6768 mDsDx = tmpFloats[Matrix.MSCALE_X]; 6769 mDtDx = tmpFloats[Matrix.MSKEW_X]; 6770 mDsDy = tmpFloats[Matrix.MSKEW_Y]; 6771 mDtDy = tmpFloats[Matrix.MSCALE_Y]; 6772 int x = (int)tmpFloats[Matrix.MTRANS_X] + mXOffset; 6773 int y = (int)tmpFloats[Matrix.MTRANS_Y] + mYOffset; 6774 int w = frame.width(); 6775 int h = frame.height(); 6776 mShownFrame.set(x, y, x+w, y+h); 6777 6778 // Now set the alpha... but because our current hardware 6779 // can't do alpha transformation on a non-opaque surface, 6780 // turn it off if we are running an animation that is also 6781 // transforming since it is more important to have that 6782 // animation be smooth. 6783 mShownAlpha = mAlpha; 6784 if (!mLimitedAlphaCompositing 6785 || (!PixelFormat.formatHasAlpha(mAttrs.format) 6786 || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy) 6787 && x == frame.left && y == frame.top))) { 6788 //Slog.i(TAG, "Applying alpha transform"); 6789 if (selfTransformation) { 6790 mShownAlpha *= mTransformation.getAlpha(); 6791 } 6792 if (attachedTransformation != null) { 6793 mShownAlpha *= attachedTransformation.getAlpha(); 6794 } 6795 if (appTransformation != null) { 6796 mShownAlpha *= appTransformation.getAlpha(); 6797 } 6798 } else { 6799 //Slog.i(TAG, "Not applying alpha transform"); 6800 } 6801 6802 if (localLOGV) Slog.v( 6803 TAG, "Continuing animation in " + this + 6804 ": " + mShownFrame + 6805 ", alpha=" + mTransformation.getAlpha()); 6806 return; 6807 } 6808 6809 mShownFrame.set(mFrame); 6810 if (mXOffset != 0 || mYOffset != 0) { 6811 mShownFrame.offset(mXOffset, mYOffset); 6812 } 6813 mShownAlpha = mAlpha; 6814 mDsDx = 1; 6815 mDtDx = 0; 6816 mDsDy = 0; 6817 mDtDy = 1; 6818 } 6819 6820 /** 6821 * Is this window visible? It is not visible if there is no 6822 * surface, or we are in the process of running an exit animation 6823 * that will remove the surface, or its app token has been hidden. 6824 */ 6825 public boolean isVisibleLw() { 6826 final AppWindowToken atoken = mAppToken; 6827 return mSurface != null && mPolicyVisibility && !mAttachedHidden 6828 && (atoken == null || !atoken.hiddenRequested) 6829 && !mExiting && !mDestroying; 6830 } 6831 6832 /** 6833 * Like {@link #isVisibleLw}, but also counts a window that is currently 6834 * "hidden" behind the keyguard as visible. This allows us to apply 6835 * things like window flags that impact the keyguard. 6836 * XXX I am starting to think we need to have ANOTHER visibility flag 6837 * for this "hidden behind keyguard" state rather than overloading 6838 * mPolicyVisibility. Ungh. 6839 */ 6840 public boolean isVisibleOrBehindKeyguardLw() { 6841 final AppWindowToken atoken = mAppToken; 6842 return mSurface != null && !mAttachedHidden 6843 && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested) 6844 && (mOrientationChanging || (!mDrawPending && !mCommitDrawPending)) 6845 && !mExiting && !mDestroying; 6846 } 6847 6848 /** 6849 * Is this window visible, ignoring its app token? It is not visible 6850 * if there is no surface, or we are in the process of running an exit animation 6851 * that will remove the surface. 6852 */ 6853 public boolean isWinVisibleLw() { 6854 final AppWindowToken atoken = mAppToken; 6855 return mSurface != null && mPolicyVisibility && !mAttachedHidden 6856 && (atoken == null || !atoken.hiddenRequested || atoken.animating) 6857 && !mExiting && !mDestroying; 6858 } 6859 6860 /** 6861 * The same as isVisible(), but follows the current hidden state of 6862 * the associated app token, not the pending requested hidden state. 6863 */ 6864 boolean isVisibleNow() { 6865 return mSurface != null && mPolicyVisibility && !mAttachedHidden 6866 && !mRootToken.hidden && !mExiting && !mDestroying; 6867 } 6868 6869 /** 6870 * Same as isVisible(), but we also count it as visible between the 6871 * call to IWindowSession.add() and the first relayout(). 6872 */ 6873 boolean isVisibleOrAdding() { 6874 final AppWindowToken atoken = mAppToken; 6875 return ((mSurface != null && !mReportDestroySurface) 6876 || (!mRelayoutCalled && mViewVisibility == View.VISIBLE)) 6877 && mPolicyVisibility && !mAttachedHidden 6878 && (atoken == null || !atoken.hiddenRequested) 6879 && !mExiting && !mDestroying; 6880 } 6881 6882 /** 6883 * Is this window currently on-screen? It is on-screen either if it 6884 * is visible or it is currently running an animation before no longer 6885 * being visible. 6886 */ 6887 boolean isOnScreen() { 6888 final AppWindowToken atoken = mAppToken; 6889 if (atoken != null) { 6890 return mSurface != null && mPolicyVisibility && !mDestroying 6891 && ((!mAttachedHidden && !atoken.hiddenRequested) 6892 || mAnimation != null || atoken.animation != null); 6893 } else { 6894 return mSurface != null && mPolicyVisibility && !mDestroying 6895 && (!mAttachedHidden || mAnimation != null); 6896 } 6897 } 6898 6899 /** 6900 * Like isOnScreen(), but we don't return true if the window is part 6901 * of a transition that has not yet been started. 6902 */ 6903 boolean isReadyForDisplay() { 6904 if (mRootToken.waitingToShow && 6905 mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 6906 return false; 6907 } 6908 final AppWindowToken atoken = mAppToken; 6909 final boolean animating = atoken != null 6910 ? (atoken.animation != null) : false; 6911 return mSurface != null && mPolicyVisibility && !mDestroying 6912 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE 6913 && !mRootToken.hidden) 6914 || mAnimation != null || animating); 6915 } 6916 6917 /** Is the window or its container currently animating? */ 6918 boolean isAnimating() { 6919 final WindowState attached = mAttachedWindow; 6920 final AppWindowToken atoken = mAppToken; 6921 return mAnimation != null 6922 || (attached != null && attached.mAnimation != null) 6923 || (atoken != null && 6924 (atoken.animation != null 6925 || atoken.inPendingTransaction)); 6926 } 6927 6928 /** Is this window currently animating? */ 6929 boolean isWindowAnimating() { 6930 return mAnimation != null; 6931 } 6932 6933 /** 6934 * Like isOnScreen, but returns false if the surface hasn't yet 6935 * been drawn. 6936 */ 6937 public boolean isDisplayedLw() { 6938 final AppWindowToken atoken = mAppToken; 6939 return mSurface != null && mPolicyVisibility && !mDestroying 6940 && !mDrawPending && !mCommitDrawPending 6941 && ((!mAttachedHidden && 6942 (atoken == null || !atoken.hiddenRequested)) 6943 || mAnimating); 6944 } 6945 6946 /** 6947 * Returns true if the window has a surface that it has drawn a 6948 * complete UI in to. Note that this returns true if the orientation 6949 * is changing even if the window hasn't redrawn because we don't want 6950 * to stop things from executing during that time. 6951 */ 6952 public boolean isDrawnLw() { 6953 final AppWindowToken atoken = mAppToken; 6954 return mSurface != null && !mDestroying 6955 && (mOrientationChanging || (!mDrawPending && !mCommitDrawPending)); 6956 } 6957 6958 /** 6959 * Return true if the window is opaque and fully drawn. This indicates 6960 * it may obscure windows behind it. 6961 */ 6962 boolean isOpaqueDrawn() { 6963 return (mAttrs.format == PixelFormat.OPAQUE 6964 || mAttrs.type == TYPE_WALLPAPER) 6965 && mSurface != null && mAnimation == null 6966 && (mAppToken == null || mAppToken.animation == null) 6967 && !mDrawPending && !mCommitDrawPending; 6968 } 6969 6970 boolean needsBackgroundFiller(int screenWidth, int screenHeight) { 6971 return 6972 // only if the application is requesting compatible window 6973 (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 && 6974 // only if it's visible 6975 mHasDrawn && mViewVisibility == View.VISIBLE && 6976 // and only if the application fills the compatible screen 6977 mFrame.left <= mCompatibleScreenFrame.left && 6978 mFrame.top <= mCompatibleScreenFrame.top && 6979 mFrame.right >= mCompatibleScreenFrame.right && 6980 mFrame.bottom >= mCompatibleScreenFrame.bottom && 6981 // and starting window do not need background filler 6982 mAttrs.type != mAttrs.TYPE_APPLICATION_STARTING; 6983 } 6984 6985 boolean isFullscreen(int screenWidth, int screenHeight) { 6986 return mFrame.left <= 0 && mFrame.top <= 0 && 6987 mFrame.right >= screenWidth && mFrame.bottom >= screenHeight; 6988 } 6989 6990 void removeLocked() { 6991 disposeInputChannel(); 6992 6993 if (mAttachedWindow != null) { 6994 mAttachedWindow.mChildWindows.remove(this); 6995 } 6996 destroySurfaceLocked(); 6997 mSession.windowRemovedLocked(); 6998 try { 6999 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0); 7000 } catch (RuntimeException e) { 7001 // Ignore if it has already been removed (usually because 7002 // we are doing this as part of processing a death note.) 7003 } 7004 } 7005 7006 void disposeInputChannel() { 7007 if (mInputChannel != null) { 7008 mInputManager.unregisterInputChannel(mInputChannel); 7009 7010 mInputChannel.dispose(); 7011 mInputChannel = null; 7012 } 7013 } 7014 7015 private class DeathRecipient implements IBinder.DeathRecipient { 7016 public void binderDied() { 7017 try { 7018 synchronized(mWindowMap) { 7019 WindowState win = windowForClientLocked(mSession, mClient, false); 7020 Slog.i(TAG, "WIN DEATH: " + win); 7021 if (win != null) { 7022 removeWindowLocked(mSession, win); 7023 } 7024 } 7025 } catch (IllegalArgumentException ex) { 7026 // This will happen if the window has already been 7027 // removed. 7028 } 7029 } 7030 } 7031 7032 /** Returns true if this window desires key events. */ 7033 public final boolean canReceiveKeys() { 7034 return isVisibleOrAdding() 7035 && (mViewVisibility == View.VISIBLE) 7036 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0); 7037 } 7038 7039 public boolean hasDrawnLw() { 7040 return mHasDrawn; 7041 } 7042 7043 public boolean showLw(boolean doAnimation) { 7044 return showLw(doAnimation, true); 7045 } 7046 7047 boolean showLw(boolean doAnimation, boolean requestAnim) { 7048 if (mPolicyVisibility && mPolicyVisibilityAfterAnim) { 7049 return false; 7050 } 7051 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this); 7052 if (doAnimation) { 7053 if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility=" 7054 + mPolicyVisibility + " mAnimation=" + mAnimation); 7055 if (mDisplayFrozen || !mPolicy.isScreenOn()) { 7056 doAnimation = false; 7057 } else if (mPolicyVisibility && mAnimation == null) { 7058 // Check for the case where we are currently visible and 7059 // not animating; we do not want to do animation at such a 7060 // point to become visible when we already are. 7061 doAnimation = false; 7062 } 7063 } 7064 mPolicyVisibility = true; 7065 mPolicyVisibilityAfterAnim = true; 7066 if (doAnimation) { 7067 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true); 7068 } 7069 if (requestAnim) { 7070 requestAnimationLocked(0); 7071 } 7072 return true; 7073 } 7074 7075 public boolean hideLw(boolean doAnimation) { 7076 return hideLw(doAnimation, true); 7077 } 7078 7079 boolean hideLw(boolean doAnimation, boolean requestAnim) { 7080 if (doAnimation) { 7081 if (mDisplayFrozen || !mPolicy.isScreenOn()) { 7082 doAnimation = false; 7083 } 7084 } 7085 boolean current = doAnimation ? mPolicyVisibilityAfterAnim 7086 : mPolicyVisibility; 7087 if (!current) { 7088 return false; 7089 } 7090 if (doAnimation) { 7091 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false); 7092 if (mAnimation == null) { 7093 doAnimation = false; 7094 } 7095 } 7096 if (doAnimation) { 7097 mPolicyVisibilityAfterAnim = false; 7098 } else { 7099 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this); 7100 mPolicyVisibilityAfterAnim = false; 7101 mPolicyVisibility = false; 7102 // Window is no longer visible -- make sure if we were waiting 7103 // for it to be displayed before enabling the display, that 7104 // we allow the display to be enabled now. 7105 enableScreenIfNeededLocked(); 7106 if (mCurrentFocus == this) { 7107 mFocusMayChange = true; 7108 } 7109 } 7110 if (requestAnim) { 7111 requestAnimationLocked(0); 7112 } 7113 return true; 7114 } 7115 7116 void dump(PrintWriter pw, String prefix) { 7117 pw.print(prefix); pw.print("mSession="); pw.print(mSession); 7118 pw.print(" mClient="); pw.println(mClient.asBinder()); 7119 pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs); 7120 if (mAttachedWindow != null || mLayoutAttached) { 7121 pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow); 7122 pw.print(" mLayoutAttached="); pw.println(mLayoutAttached); 7123 } 7124 if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) { 7125 pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow); 7126 pw.print(" mIsWallpaper="); pw.print(mIsWallpaper); 7127 pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer); 7128 pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible); 7129 } 7130 pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer); 7131 pw.print(" mSubLayer="); pw.print(mSubLayer); 7132 pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+"); 7133 pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment 7134 : (mAppToken != null ? mAppToken.animLayerAdjustment : 0))); 7135 pw.print("="); pw.print(mAnimLayer); 7136 pw.print(" mLastLayer="); pw.println(mLastLayer); 7137 if (mSurface != null) { 7138 pw.print(prefix); pw.print("mSurface="); pw.println(mSurface); 7139 pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown); 7140 pw.print(" layer="); pw.print(mSurfaceLayer); 7141 pw.print(" alpha="); pw.print(mSurfaceAlpha); 7142 pw.print(" rect=("); pw.print(mSurfaceX); 7143 pw.print(","); pw.print(mSurfaceY); 7144 pw.print(") "); pw.print(mSurfaceW); 7145 pw.print(" x "); pw.println(mSurfaceH); 7146 } 7147 pw.print(prefix); pw.print("mToken="); pw.println(mToken); 7148 pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken); 7149 if (mAppToken != null) { 7150 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken); 7151 } 7152 if (mTargetAppToken != null) { 7153 pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken); 7154 } 7155 pw.print(prefix); pw.print("mViewVisibility=0x"); 7156 pw.print(Integer.toHexString(mViewVisibility)); 7157 pw.print(" mLastHidden="); pw.print(mLastHidden); 7158 pw.print(" mHaveFrame="); pw.print(mHaveFrame); 7159 pw.print(" mObscured="); pw.println(mObscured); 7160 if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) { 7161 pw.print(prefix); pw.print("mPolicyVisibility="); 7162 pw.print(mPolicyVisibility); 7163 pw.print(" mPolicyVisibilityAfterAnim="); 7164 pw.print(mPolicyVisibilityAfterAnim); 7165 pw.print(" mAttachedHidden="); pw.println(mAttachedHidden); 7166 } 7167 if (!mRelayoutCalled) { 7168 pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled); 7169 } 7170 pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth); 7171 pw.print(" h="); pw.print(mRequestedHeight); 7172 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 7173 if (mXOffset != 0 || mYOffset != 0) { 7174 pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset); 7175 pw.print(" y="); pw.println(mYOffset); 7176 } 7177 pw.print(prefix); pw.print("mGivenContentInsets="); 7178 mGivenContentInsets.printShortString(pw); 7179 pw.print(" mGivenVisibleInsets="); 7180 mGivenVisibleInsets.printShortString(pw); 7181 pw.println(); 7182 if (mTouchableInsets != 0 || mGivenInsetsPending) { 7183 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets); 7184 pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending); 7185 } 7186 pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration); 7187 pw.print(prefix); pw.print("mShownFrame="); 7188 mShownFrame.printShortString(pw); 7189 pw.print(" last="); mLastShownFrame.printShortString(pw); 7190 pw.println(); 7191 pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw); 7192 pw.print(" last="); mLastFrame.printShortString(pw); 7193 pw.println(); 7194 pw.print(prefix); pw.print("mContainingFrame="); 7195 mContainingFrame.printShortString(pw); 7196 pw.print(" mDisplayFrame="); 7197 mDisplayFrame.printShortString(pw); 7198 pw.println(); 7199 pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw); 7200 pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw); 7201 pw.println(); 7202 pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw); 7203 pw.print(" last="); mLastContentInsets.printShortString(pw); 7204 pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw); 7205 pw.print(" last="); mLastVisibleInsets.printShortString(pw); 7206 pw.println(); 7207 if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) { 7208 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha); 7209 pw.print(" mAlpha="); pw.print(mAlpha); 7210 pw.print(" mLastAlpha="); pw.println(mLastAlpha); 7211 } 7212 if (mAnimating || mLocalAnimating || mAnimationIsEntrance 7213 || mAnimation != null) { 7214 pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating); 7215 pw.print(" mLocalAnimating="); pw.print(mLocalAnimating); 7216 pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance); 7217 pw.print(" mAnimation="); pw.println(mAnimation); 7218 } 7219 if (mHasTransformation || mHasLocalTransformation) { 7220 pw.print(prefix); pw.print("XForm: has="); 7221 pw.print(mHasTransformation); 7222 pw.print(" hasLocal="); pw.print(mHasLocalTransformation); 7223 pw.print(" "); mTransformation.printShortString(pw); 7224 pw.println(); 7225 } 7226 pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending); 7227 pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending); 7228 pw.print(" mReadyToShow="); pw.print(mReadyToShow); 7229 pw.print(" mHasDrawn="); pw.println(mHasDrawn); 7230 if (mExiting || mRemoveOnExit || mDestroying || mRemoved) { 7231 pw.print(prefix); pw.print("mExiting="); pw.print(mExiting); 7232 pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit); 7233 pw.print(" mDestroying="); pw.print(mDestroying); 7234 pw.print(" mRemoved="); pw.println(mRemoved); 7235 } 7236 if (mOrientationChanging || mAppFreezing || mTurnOnScreen) { 7237 pw.print(prefix); pw.print("mOrientationChanging="); 7238 pw.print(mOrientationChanging); 7239 pw.print(" mAppFreezing="); pw.print(mAppFreezing); 7240 pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen); 7241 } 7242 if (mHScale != 1 || mVScale != 1) { 7243 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale); 7244 pw.print(" mVScale="); pw.println(mVScale); 7245 } 7246 if (mWallpaperX != -1 || mWallpaperY != -1) { 7247 pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX); 7248 pw.print(" mWallpaperY="); pw.println(mWallpaperY); 7249 } 7250 if (mWallpaperXStep != -1 || mWallpaperYStep != -1) { 7251 pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep); 7252 pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep); 7253 } 7254 } 7255 7256 String makeInputChannelName() { 7257 return Integer.toHexString(System.identityHashCode(this)) 7258 + " " + mAttrs.getTitle(); 7259 } 7260 7261 @Override 7262 public String toString() { 7263 return "Window{" 7264 + Integer.toHexString(System.identityHashCode(this)) 7265 + " " + mAttrs.getTitle() + " paused=" + mToken.paused + "}"; 7266 } 7267 } 7268 7269 // ------------------------------------------------------------- 7270 // Window Token State 7271 // ------------------------------------------------------------- 7272 7273 class WindowToken { 7274 // The actual token. 7275 final IBinder token; 7276 7277 // The type of window this token is for, as per WindowManager.LayoutParams. 7278 final int windowType; 7279 7280 // Set if this token was explicitly added by a client, so should 7281 // not be removed when all windows are removed. 7282 final boolean explicit; 7283 7284 // For printing. 7285 String stringName; 7286 7287 // If this is an AppWindowToken, this is non-null. 7288 AppWindowToken appWindowToken; 7289 7290 // All of the windows associated with this token. 7291 final ArrayList<WindowState> windows = new ArrayList<WindowState>(); 7292 7293 // Is key dispatching paused for this token? 7294 boolean paused = false; 7295 7296 // Should this token's windows be hidden? 7297 boolean hidden; 7298 7299 // Temporary for finding which tokens no longer have visible windows. 7300 boolean hasVisible; 7301 7302 // Set to true when this token is in a pending transaction where it 7303 // will be shown. 7304 boolean waitingToShow; 7305 7306 // Set to true when this token is in a pending transaction where it 7307 // will be hidden. 7308 boolean waitingToHide; 7309 7310 // Set to true when this token is in a pending transaction where its 7311 // windows will be put to the bottom of the list. 7312 boolean sendingToBottom; 7313 7314 // Set to true when this token is in a pending transaction where its 7315 // windows will be put to the top of the list. 7316 boolean sendingToTop; 7317 7318 WindowToken(IBinder _token, int type, boolean _explicit) { 7319 token = _token; 7320 windowType = type; 7321 explicit = _explicit; 7322 } 7323 7324 void dump(PrintWriter pw, String prefix) { 7325 pw.print(prefix); pw.print("token="); pw.println(token); 7326 pw.print(prefix); pw.print("windows="); pw.println(windows); 7327 pw.print(prefix); pw.print("windowType="); pw.print(windowType); 7328 pw.print(" hidden="); pw.print(hidden); 7329 pw.print(" hasVisible="); pw.println(hasVisible); 7330 if (waitingToShow || waitingToHide || sendingToBottom || sendingToTop) { 7331 pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow); 7332 pw.print(" waitingToHide="); pw.print(waitingToHide); 7333 pw.print(" sendingToBottom="); pw.print(sendingToBottom); 7334 pw.print(" sendingToTop="); pw.println(sendingToTop); 7335 } 7336 } 7337 7338 @Override 7339 public String toString() { 7340 if (stringName == null) { 7341 StringBuilder sb = new StringBuilder(); 7342 sb.append("WindowToken{"); 7343 sb.append(Integer.toHexString(System.identityHashCode(this))); 7344 sb.append(" token="); sb.append(token); sb.append('}'); 7345 stringName = sb.toString(); 7346 } 7347 return stringName; 7348 } 7349 }; 7350 7351 class AppWindowToken extends WindowToken { 7352 // Non-null only for application tokens. 7353 final IApplicationToken appToken; 7354 7355 // All of the windows and child windows that are included in this 7356 // application token. Note this list is NOT sorted! 7357 final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>(); 7358 7359 int groupId = -1; 7360 boolean appFullscreen; 7361 int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 7362 7363 // The input dispatching timeout for this application token in nanoseconds. 7364 long inputDispatchingTimeoutNanos; 7365 7366 // These are used for determining when all windows associated with 7367 // an activity have been drawn, so they can be made visible together 7368 // at the same time. 7369 int lastTransactionSequence = mTransactionSequence-1; 7370 int numInterestingWindows; 7371 int numDrawnWindows; 7372 boolean inPendingTransaction; 7373 boolean allDrawn; 7374 7375 // Is this token going to be hidden in a little while? If so, it 7376 // won't be taken into account for setting the screen orientation. 7377 boolean willBeHidden; 7378 7379 // Is this window's surface needed? This is almost like hidden, except 7380 // it will sometimes be true a little earlier: when the token has 7381 // been shown, but is still waiting for its app transition to execute 7382 // before making its windows shown. 7383 boolean hiddenRequested; 7384 7385 // Have we told the window clients to hide themselves? 7386 boolean clientHidden; 7387 7388 // Last visibility state we reported to the app token. 7389 boolean reportedVisible; 7390 7391 // Set to true when the token has been removed from the window mgr. 7392 boolean removed; 7393 7394 // Have we been asked to have this token keep the screen frozen? 7395 boolean freezingScreen; 7396 7397 boolean animating; 7398 Animation animation; 7399 boolean hasTransformation; 7400 final Transformation transformation = new Transformation(); 7401 7402 // Offset to the window of all layers in the token, for use by 7403 // AppWindowToken animations. 7404 int animLayerAdjustment; 7405 7406 // Information about an application starting window if displayed. 7407 StartingData startingData; 7408 WindowState startingWindow; 7409 View startingView; 7410 boolean startingDisplayed; 7411 boolean startingMoved; 7412 boolean firstWindowDrawn; 7413 7414 AppWindowToken(IApplicationToken _token) { 7415 super(_token.asBinder(), 7416 WindowManager.LayoutParams.TYPE_APPLICATION, true); 7417 appWindowToken = this; 7418 appToken = _token; 7419 } 7420 7421 public void setAnimation(Animation anim) { 7422 if (localLOGV) Slog.v( 7423 TAG, "Setting animation in " + this + ": " + anim); 7424 animation = anim; 7425 animating = false; 7426 anim.restrictDuration(MAX_ANIMATION_DURATION); 7427 anim.scaleCurrentDuration(mTransitionAnimationScale); 7428 int zorder = anim.getZAdjustment(); 7429 int adj = 0; 7430 if (zorder == Animation.ZORDER_TOP) { 7431 adj = TYPE_LAYER_OFFSET; 7432 } else if (zorder == Animation.ZORDER_BOTTOM) { 7433 adj = -TYPE_LAYER_OFFSET; 7434 } 7435 7436 if (animLayerAdjustment != adj) { 7437 animLayerAdjustment = adj; 7438 updateLayers(); 7439 } 7440 } 7441 7442 public void setDummyAnimation() { 7443 if (animation == null) { 7444 if (localLOGV) Slog.v( 7445 TAG, "Setting dummy animation in " + this); 7446 animation = sDummyAnimation; 7447 } 7448 } 7449 7450 public void clearAnimation() { 7451 if (animation != null) { 7452 animation = null; 7453 animating = true; 7454 } 7455 } 7456 7457 void updateLayers() { 7458 final int N = allAppWindows.size(); 7459 final int adj = animLayerAdjustment; 7460 for (int i=0; i<N; i++) { 7461 WindowState w = allAppWindows.get(i); 7462 w.mAnimLayer = w.mLayer + adj; 7463 if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": " 7464 + w.mAnimLayer); 7465 if (w == mInputMethodTarget) { 7466 setInputMethodAnimLayerAdjustment(adj); 7467 } 7468 if (w == mWallpaperTarget && mLowerWallpaperTarget == null) { 7469 setWallpaperAnimLayerAdjustmentLocked(adj); 7470 } 7471 } 7472 } 7473 7474 void sendAppVisibilityToClients() { 7475 final int N = allAppWindows.size(); 7476 for (int i=0; i<N; i++) { 7477 WindowState win = allAppWindows.get(i); 7478 if (win == startingWindow && clientHidden) { 7479 // Don't hide the starting window. 7480 continue; 7481 } 7482 try { 7483 if (DEBUG_VISIBILITY) Slog.v(TAG, 7484 "Setting visibility of " + win + ": " + (!clientHidden)); 7485 win.mClient.dispatchAppVisibility(!clientHidden); 7486 } catch (RemoteException e) { 7487 } 7488 } 7489 } 7490 7491 void showAllWindowsLocked() { 7492 final int NW = allAppWindows.size(); 7493 for (int i=0; i<NW; i++) { 7494 WindowState w = allAppWindows.get(i); 7495 if (DEBUG_VISIBILITY) Slog.v(TAG, 7496 "performing show on: " + w); 7497 w.performShowLocked(); 7498 } 7499 } 7500 7501 // This must be called while inside a transaction. 7502 boolean stepAnimationLocked(long currentTime, int dw, int dh) { 7503 if (!mDisplayFrozen && mPolicy.isScreenOn()) { 7504 // We will run animations as long as the display isn't frozen. 7505 7506 if (animation == sDummyAnimation) { 7507 // This guy is going to animate, but not yet. For now count 7508 // it as not animating for purposes of scheduling transactions; 7509 // when it is really time to animate, this will be set to 7510 // a real animation and the next call will execute normally. 7511 return false; 7512 } 7513 7514 if ((allDrawn || animating || startingDisplayed) && animation != null) { 7515 if (!animating) { 7516 if (DEBUG_ANIM) Slog.v( 7517 TAG, "Starting animation in " + this + 7518 " @ " + currentTime + ": dw=" + dw + " dh=" + dh 7519 + " scale=" + mTransitionAnimationScale 7520 + " allDrawn=" + allDrawn + " animating=" + animating); 7521 animation.initialize(dw, dh, dw, dh); 7522 animation.setStartTime(currentTime); 7523 animating = true; 7524 } 7525 transformation.clear(); 7526 final boolean more = animation.getTransformation( 7527 currentTime, transformation); 7528 if (DEBUG_ANIM) Slog.v( 7529 TAG, "Stepped animation in " + this + 7530 ": more=" + more + ", xform=" + transformation); 7531 if (more) { 7532 // we're done! 7533 hasTransformation = true; 7534 return true; 7535 } 7536 if (DEBUG_ANIM) Slog.v( 7537 TAG, "Finished animation in " + this + 7538 " @ " + currentTime); 7539 animation = null; 7540 } 7541 } else if (animation != null) { 7542 // If the display is frozen, and there is a pending animation, 7543 // clear it and make sure we run the cleanup code. 7544 animating = true; 7545 animation = null; 7546 } 7547 7548 hasTransformation = false; 7549 7550 if (!animating) { 7551 return false; 7552 } 7553 7554 clearAnimation(); 7555 animating = false; 7556 if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == this) { 7557 moveInputMethodWindowsIfNeededLocked(true); 7558 } 7559 7560 if (DEBUG_ANIM) Slog.v( 7561 TAG, "Animation done in " + this 7562 + ": reportedVisible=" + reportedVisible); 7563 7564 transformation.clear(); 7565 if (animLayerAdjustment != 0) { 7566 animLayerAdjustment = 0; 7567 updateLayers(); 7568 } 7569 7570 final int N = windows.size(); 7571 for (int i=0; i<N; i++) { 7572 windows.get(i).finishExit(); 7573 } 7574 updateReportedVisibilityLocked(); 7575 7576 return false; 7577 } 7578 7579 void updateReportedVisibilityLocked() { 7580 if (appToken == null) { 7581 return; 7582 } 7583 7584 int numInteresting = 0; 7585 int numVisible = 0; 7586 boolean nowGone = true; 7587 7588 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this); 7589 final int N = allAppWindows.size(); 7590 for (int i=0; i<N; i++) { 7591 WindowState win = allAppWindows.get(i); 7592 if (win == startingWindow || win.mAppFreezing 7593 || win.mViewVisibility != View.VISIBLE 7594 || win.mAttrs.type == TYPE_APPLICATION_STARTING) { 7595 continue; 7596 } 7597 if (DEBUG_VISIBILITY) { 7598 Slog.v(TAG, "Win " + win + ": isDrawn=" 7599 + win.isDrawnLw() 7600 + ", isAnimating=" + win.isAnimating()); 7601 if (!win.isDrawnLw()) { 7602 Slog.v(TAG, "Not displayed: s=" + win.mSurface 7603 + " pv=" + win.mPolicyVisibility 7604 + " dp=" + win.mDrawPending 7605 + " cdp=" + win.mCommitDrawPending 7606 + " ah=" + win.mAttachedHidden 7607 + " th=" 7608 + (win.mAppToken != null 7609 ? win.mAppToken.hiddenRequested : false) 7610 + " a=" + win.mAnimating); 7611 } 7612 } 7613 numInteresting++; 7614 if (win.isDrawnLw()) { 7615 if (!win.isAnimating()) { 7616 numVisible++; 7617 } 7618 nowGone = false; 7619 } else if (win.isAnimating()) { 7620 nowGone = false; 7621 } 7622 } 7623 7624 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting; 7625 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting=" 7626 + numInteresting + " visible=" + numVisible); 7627 if (nowVisible != reportedVisible) { 7628 if (DEBUG_VISIBILITY) Slog.v( 7629 TAG, "Visibility changed in " + this 7630 + ": vis=" + nowVisible); 7631 reportedVisible = nowVisible; 7632 Message m = mH.obtainMessage( 7633 H.REPORT_APPLICATION_TOKEN_WINDOWS, 7634 nowVisible ? 1 : 0, 7635 nowGone ? 1 : 0, 7636 this); 7637 mH.sendMessage(m); 7638 } 7639 } 7640 7641 WindowState findMainWindow() { 7642 int j = windows.size(); 7643 while (j > 0) { 7644 j--; 7645 WindowState win = windows.get(j); 7646 if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION 7647 || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { 7648 return win; 7649 } 7650 } 7651 return null; 7652 } 7653 7654 void dump(PrintWriter pw, String prefix) { 7655 super.dump(pw, prefix); 7656 if (appToken != null) { 7657 pw.print(prefix); pw.println("app=true"); 7658 } 7659 if (allAppWindows.size() > 0) { 7660 pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows); 7661 } 7662 pw.print(prefix); pw.print("groupId="); pw.print(groupId); 7663 pw.print(" appFullscreen="); pw.print(appFullscreen); 7664 pw.print(" requestedOrientation="); pw.println(requestedOrientation); 7665 pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested); 7666 pw.print(" clientHidden="); pw.print(clientHidden); 7667 pw.print(" willBeHidden="); pw.print(willBeHidden); 7668 pw.print(" reportedVisible="); pw.println(reportedVisible); 7669 if (paused || freezingScreen) { 7670 pw.print(prefix); pw.print("paused="); pw.print(paused); 7671 pw.print(" freezingScreen="); pw.println(freezingScreen); 7672 } 7673 if (numInterestingWindows != 0 || numDrawnWindows != 0 7674 || inPendingTransaction || allDrawn) { 7675 pw.print(prefix); pw.print("numInterestingWindows="); 7676 pw.print(numInterestingWindows); 7677 pw.print(" numDrawnWindows="); pw.print(numDrawnWindows); 7678 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction); 7679 pw.print(" allDrawn="); pw.println(allDrawn); 7680 } 7681 if (animating || animation != null) { 7682 pw.print(prefix); pw.print("animating="); pw.print(animating); 7683 pw.print(" animation="); pw.println(animation); 7684 } 7685 if (animLayerAdjustment != 0) { 7686 pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment); 7687 } 7688 if (hasTransformation) { 7689 pw.print(prefix); pw.print("hasTransformation="); pw.print(hasTransformation); 7690 pw.print(" transformation="); transformation.printShortString(pw); 7691 pw.println(); 7692 } 7693 if (startingData != null || removed || firstWindowDrawn) { 7694 pw.print(prefix); pw.print("startingData="); pw.print(startingData); 7695 pw.print(" removed="); pw.print(removed); 7696 pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn); 7697 } 7698 if (startingWindow != null || startingView != null 7699 || startingDisplayed || startingMoved) { 7700 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow); 7701 pw.print(" startingView="); pw.print(startingView); 7702 pw.print(" startingDisplayed="); pw.print(startingDisplayed); 7703 pw.print(" startingMoved"); pw.println(startingMoved); 7704 } 7705 } 7706 7707 @Override 7708 public String toString() { 7709 if (stringName == null) { 7710 StringBuilder sb = new StringBuilder(); 7711 sb.append("AppWindowToken{"); 7712 sb.append(Integer.toHexString(System.identityHashCode(this))); 7713 sb.append(" token="); sb.append(token); sb.append('}'); 7714 stringName = sb.toString(); 7715 } 7716 return stringName; 7717 } 7718 } 7719 7720 // ------------------------------------------------------------- 7721 // DummyAnimation 7722 // ------------------------------------------------------------- 7723 7724 // This is an animation that does nothing: it just immediately finishes 7725 // itself every time it is called. It is used as a stub animation in cases 7726 // where we want to synchronize multiple things that may be animating. 7727 static final class DummyAnimation extends Animation { 7728 public boolean getTransformation(long currentTime, Transformation outTransformation) { 7729 return false; 7730 } 7731 } 7732 static final Animation sDummyAnimation = new DummyAnimation(); 7733 7734 // ------------------------------------------------------------- 7735 // Async Handler 7736 // ------------------------------------------------------------- 7737 7738 static final class StartingData { 7739 final String pkg; 7740 final int theme; 7741 final CharSequence nonLocalizedLabel; 7742 final int labelRes; 7743 final int icon; 7744 7745 StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel, 7746 int _labelRes, int _icon) { 7747 pkg = _pkg; 7748 theme = _theme; 7749 nonLocalizedLabel = _nonLocalizedLabel; 7750 labelRes = _labelRes; 7751 icon = _icon; 7752 } 7753 } 7754 7755 private final class H extends Handler { 7756 public static final int REPORT_FOCUS_CHANGE = 2; 7757 public static final int REPORT_LOSING_FOCUS = 3; 7758 public static final int ANIMATE = 4; 7759 public static final int ADD_STARTING = 5; 7760 public static final int REMOVE_STARTING = 6; 7761 public static final int FINISHED_STARTING = 7; 7762 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 7763 public static final int WINDOW_FREEZE_TIMEOUT = 11; 7764 public static final int HOLD_SCREEN_CHANGED = 12; 7765 public static final int APP_TRANSITION_TIMEOUT = 13; 7766 public static final int PERSIST_ANIMATION_SCALE = 14; 7767 public static final int FORCE_GC = 15; 7768 public static final int ENABLE_SCREEN = 16; 7769 public static final int APP_FREEZE_TIMEOUT = 17; 7770 public static final int SEND_NEW_CONFIGURATION = 18; 7771 public static final int REPORT_WINDOWS_CHANGE = 19; 7772 7773 private Session mLastReportedHold; 7774 7775 public H() { 7776 } 7777 7778 @Override 7779 public void handleMessage(Message msg) { 7780 switch (msg.what) { 7781 case REPORT_FOCUS_CHANGE: { 7782 WindowState lastFocus; 7783 WindowState newFocus; 7784 7785 synchronized(mWindowMap) { 7786 lastFocus = mLastFocus; 7787 newFocus = mCurrentFocus; 7788 if (lastFocus == newFocus) { 7789 // Focus is not changing, so nothing to do. 7790 return; 7791 } 7792 mLastFocus = newFocus; 7793 //Slog.i(TAG, "Focus moving from " + lastFocus 7794 // + " to " + newFocus); 7795 if (newFocus != null && lastFocus != null 7796 && !newFocus.isDisplayedLw()) { 7797 //Slog.i(TAG, "Delaying loss of focus..."); 7798 mLosingFocus.add(lastFocus); 7799 lastFocus = null; 7800 } 7801 } 7802 7803 if (lastFocus != newFocus) { 7804 //System.out.println("Changing focus from " + lastFocus 7805 // + " to " + newFocus); 7806 if (newFocus != null) { 7807 try { 7808 //Slog.i(TAG, "Gaining focus: " + newFocus); 7809 newFocus.mClient.windowFocusChanged(true, mInTouchMode); 7810 } catch (RemoteException e) { 7811 // Ignore if process has died. 7812 } 7813 notifyFocusChanged(); 7814 } 7815 7816 if (lastFocus != null) { 7817 try { 7818 //Slog.i(TAG, "Losing focus: " + lastFocus); 7819 lastFocus.mClient.windowFocusChanged(false, mInTouchMode); 7820 } catch (RemoteException e) { 7821 // Ignore if process has died. 7822 } 7823 } 7824 } 7825 } break; 7826 7827 case REPORT_LOSING_FOCUS: { 7828 ArrayList<WindowState> losers; 7829 7830 synchronized(mWindowMap) { 7831 losers = mLosingFocus; 7832 mLosingFocus = new ArrayList<WindowState>(); 7833 } 7834 7835 final int N = losers.size(); 7836 for (int i=0; i<N; i++) { 7837 try { 7838 //Slog.i(TAG, "Losing delayed focus: " + losers.get(i)); 7839 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode); 7840 } catch (RemoteException e) { 7841 // Ignore if process has died. 7842 } 7843 } 7844 } break; 7845 7846 case ANIMATE: { 7847 synchronized(mWindowMap) { 7848 mAnimationPending = false; 7849 performLayoutAndPlaceSurfacesLocked(); 7850 } 7851 } break; 7852 7853 case ADD_STARTING: { 7854 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7855 final StartingData sd = wtoken.startingData; 7856 7857 if (sd == null) { 7858 // Animation has been canceled... do nothing. 7859 return; 7860 } 7861 7862 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 7863 + wtoken + ": pkg=" + sd.pkg); 7864 7865 View view = null; 7866 try { 7867 view = mPolicy.addStartingWindow( 7868 wtoken.token, sd.pkg, 7869 sd.theme, sd.nonLocalizedLabel, sd.labelRes, 7870 sd.icon); 7871 } catch (Exception e) { 7872 Slog.w(TAG, "Exception when adding starting window", e); 7873 } 7874 7875 if (view != null) { 7876 boolean abort = false; 7877 7878 synchronized(mWindowMap) { 7879 if (wtoken.removed || wtoken.startingData == null) { 7880 // If the window was successfully added, then 7881 // we need to remove it. 7882 if (wtoken.startingWindow != null) { 7883 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7884 "Aborted starting " + wtoken 7885 + ": removed=" + wtoken.removed 7886 + " startingData=" + wtoken.startingData); 7887 wtoken.startingWindow = null; 7888 wtoken.startingData = null; 7889 abort = true; 7890 } 7891 } else { 7892 wtoken.startingView = view; 7893 } 7894 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7895 "Added starting " + wtoken 7896 + ": startingWindow=" 7897 + wtoken.startingWindow + " startingView=" 7898 + wtoken.startingView); 7899 } 7900 7901 if (abort) { 7902 try { 7903 mPolicy.removeStartingWindow(wtoken.token, view); 7904 } catch (Exception e) { 7905 Slog.w(TAG, "Exception when removing starting window", e); 7906 } 7907 } 7908 } 7909 } break; 7910 7911 case REMOVE_STARTING: { 7912 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7913 IBinder token = null; 7914 View view = null; 7915 synchronized (mWindowMap) { 7916 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7917 + wtoken + ": startingWindow=" 7918 + wtoken.startingWindow + " startingView=" 7919 + wtoken.startingView); 7920 if (wtoken.startingWindow != null) { 7921 view = wtoken.startingView; 7922 token = wtoken.token; 7923 wtoken.startingData = null; 7924 wtoken.startingView = null; 7925 wtoken.startingWindow = null; 7926 } 7927 } 7928 if (view != null) { 7929 try { 7930 mPolicy.removeStartingWindow(token, view); 7931 } catch (Exception e) { 7932 Slog.w(TAG, "Exception when removing starting window", e); 7933 } 7934 } 7935 } break; 7936 7937 case FINISHED_STARTING: { 7938 IBinder token = null; 7939 View view = null; 7940 while (true) { 7941 synchronized (mWindowMap) { 7942 final int N = mFinishedStarting.size(); 7943 if (N <= 0) { 7944 break; 7945 } 7946 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7947 7948 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7949 "Finished starting " + wtoken 7950 + ": startingWindow=" + wtoken.startingWindow 7951 + " startingView=" + wtoken.startingView); 7952 7953 if (wtoken.startingWindow == null) { 7954 continue; 7955 } 7956 7957 view = wtoken.startingView; 7958 token = wtoken.token; 7959 wtoken.startingData = null; 7960 wtoken.startingView = null; 7961 wtoken.startingWindow = null; 7962 } 7963 7964 try { 7965 mPolicy.removeStartingWindow(token, view); 7966 } catch (Exception e) { 7967 Slog.w(TAG, "Exception when removing starting window", e); 7968 } 7969 } 7970 } break; 7971 7972 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7973 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7974 7975 boolean nowVisible = msg.arg1 != 0; 7976 boolean nowGone = msg.arg2 != 0; 7977 7978 try { 7979 if (DEBUG_VISIBILITY) Slog.v( 7980 TAG, "Reporting visible in " + wtoken 7981 + " visible=" + nowVisible 7982 + " gone=" + nowGone); 7983 if (nowVisible) { 7984 wtoken.appToken.windowsVisible(); 7985 } else { 7986 wtoken.appToken.windowsGone(); 7987 } 7988 } catch (RemoteException ex) { 7989 } 7990 } break; 7991 7992 case WINDOW_FREEZE_TIMEOUT: { 7993 synchronized (mWindowMap) { 7994 Slog.w(TAG, "Window freeze timeout expired."); 7995 int i = mWindows.size(); 7996 while (i > 0) { 7997 i--; 7998 WindowState w = mWindows.get(i); 7999 if (w.mOrientationChanging) { 8000 w.mOrientationChanging = false; 8001 Slog.w(TAG, "Force clearing orientation change: " + w); 8002 } 8003 } 8004 performLayoutAndPlaceSurfacesLocked(); 8005 } 8006 break; 8007 } 8008 8009 case HOLD_SCREEN_CHANGED: { 8010 Session oldHold; 8011 Session newHold; 8012 synchronized (mWindowMap) { 8013 oldHold = mLastReportedHold; 8014 newHold = (Session)msg.obj; 8015 mLastReportedHold = newHold; 8016 } 8017 8018 if (oldHold != newHold) { 8019 try { 8020 if (oldHold != null) { 8021 mBatteryStats.noteStopWakelock(oldHold.mUid, -1, 8022 "window", 8023 BatteryStats.WAKE_TYPE_WINDOW); 8024 } 8025 if (newHold != null) { 8026 mBatteryStats.noteStartWakelock(newHold.mUid, -1, 8027 "window", 8028 BatteryStats.WAKE_TYPE_WINDOW); 8029 } 8030 } catch (RemoteException e) { 8031 } 8032 } 8033 break; 8034 } 8035 8036 case APP_TRANSITION_TIMEOUT: { 8037 synchronized (mWindowMap) { 8038 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 8039 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8040 "*** APP TRANSITION TIMEOUT"); 8041 mAppTransitionReady = true; 8042 mAppTransitionTimeout = true; 8043 performLayoutAndPlaceSurfacesLocked(); 8044 } 8045 } 8046 break; 8047 } 8048 8049 case PERSIST_ANIMATION_SCALE: { 8050 Settings.System.putFloat(mContext.getContentResolver(), 8051 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); 8052 Settings.System.putFloat(mContext.getContentResolver(), 8053 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); 8054 break; 8055 } 8056 8057 case FORCE_GC: { 8058 synchronized(mWindowMap) { 8059 if (mAnimationPending) { 8060 // If we are animating, don't do the gc now but 8061 // delay a bit so we don't interrupt the animation. 8062 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 8063 2000); 8064 return; 8065 } 8066 // If we are currently rotating the display, it will 8067 // schedule a new message when done. 8068 if (mDisplayFrozen) { 8069 return; 8070 } 8071 mFreezeGcPending = 0; 8072 } 8073 Runtime.getRuntime().gc(); 8074 break; 8075 } 8076 8077 case ENABLE_SCREEN: { 8078 performEnableScreen(); 8079 break; 8080 } 8081 8082 case APP_FREEZE_TIMEOUT: { 8083 synchronized (mWindowMap) { 8084 Slog.w(TAG, "App freeze timeout expired."); 8085 int i = mAppTokens.size(); 8086 while (i > 0) { 8087 i--; 8088 AppWindowToken tok = mAppTokens.get(i); 8089 if (tok.freezingScreen) { 8090 Slog.w(TAG, "Force clearing freeze: " + tok); 8091 unsetAppFreezingScreenLocked(tok, true, true); 8092 } 8093 } 8094 } 8095 break; 8096 } 8097 8098 case SEND_NEW_CONFIGURATION: { 8099 removeMessages(SEND_NEW_CONFIGURATION); 8100 sendNewConfiguration(); 8101 break; 8102 } 8103 8104 case REPORT_WINDOWS_CHANGE: { 8105 if (mWindowsChanged) { 8106 synchronized (mWindowMap) { 8107 mWindowsChanged = false; 8108 } 8109 notifyWindowsChanged(); 8110 } 8111 break; 8112 } 8113 8114 } 8115 } 8116 } 8117 8118 // ------------------------------------------------------------- 8119 // IWindowManager API 8120 // ------------------------------------------------------------- 8121 8122 public IWindowSession openSession(IInputMethodClient client, 8123 IInputContext inputContext) { 8124 if (client == null) throw new IllegalArgumentException("null client"); 8125 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 8126 Session session = new Session(client, inputContext); 8127 return session; 8128 } 8129 8130 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 8131 synchronized (mWindowMap) { 8132 // The focus for the client is the window immediately below 8133 // where we would place the input method window. 8134 int idx = findDesiredInputMethodWindowIndexLocked(false); 8135 WindowState imFocus; 8136 if (idx > 0) { 8137 imFocus = mWindows.get(idx-1); 8138 if (imFocus != null) { 8139 if (imFocus.mSession.mClient != null && 8140 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 8141 return true; 8142 } 8143 } 8144 } 8145 } 8146 return false; 8147 } 8148 8149 // ------------------------------------------------------------- 8150 // Internals 8151 // ------------------------------------------------------------- 8152 8153 final WindowState windowForClientLocked(Session session, IWindow client, 8154 boolean throwOnError) { 8155 return windowForClientLocked(session, client.asBinder(), throwOnError); 8156 } 8157 8158 final WindowState windowForClientLocked(Session session, IBinder client, 8159 boolean throwOnError) { 8160 WindowState win = mWindowMap.get(client); 8161 if (localLOGV) Slog.v( 8162 TAG, "Looking up client " + client + ": " + win); 8163 if (win == null) { 8164 RuntimeException ex = new IllegalArgumentException( 8165 "Requested window " + client + " does not exist"); 8166 if (throwOnError) { 8167 throw ex; 8168 } 8169 Slog.w(TAG, "Failed looking up window", ex); 8170 return null; 8171 } 8172 if (session != null && win.mSession != session) { 8173 RuntimeException ex = new IllegalArgumentException( 8174 "Requested window " + client + " is in session " + 8175 win.mSession + ", not " + session); 8176 if (throwOnError) { 8177 throw ex; 8178 } 8179 Slog.w(TAG, "Failed looking up window", ex); 8180 return null; 8181 } 8182 8183 return win; 8184 } 8185 8186 final void rebuildAppWindowListLocked() { 8187 int NW = mWindows.size(); 8188 int i; 8189 int lastWallpaper = -1; 8190 int numRemoved = 0; 8191 8192 // First remove all existing app windows. 8193 i=0; 8194 while (i < NW) { 8195 WindowState w = mWindows.get(i); 8196 if (w.mAppToken != null) { 8197 WindowState win = mWindows.remove(i); 8198 mWindowsChanged = true; 8199 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 8200 "Rebuild removing window: " + win); 8201 NW--; 8202 numRemoved++; 8203 continue; 8204 } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER 8205 && lastWallpaper == i-1) { 8206 lastWallpaper = i; 8207 } 8208 i++; 8209 } 8210 8211 // The wallpaper window(s) typically live at the bottom of the stack, 8212 // so skip them before adding app tokens. 8213 lastWallpaper++; 8214 i = lastWallpaper; 8215 8216 // First add all of the exiting app tokens... these are no longer 8217 // in the main app list, but still have windows shown. We put them 8218 // in the back because now that the animation is over we no longer 8219 // will care about them. 8220 int NT = mExitingAppTokens.size(); 8221 for (int j=0; j<NT; j++) { 8222 i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j)); 8223 } 8224 8225 // And add in the still active app tokens in Z order. 8226 NT = mAppTokens.size(); 8227 for (int j=0; j<NT; j++) { 8228 i = reAddAppWindowsLocked(i, mAppTokens.get(j)); 8229 } 8230 8231 i -= lastWallpaper; 8232 if (i != numRemoved) { 8233 Slog.w(TAG, "Rebuild removed " + numRemoved 8234 + " windows but added " + i); 8235 } 8236 } 8237 8238 private final void assignLayersLocked() { 8239 int N = mWindows.size(); 8240 int curBaseLayer = 0; 8241 int curLayer = 0; 8242 int i; 8243 8244 for (i=0; i<N; i++) { 8245 WindowState w = mWindows.get(i); 8246 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 8247 || (i > 0 && w.mIsWallpaper)) { 8248 curLayer += WINDOW_LAYER_MULTIPLIER; 8249 w.mLayer = curLayer; 8250 } else { 8251 curBaseLayer = curLayer = w.mBaseLayer; 8252 w.mLayer = curLayer; 8253 } 8254 if (w.mTargetAppToken != null) { 8255 w.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment; 8256 } else if (w.mAppToken != null) { 8257 w.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment; 8258 } else { 8259 w.mAnimLayer = w.mLayer; 8260 } 8261 if (w.mIsImWindow) { 8262 w.mAnimLayer += mInputMethodAnimLayerAdjustment; 8263 } else if (w.mIsWallpaper) { 8264 w.mAnimLayer += mWallpaperAnimLayerAdjustment; 8265 } 8266 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 8267 + w.mAnimLayer); 8268 //System.out.println( 8269 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 8270 } 8271 } 8272 8273 private boolean mInLayout = false; 8274 private final void performLayoutAndPlaceSurfacesLocked() { 8275 if (mInLayout) { 8276 if (DEBUG) { 8277 throw new RuntimeException("Recursive call!"); 8278 } 8279 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout"); 8280 return; 8281 } 8282 8283 if (mWaitingForConfig) { 8284 // Our configuration has changed (most likely rotation), but we 8285 // don't yet have the complete configuration to report to 8286 // applications. Don't do any window layout until we have it. 8287 return; 8288 } 8289 8290 if (mDisplay == null) { 8291 // Not yet initialized, nothing to do. 8292 return; 8293 } 8294 8295 boolean recoveringMemory = false; 8296 if (mForceRemoves != null) { 8297 recoveringMemory = true; 8298 // Wait a little it for things to settle down, and off we go. 8299 for (int i=0; i<mForceRemoves.size(); i++) { 8300 WindowState ws = mForceRemoves.get(i); 8301 Slog.i(TAG, "Force removing: " + ws); 8302 removeWindowInnerLocked(ws.mSession, ws); 8303 } 8304 mForceRemoves = null; 8305 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 8306 Object tmp = new Object(); 8307 synchronized (tmp) { 8308 try { 8309 tmp.wait(250); 8310 } catch (InterruptedException e) { 8311 } 8312 } 8313 } 8314 8315 mInLayout = true; 8316 try { 8317 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 8318 8319 int i = mPendingRemove.size()-1; 8320 if (i >= 0) { 8321 while (i >= 0) { 8322 WindowState w = mPendingRemove.get(i); 8323 removeWindowInnerLocked(w.mSession, w); 8324 i--; 8325 } 8326 mPendingRemove.clear(); 8327 8328 mInLayout = false; 8329 assignLayersLocked(); 8330 mLayoutNeeded = true; 8331 performLayoutAndPlaceSurfacesLocked(); 8332 8333 } else { 8334 mInLayout = false; 8335 if (mLayoutNeeded) { 8336 requestAnimationLocked(0); 8337 } 8338 } 8339 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 8340 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 8341 mH.sendMessage(mH.obtainMessage(H.REPORT_WINDOWS_CHANGE)); 8342 } 8343 } catch (RuntimeException e) { 8344 mInLayout = false; 8345 Slog.e(TAG, "Unhandled exception while layout out windows", e); 8346 } 8347 } 8348 8349 private final int performLayoutLockedInner() { 8350 if (!mLayoutNeeded) { 8351 return 0; 8352 } 8353 8354 mLayoutNeeded = false; 8355 8356 final int dw = mDisplay.getWidth(); 8357 final int dh = mDisplay.getHeight(); 8358 8359 final int N = mWindows.size(); 8360 int i; 8361 8362 if (DEBUG_LAYOUT) Slog.v(TAG, "performLayout: needed=" 8363 + mLayoutNeeded + " dw=" + dw + " dh=" + dh); 8364 8365 mPolicy.beginLayoutLw(dw, dh); 8366 8367 int seq = mLayoutSeq+1; 8368 if (seq < 0) seq = 0; 8369 mLayoutSeq = seq; 8370 8371 // First perform layout of any root windows (not attached 8372 // to another window). 8373 int topAttached = -1; 8374 for (i = N-1; i >= 0; i--) { 8375 WindowState win = mWindows.get(i); 8376 8377 // Don't do layout of a window if it is not visible, or 8378 // soon won't be visible, to avoid wasting time and funky 8379 // changes while a window is animating away. 8380 final AppWindowToken atoken = win.mAppToken; 8381 final boolean gone = win.mViewVisibility == View.GONE 8382 || !win.mRelayoutCalled 8383 || win.mRootToken.hidden 8384 || (atoken != null && atoken.hiddenRequested) 8385 || win.mAttachedHidden 8386 || win.mExiting || win.mDestroying; 8387 8388 if (!win.mLayoutAttached) { 8389 if (DEBUG_LAYOUT) Slog.v(TAG, "First pass " + win 8390 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 8391 + " mLayoutAttached=" + win.mLayoutAttached); 8392 if (DEBUG_LAYOUT && gone) Slog.v(TAG, " (mViewVisibility=" 8393 + win.mViewVisibility + " mRelayoutCalled=" 8394 + win.mRelayoutCalled + " hidden=" 8395 + win.mRootToken.hidden + " hiddenRequested=" 8396 + (atoken != null && atoken.hiddenRequested) 8397 + " mAttachedHidden=" + win.mAttachedHidden); 8398 } 8399 8400 // If this view is GONE, then skip it -- keep the current 8401 // frame, and let the caller know so they can ignore it 8402 // if they want. (We do the normal layout for INVISIBLE 8403 // windows, since that means "perform layout as normal, 8404 // just don't display"). 8405 if (!gone || !win.mHaveFrame) { 8406 if (!win.mLayoutAttached) { 8407 mPolicy.layoutWindowLw(win, win.mAttrs, null); 8408 win.mLayoutSeq = seq; 8409 if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame=" 8410 + win.mFrame + " mContainingFrame=" 8411 + win.mContainingFrame + " mDisplayFrame=" 8412 + win.mDisplayFrame); 8413 } else { 8414 if (topAttached < 0) topAttached = i; 8415 } 8416 } 8417 } 8418 8419 // Now perform layout of attached windows, which usually 8420 // depend on the position of the window they are attached to. 8421 // XXX does not deal with windows that are attached to windows 8422 // that are themselves attached. 8423 for (i = topAttached; i >= 0; i--) { 8424 WindowState win = mWindows.get(i); 8425 8426 // If this view is GONE, then skip it -- keep the current 8427 // frame, and let the caller know so they can ignore it 8428 // if they want. (We do the normal layout for INVISIBLE 8429 // windows, since that means "perform layout as normal, 8430 // just don't display"). 8431 if (win.mLayoutAttached) { 8432 if (DEBUG_LAYOUT) Slog.v(TAG, "Second pass " + win 8433 + " mHaveFrame=" + win.mHaveFrame 8434 + " mViewVisibility=" + win.mViewVisibility 8435 + " mRelayoutCalled=" + win.mRelayoutCalled); 8436 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8437 || !win.mHaveFrame) { 8438 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 8439 win.mLayoutSeq = seq; 8440 if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame=" 8441 + win.mFrame + " mContainingFrame=" 8442 + win.mContainingFrame + " mDisplayFrame=" 8443 + win.mDisplayFrame); 8444 } 8445 } 8446 } 8447 8448 // Window frames may have changed. Tell the input dispatcher about it. 8449 mInputMonitor.updateInputWindowsLw(); 8450 8451 return mPolicy.finishLayoutLw(); 8452 } 8453 8454 private final void performLayoutAndPlaceSurfacesLockedInner( 8455 boolean recoveringMemory) { 8456 final long currentTime = SystemClock.uptimeMillis(); 8457 final int dw = mDisplay.getWidth(); 8458 final int dh = mDisplay.getHeight(); 8459 8460 int i; 8461 8462 if (mFocusMayChange) { 8463 mFocusMayChange = false; 8464 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES); 8465 } 8466 8467 // Initialize state of exiting tokens. 8468 for (i=mExitingTokens.size()-1; i>=0; i--) { 8469 mExitingTokens.get(i).hasVisible = false; 8470 } 8471 8472 // Initialize state of exiting applications. 8473 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 8474 mExitingAppTokens.get(i).hasVisible = false; 8475 } 8476 8477 boolean orientationChangeComplete = true; 8478 Session holdScreen = null; 8479 float screenBrightness = -1; 8480 float buttonBrightness = -1; 8481 boolean focusDisplayed = false; 8482 boolean animating = false; 8483 boolean createWatermark = false; 8484 8485 if (mFxSession == null) { 8486 mFxSession = new SurfaceSession(); 8487 createWatermark = true; 8488 } 8489 8490 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION"); 8491 8492 Surface.openTransaction(); 8493 8494 if (createWatermark) { 8495 createWatermark(); 8496 } 8497 if (mWatermark != null) { 8498 mWatermark.positionSurface(dw, dh); 8499 } 8500 8501 try { 8502 boolean wallpaperForceHidingChanged = false; 8503 int repeats = 0; 8504 int changes = 0; 8505 8506 do { 8507 repeats++; 8508 if (repeats > 6) { 8509 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 8510 mLayoutNeeded = false; 8511 break; 8512 } 8513 8514 if ((changes&(WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER 8515 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG 8516 | WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT)) != 0) { 8517 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) { 8518 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 8519 assignLayersLocked(); 8520 mLayoutNeeded = true; 8521 } 8522 } 8523 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 8524 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 8525 if (updateOrientationFromAppTokensLocked()) { 8526 mLayoutNeeded = true; 8527 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8528 } 8529 } 8530 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 8531 mLayoutNeeded = true; 8532 } 8533 } 8534 8535 // FIRST LOOP: Perform a layout, if needed. 8536 if (repeats < 4) { 8537 changes = performLayoutLockedInner(); 8538 if (changes != 0) { 8539 continue; 8540 } 8541 } else { 8542 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 8543 changes = 0; 8544 } 8545 8546 final int transactionSequence = ++mTransactionSequence; 8547 8548 // Update animations of all applications, including those 8549 // associated with exiting/removed apps 8550 boolean tokensAnimating = false; 8551 final int NAT = mAppTokens.size(); 8552 for (i=0; i<NAT; i++) { 8553 if (mAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) { 8554 tokensAnimating = true; 8555 } 8556 } 8557 final int NEAT = mExitingAppTokens.size(); 8558 for (i=0; i<NEAT; i++) { 8559 if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) { 8560 tokensAnimating = true; 8561 } 8562 } 8563 8564 // SECOND LOOP: Execute animations and update visibility of windows. 8565 8566 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq=" 8567 + transactionSequence + " tokensAnimating=" 8568 + tokensAnimating); 8569 8570 animating = tokensAnimating; 8571 8572 boolean tokenMayBeDrawn = false; 8573 boolean wallpaperMayChange = false; 8574 boolean forceHiding = false; 8575 8576 mPolicy.beginAnimationLw(dw, dh); 8577 8578 final int N = mWindows.size(); 8579 8580 for (i=N-1; i>=0; i--) { 8581 WindowState w = mWindows.get(i); 8582 8583 final WindowManager.LayoutParams attrs = w.mAttrs; 8584 8585 if (w.mSurface != null) { 8586 // Execute animation. 8587 if (w.commitFinishDrawingLocked(currentTime)) { 8588 if ((w.mAttrs.flags 8589 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { 8590 if (DEBUG_WALLPAPER) Slog.v(TAG, 8591 "First draw done in potential wallpaper target " + w); 8592 wallpaperMayChange = true; 8593 } 8594 } 8595 8596 boolean wasAnimating = w.mAnimating; 8597 if (w.stepAnimationLocked(currentTime, dw, dh)) { 8598 animating = true; 8599 //w.dump(" "); 8600 } 8601 if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) { 8602 wallpaperMayChange = true; 8603 } 8604 8605 if (mPolicy.doesForceHide(w, attrs)) { 8606 if (!wasAnimating && animating) { 8607 if (DEBUG_VISIBILITY) Slog.v(TAG, 8608 "Animation done that could impact force hide: " 8609 + w); 8610 wallpaperForceHidingChanged = true; 8611 mFocusMayChange = true; 8612 } else if (w.isReadyForDisplay() && w.mAnimation == null) { 8613 forceHiding = true; 8614 } 8615 } else if (mPolicy.canBeForceHidden(w, attrs)) { 8616 boolean changed; 8617 if (forceHiding) { 8618 changed = w.hideLw(false, false); 8619 if (DEBUG_VISIBILITY && changed) Slog.v(TAG, 8620 "Now policy hidden: " + w); 8621 } else { 8622 changed = w.showLw(false, false); 8623 if (DEBUG_VISIBILITY && changed) Slog.v(TAG, 8624 "Now policy shown: " + w); 8625 if (changed) { 8626 if (wallpaperForceHidingChanged 8627 && w.isVisibleNow() /*w.isReadyForDisplay()*/) { 8628 // Assume we will need to animate. If 8629 // we don't (because the wallpaper will 8630 // stay with the lock screen), then we will 8631 // clean up later. 8632 Animation a = mPolicy.createForceHideEnterAnimation(); 8633 if (a != null) { 8634 w.setAnimation(a); 8635 } 8636 } 8637 if (mCurrentFocus == null || 8638 mCurrentFocus.mLayer < w.mLayer) { 8639 // We are showing on to of the current 8640 // focus, so re-evaluate focus to make 8641 // sure it is correct. 8642 mFocusMayChange = true; 8643 } 8644 } 8645 } 8646 if (changed && (attrs.flags 8647 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { 8648 wallpaperMayChange = true; 8649 } 8650 } 8651 8652 mPolicy.animatingWindowLw(w, attrs); 8653 } 8654 8655 final AppWindowToken atoken = w.mAppToken; 8656 if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) { 8657 if (atoken.lastTransactionSequence != transactionSequence) { 8658 atoken.lastTransactionSequence = transactionSequence; 8659 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 8660 atoken.startingDisplayed = false; 8661 } 8662 if ((w.isOnScreen() || w.mAttrs.type 8663 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION) 8664 && !w.mExiting && !w.mDestroying) { 8665 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 8666 Slog.v(TAG, "Eval win " + w + ": isDrawn=" 8667 + w.isDrawnLw() 8668 + ", isAnimating=" + w.isAnimating()); 8669 if (!w.isDrawnLw()) { 8670 Slog.v(TAG, "Not displayed: s=" + w.mSurface 8671 + " pv=" + w.mPolicyVisibility 8672 + " dp=" + w.mDrawPending 8673 + " cdp=" + w.mCommitDrawPending 8674 + " ah=" + w.mAttachedHidden 8675 + " th=" + atoken.hiddenRequested 8676 + " a=" + w.mAnimating); 8677 } 8678 } 8679 if (w != atoken.startingWindow) { 8680 if (!atoken.freezingScreen || !w.mAppFreezing) { 8681 atoken.numInterestingWindows++; 8682 if (w.isDrawnLw()) { 8683 atoken.numDrawnWindows++; 8684 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 8685 "tokenMayBeDrawn: " + atoken 8686 + " freezingScreen=" + atoken.freezingScreen 8687 + " mAppFreezing=" + w.mAppFreezing); 8688 tokenMayBeDrawn = true; 8689 } 8690 } 8691 } else if (w.isDrawnLw()) { 8692 atoken.startingDisplayed = true; 8693 } 8694 } 8695 } else if (w.mReadyToShow) { 8696 w.performShowLocked(); 8697 } 8698 } 8699 8700 changes |= mPolicy.finishAnimationLw(); 8701 8702 if (tokenMayBeDrawn) { 8703 // See if any windows have been drawn, so they (and others 8704 // associated with them) can now be shown. 8705 final int NT = mTokenList.size(); 8706 for (i=0; i<NT; i++) { 8707 AppWindowToken wtoken = mTokenList.get(i).appWindowToken; 8708 if (wtoken == null) { 8709 continue; 8710 } 8711 if (wtoken.freezingScreen) { 8712 int numInteresting = wtoken.numInterestingWindows; 8713 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 8714 if (DEBUG_VISIBILITY) Slog.v(TAG, 8715 "allDrawn: " + wtoken 8716 + " interesting=" + numInteresting 8717 + " drawn=" + wtoken.numDrawnWindows); 8718 wtoken.showAllWindowsLocked(); 8719 unsetAppFreezingScreenLocked(wtoken, false, true); 8720 orientationChangeComplete = true; 8721 } 8722 } else if (!wtoken.allDrawn) { 8723 int numInteresting = wtoken.numInterestingWindows; 8724 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 8725 if (DEBUG_VISIBILITY) Slog.v(TAG, 8726 "allDrawn: " + wtoken 8727 + " interesting=" + numInteresting 8728 + " drawn=" + wtoken.numDrawnWindows); 8729 wtoken.allDrawn = true; 8730 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 8731 8732 // We can now show all of the drawn windows! 8733 if (!mOpeningApps.contains(wtoken)) { 8734 wtoken.showAllWindowsLocked(); 8735 } 8736 } 8737 } 8738 } 8739 } 8740 8741 // If we are ready to perform an app transition, check through 8742 // all of the app tokens to be shown and see if they are ready 8743 // to go. 8744 if (mAppTransitionReady) { 8745 int NN = mOpeningApps.size(); 8746 boolean goodToGo = true; 8747 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8748 "Checking " + NN + " opening apps (frozen=" 8749 + mDisplayFrozen + " timeout=" 8750 + mAppTransitionTimeout + ")..."); 8751 if (!mDisplayFrozen && !mAppTransitionTimeout) { 8752 // If the display isn't frozen, wait to do anything until 8753 // all of the apps are ready. Otherwise just go because 8754 // we'll unfreeze the display when everyone is ready. 8755 for (i=0; i<NN && goodToGo; i++) { 8756 AppWindowToken wtoken = mOpeningApps.get(i); 8757 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8758 "Check opening app" + wtoken + ": allDrawn=" 8759 + wtoken.allDrawn + " startingDisplayed=" 8760 + wtoken.startingDisplayed); 8761 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8762 && !wtoken.startingMoved) { 8763 goodToGo = false; 8764 } 8765 } 8766 } 8767 if (goodToGo) { 8768 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8769 int transit = mNextAppTransition; 8770 if (mSkipAppTransitionAnimation) { 8771 transit = WindowManagerPolicy.TRANSIT_UNSET; 8772 } 8773 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 8774 mAppTransitionReady = false; 8775 mAppTransitionRunning = true; 8776 mAppTransitionTimeout = false; 8777 mStartingIconInTransition = false; 8778 mSkipAppTransitionAnimation = false; 8779 8780 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8781 8782 // If there are applications waiting to come to the 8783 // top of the stack, now is the time to move their windows. 8784 // (Note that we don't do apps going to the bottom 8785 // here -- we want to keep their windows in the old 8786 // Z-order until the animation completes.) 8787 if (mToTopApps.size() > 0) { 8788 NN = mAppTokens.size(); 8789 for (i=0; i<NN; i++) { 8790 AppWindowToken wtoken = mAppTokens.get(i); 8791 if (wtoken.sendingToTop) { 8792 wtoken.sendingToTop = false; 8793 moveAppWindowsLocked(wtoken, NN, false); 8794 } 8795 } 8796 mToTopApps.clear(); 8797 } 8798 8799 WindowState oldWallpaper = mWallpaperTarget; 8800 8801 adjustWallpaperWindowsLocked(); 8802 wallpaperMayChange = false; 8803 8804 // The top-most window will supply the layout params, 8805 // and we will determine it below. 8806 LayoutParams animLp = null; 8807 AppWindowToken animToken = null; 8808 int bestAnimLayer = -1; 8809 8810 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8811 "New wallpaper target=" + mWallpaperTarget 8812 + ", lower target=" + mLowerWallpaperTarget 8813 + ", upper target=" + mUpperWallpaperTarget); 8814 int foundWallpapers = 0; 8815 // Do a first pass through the tokens for two 8816 // things: 8817 // (1) Determine if both the closing and opening 8818 // app token sets are wallpaper targets, in which 8819 // case special animations are needed 8820 // (since the wallpaper needs to stay static 8821 // behind them). 8822 // (2) Find the layout params of the top-most 8823 // application window in the tokens, which is 8824 // what will control the animation theme. 8825 final int NC = mClosingApps.size(); 8826 NN = NC + mOpeningApps.size(); 8827 for (i=0; i<NN; i++) { 8828 AppWindowToken wtoken; 8829 int mode; 8830 if (i < NC) { 8831 wtoken = mClosingApps.get(i); 8832 mode = 1; 8833 } else { 8834 wtoken = mOpeningApps.get(i-NC); 8835 mode = 2; 8836 } 8837 if (mLowerWallpaperTarget != null) { 8838 if (mLowerWallpaperTarget.mAppToken == wtoken 8839 || mUpperWallpaperTarget.mAppToken == wtoken) { 8840 foundWallpapers |= mode; 8841 } 8842 } 8843 if (wtoken.appFullscreen) { 8844 WindowState ws = wtoken.findMainWindow(); 8845 if (ws != null) { 8846 // If this is a compatibility mode 8847 // window, we will always use its anim. 8848 if ((ws.mAttrs.flags&FLAG_COMPATIBLE_WINDOW) != 0) { 8849 animLp = ws.mAttrs; 8850 animToken = ws.mAppToken; 8851 bestAnimLayer = Integer.MAX_VALUE; 8852 } else if (ws.mLayer > bestAnimLayer) { 8853 animLp = ws.mAttrs; 8854 animToken = ws.mAppToken; 8855 bestAnimLayer = ws.mLayer; 8856 } 8857 } 8858 } 8859 } 8860 8861 if (foundWallpapers == 3) { 8862 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8863 "Wallpaper animation!"); 8864 switch (transit) { 8865 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: 8866 case WindowManagerPolicy.TRANSIT_TASK_OPEN: 8867 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: 8868 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN; 8869 break; 8870 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: 8871 case WindowManagerPolicy.TRANSIT_TASK_CLOSE: 8872 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: 8873 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE; 8874 break; 8875 } 8876 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8877 "New transit: " + transit); 8878 } else if (oldWallpaper != null) { 8879 // We are transitioning from an activity with 8880 // a wallpaper to one without. 8881 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE; 8882 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8883 "New transit away from wallpaper: " + transit); 8884 } else if (mWallpaperTarget != null) { 8885 // We are transitioning from an activity without 8886 // a wallpaper to now showing the wallpaper 8887 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN; 8888 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8889 "New transit into wallpaper: " + transit); 8890 } 8891 8892 if ((transit&WindowManagerPolicy.TRANSIT_ENTER_MASK) != 0) { 8893 mLastEnterAnimToken = animToken; 8894 mLastEnterAnimParams = animLp; 8895 } else if (mLastEnterAnimParams != null) { 8896 animLp = mLastEnterAnimParams; 8897 mLastEnterAnimToken = null; 8898 mLastEnterAnimParams = null; 8899 } 8900 8901 // If all closing windows are obscured, then there is 8902 // no need to do an animation. This is the case, for 8903 // example, when this transition is being done behind 8904 // the lock screen. 8905 if (!mPolicy.allowAppAnimationsLw()) { 8906 animLp = null; 8907 } 8908 8909 NN = mOpeningApps.size(); 8910 for (i=0; i<NN; i++) { 8911 AppWindowToken wtoken = mOpeningApps.get(i); 8912 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8913 "Now opening app" + wtoken); 8914 wtoken.reportedVisible = false; 8915 wtoken.inPendingTransaction = false; 8916 wtoken.animation = null; 8917 setTokenVisibilityLocked(wtoken, animLp, true, transit, false); 8918 wtoken.updateReportedVisibilityLocked(); 8919 wtoken.waitingToShow = false; 8920 wtoken.showAllWindowsLocked(); 8921 } 8922 NN = mClosingApps.size(); 8923 for (i=0; i<NN; i++) { 8924 AppWindowToken wtoken = mClosingApps.get(i); 8925 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8926 "Now closing app" + wtoken); 8927 wtoken.inPendingTransaction = false; 8928 wtoken.animation = null; 8929 setTokenVisibilityLocked(wtoken, animLp, false, transit, false); 8930 wtoken.updateReportedVisibilityLocked(); 8931 wtoken.waitingToHide = false; 8932 // Force the allDrawn flag, because we want to start 8933 // this guy's animations regardless of whether it's 8934 // gotten drawn. 8935 wtoken.allDrawn = true; 8936 } 8937 8938 mNextAppTransitionPackage = null; 8939 8940 mOpeningApps.clear(); 8941 mClosingApps.clear(); 8942 8943 // This has changed the visibility of windows, so perform 8944 // a new layout to get them all up-to-date. 8945 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8946 mLayoutNeeded = true; 8947 if (!moveInputMethodWindowsIfNeededLocked(true)) { 8948 assignLayersLocked(); 8949 } 8950 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES); 8951 mFocusMayChange = false; 8952 } 8953 } 8954 8955 int adjResult = 0; 8956 8957 if (!animating && mAppTransitionRunning) { 8958 // We have finished the animation of an app transition. To do 8959 // this, we have delayed a lot of operations like showing and 8960 // hiding apps, moving apps in Z-order, etc. The app token list 8961 // reflects the correct Z-order, but the window list may now 8962 // be out of sync with it. So here we will just rebuild the 8963 // entire app window list. Fun! 8964 mAppTransitionRunning = false; 8965 // Clear information about apps that were moving. 8966 mToBottomApps.clear(); 8967 8968 rebuildAppWindowListLocked(); 8969 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8970 adjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED; 8971 moveInputMethodWindowsIfNeededLocked(false); 8972 wallpaperMayChange = true; 8973 // Since the window list has been rebuilt, focus might 8974 // have to be recomputed since the actual order of windows 8975 // might have changed again. 8976 mFocusMayChange = true; 8977 } 8978 8979 if (wallpaperForceHidingChanged && changes == 0 && !mAppTransitionReady) { 8980 // At this point, there was a window with a wallpaper that 8981 // was force hiding other windows behind it, but now it 8982 // is going away. This may be simple -- just animate 8983 // away the wallpaper and its window -- or it may be 8984 // hard -- the wallpaper now needs to be shown behind 8985 // something that was hidden. 8986 WindowState oldWallpaper = mWallpaperTarget; 8987 if (mLowerWallpaperTarget != null 8988 && mLowerWallpaperTarget.mAppToken != null) { 8989 if (DEBUG_WALLPAPER) Slog.v(TAG, 8990 "wallpaperForceHiding changed with lower=" 8991 + mLowerWallpaperTarget); 8992 if (DEBUG_WALLPAPER) Slog.v(TAG, 8993 "hidden=" + mLowerWallpaperTarget.mAppToken.hidden + 8994 " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested); 8995 if (mLowerWallpaperTarget.mAppToken.hidden) { 8996 // The lower target has become hidden before we 8997 // actually started the animation... let's completely 8998 // re-evaluate everything. 8999 mLowerWallpaperTarget = mUpperWallpaperTarget = null; 9000 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 9001 } 9002 } 9003 adjResult |= adjustWallpaperWindowsLocked(); 9004 wallpaperMayChange = false; 9005 wallpaperForceHidingChanged = false; 9006 if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper 9007 + " NEW: " + mWallpaperTarget 9008 + " LOWER: " + mLowerWallpaperTarget); 9009 if (mLowerWallpaperTarget == null) { 9010 // Whoops, we don't need a special wallpaper animation. 9011 // Clear them out. 9012 forceHiding = false; 9013 for (i=N-1; i>=0; i--) { 9014 WindowState w = mWindows.get(i); 9015 if (w.mSurface != null) { 9016 final WindowManager.LayoutParams attrs = w.mAttrs; 9017 if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) { 9018 if (DEBUG_FOCUS) Slog.i(TAG, "win=" + w + " force hides other windows"); 9019 forceHiding = true; 9020 } else if (mPolicy.canBeForceHidden(w, attrs)) { 9021 if (!w.mAnimating) { 9022 // We set the animation above so it 9023 // is not yet running. 9024 w.clearAnimation(); 9025 } 9026 } 9027 } 9028 } 9029 } 9030 } 9031 9032 if (wallpaperMayChange) { 9033 if (DEBUG_WALLPAPER) Slog.v(TAG, 9034 "Wallpaper may change! Adjusting"); 9035 adjResult |= adjustWallpaperWindowsLocked(); 9036 } 9037 9038 if ((adjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 9039 if (DEBUG_WALLPAPER) Slog.v(TAG, 9040 "Wallpaper layer changed: assigning layers + relayout"); 9041 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 9042 assignLayersLocked(); 9043 } else if ((adjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) { 9044 if (DEBUG_WALLPAPER) Slog.v(TAG, 9045 "Wallpaper visibility changed: relayout"); 9046 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 9047 } 9048 9049 if (mFocusMayChange) { 9050 mFocusMayChange = false; 9051 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES)) { 9052 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 9053 adjResult = 0; 9054 } 9055 } 9056 9057 if (mLayoutNeeded) { 9058 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 9059 } 9060 9061 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x" 9062 + Integer.toHexString(changes)); 9063 9064 mInputMonitor.updateInputWindowsLw(); 9065 } while (changes != 0); 9066 9067 // THIRD LOOP: Update the surfaces of all windows. 9068 9069 final boolean someoneLosingFocus = mLosingFocus.size() != 0; 9070 9071 boolean obscured = false; 9072 boolean blurring = false; 9073 boolean dimming = false; 9074 boolean covered = false; 9075 boolean syswin = false; 9076 boolean backgroundFillerShown = false; 9077 9078 final int N = mWindows.size(); 9079 9080 for (i=N-1; i>=0; i--) { 9081 WindowState w = mWindows.get(i); 9082 9083 boolean displayed = false; 9084 final WindowManager.LayoutParams attrs = w.mAttrs; 9085 final int attrFlags = attrs.flags; 9086 9087 if (w.mSurface != null) { 9088 // XXX NOTE: The logic here could be improved. We have 9089 // the decision about whether to resize a window separated 9090 // from whether to hide the surface. This can cause us to 9091 // resize a surface even if we are going to hide it. You 9092 // can see this by (1) holding device in landscape mode on 9093 // home screen; (2) tapping browser icon (device will rotate 9094 // to landscape; (3) tap home. The wallpaper will be resized 9095 // in step 2 but then immediately hidden, causing us to 9096 // have to resize and then redraw it again in step 3. It 9097 // would be nice to figure out how to avoid this, but it is 9098 // difficult because we do need to resize surfaces in some 9099 // cases while they are hidden such as when first showing a 9100 // window. 9101 9102 w.computeShownFrameLocked(); 9103 if (localLOGV) Slog.v( 9104 TAG, "Placing surface #" + i + " " + w.mSurface 9105 + ": new=" + w.mShownFrame + ", old=" 9106 + w.mLastShownFrame); 9107 9108 boolean resize; 9109 int width, height; 9110 if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) { 9111 resize = w.mLastRequestedWidth != w.mRequestedWidth || 9112 w.mLastRequestedHeight != w.mRequestedHeight; 9113 // for a scaled surface, we just want to use 9114 // the requested size. 9115 width = w.mRequestedWidth; 9116 height = w.mRequestedHeight; 9117 w.mLastRequestedWidth = width; 9118 w.mLastRequestedHeight = height; 9119 w.mLastShownFrame.set(w.mShownFrame); 9120 try { 9121 if (SHOW_TRANSACTIONS) logSurface(w, 9122 "POS " + w.mShownFrame.left 9123 + ", " + w.mShownFrame.top, null); 9124 w.mSurfaceX = w.mShownFrame.left; 9125 w.mSurfaceY = w.mShownFrame.top; 9126 w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top); 9127 } catch (RuntimeException e) { 9128 Slog.w(TAG, "Error positioning surface in " + w, e); 9129 if (!recoveringMemory) { 9130 reclaimSomeSurfaceMemoryLocked(w, "position"); 9131 } 9132 } 9133 } else { 9134 resize = !w.mLastShownFrame.equals(w.mShownFrame); 9135 width = w.mShownFrame.width(); 9136 height = w.mShownFrame.height(); 9137 w.mLastShownFrame.set(w.mShownFrame); 9138 } 9139 9140 if (resize) { 9141 if (width < 1) width = 1; 9142 if (height < 1) height = 1; 9143 if (w.mSurface != null) { 9144 try { 9145 if (SHOW_TRANSACTIONS) logSurface(w, 9146 "POS " + w.mShownFrame.left + "," 9147 + w.mShownFrame.top + " SIZE " 9148 + w.mShownFrame.width() + "x" 9149 + w.mShownFrame.height(), null); 9150 w.mSurfaceResized = true; 9151 w.mSurfaceW = width; 9152 w.mSurfaceH = height; 9153 w.mSurface.setSize(width, height); 9154 w.mSurfaceX = w.mShownFrame.left; 9155 w.mSurfaceY = w.mShownFrame.top; 9156 w.mSurface.setPosition(w.mShownFrame.left, 9157 w.mShownFrame.top); 9158 } catch (RuntimeException e) { 9159 // If something goes wrong with the surface (such 9160 // as running out of memory), don't take down the 9161 // entire system. 9162 Slog.e(TAG, "Failure updating surface of " + w 9163 + "size=(" + width + "x" + height 9164 + "), pos=(" + w.mShownFrame.left 9165 + "," + w.mShownFrame.top + ")", e); 9166 if (!recoveringMemory) { 9167 reclaimSomeSurfaceMemoryLocked(w, "size"); 9168 } 9169 } 9170 } 9171 } 9172 if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) { 9173 w.mContentInsetsChanged = 9174 !w.mLastContentInsets.equals(w.mContentInsets); 9175 w.mVisibleInsetsChanged = 9176 !w.mLastVisibleInsets.equals(w.mVisibleInsets); 9177 boolean configChanged = 9178 w.mConfiguration != mCurConfiguration 9179 && (w.mConfiguration == null 9180 || mCurConfiguration.diff(w.mConfiguration) != 0); 9181 if (DEBUG_CONFIGURATION && configChanged) { 9182 Slog.v(TAG, "Win " + w + " config changed: " 9183 + mCurConfiguration); 9184 } 9185 if (localLOGV) Slog.v(TAG, "Resizing " + w 9186 + ": configChanged=" + configChanged 9187 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 9188 if (!w.mLastFrame.equals(w.mFrame) 9189 || w.mContentInsetsChanged 9190 || w.mVisibleInsetsChanged 9191 || w.mSurfaceResized 9192 || configChanged) { 9193 w.mLastFrame.set(w.mFrame); 9194 w.mLastContentInsets.set(w.mContentInsets); 9195 w.mLastVisibleInsets.set(w.mVisibleInsets); 9196 // If the screen is currently frozen, then keep 9197 // it frozen until this window draws at its new 9198 // orientation. 9199 if (mDisplayFrozen) { 9200 if (DEBUG_ORIENTATION) Slog.v(TAG, 9201 "Resizing while display frozen: " + w); 9202 w.mOrientationChanging = true; 9203 if (!mWindowsFreezingScreen) { 9204 mWindowsFreezingScreen = true; 9205 // XXX should probably keep timeout from 9206 // when we first froze the display. 9207 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9208 mH.sendMessageDelayed(mH.obtainMessage( 9209 H.WINDOW_FREEZE_TIMEOUT), 2000); 9210 } 9211 } 9212 // If the orientation is changing, then we need to 9213 // hold off on unfreezing the display until this 9214 // window has been redrawn; to do that, we need 9215 // to go through the process of getting informed 9216 // by the application when it has finished drawing. 9217 if (w.mOrientationChanging) { 9218 if (DEBUG_ORIENTATION) Slog.v(TAG, 9219 "Orientation start waiting for draw in " 9220 + w + ", surface " + w.mSurface); 9221 w.mDrawPending = true; 9222 w.mCommitDrawPending = false; 9223 w.mReadyToShow = false; 9224 if (w.mAppToken != null) { 9225 w.mAppToken.allDrawn = false; 9226 } 9227 } 9228 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 9229 "Resizing window " + w + " to " + w.mFrame); 9230 mResizingWindows.add(w); 9231 } else if (w.mOrientationChanging) { 9232 if (!w.mDrawPending && !w.mCommitDrawPending) { 9233 if (DEBUG_ORIENTATION) Slog.v(TAG, 9234 "Orientation not waiting for draw in " 9235 + w + ", surface " + w.mSurface); 9236 w.mOrientationChanging = false; 9237 } 9238 } 9239 } 9240 9241 if (w.mAttachedHidden || !w.isReadyForDisplay()) { 9242 if (!w.mLastHidden) { 9243 //dump(); 9244 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Window hiding: waitingToShow=" 9245 + w.mRootToken.waitingToShow + " polvis=" 9246 + w.mPolicyVisibility + " atthid=" 9247 + w.mAttachedHidden + " tokhid=" 9248 + w.mRootToken.hidden + " vis=" 9249 + w.mViewVisibility); 9250 w.mLastHidden = true; 9251 if (SHOW_TRANSACTIONS) logSurface(w, 9252 "HIDE (performLayout)", null); 9253 if (w.mSurface != null) { 9254 w.mSurfaceShown = false; 9255 try { 9256 w.mSurface.hide(); 9257 } catch (RuntimeException e) { 9258 Slog.w(TAG, "Exception hiding surface in " + w); 9259 } 9260 } 9261 } 9262 // If we are waiting for this window to handle an 9263 // orientation change, well, it is hidden, so 9264 // doesn't really matter. Note that this does 9265 // introduce a potential glitch if the window 9266 // becomes unhidden before it has drawn for the 9267 // new orientation. 9268 if (w.mOrientationChanging) { 9269 w.mOrientationChanging = false; 9270 if (DEBUG_ORIENTATION) Slog.v(TAG, 9271 "Orientation change skips hidden " + w); 9272 } 9273 } else if (w.mLastLayer != w.mAnimLayer 9274 || w.mLastAlpha != w.mShownAlpha 9275 || w.mLastDsDx != w.mDsDx 9276 || w.mLastDtDx != w.mDtDx 9277 || w.mLastDsDy != w.mDsDy 9278 || w.mLastDtDy != w.mDtDy 9279 || w.mLastHScale != w.mHScale 9280 || w.mLastVScale != w.mVScale 9281 || w.mLastHidden) { 9282 displayed = true; 9283 w.mLastAlpha = w.mShownAlpha; 9284 w.mLastLayer = w.mAnimLayer; 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 if (SHOW_TRANSACTIONS) logSurface(w, 9292 "alpha=" + w.mShownAlpha + " layer=" + w.mAnimLayer 9293 + " matrix=[" + (w.mDsDx*w.mHScale) 9294 + "," + (w.mDtDx*w.mVScale) 9295 + "][" + (w.mDsDy*w.mHScale) 9296 + "," + (w.mDtDy*w.mVScale) + "]", null); 9297 if (w.mSurface != null) { 9298 try { 9299 w.mSurfaceAlpha = w.mShownAlpha; 9300 w.mSurface.setAlpha(w.mShownAlpha); 9301 w.mSurfaceLayer = w.mAnimLayer; 9302 w.mSurface.setLayer(w.mAnimLayer); 9303 w.mSurface.setMatrix( 9304 w.mDsDx*w.mHScale, w.mDtDx*w.mVScale, 9305 w.mDsDy*w.mHScale, w.mDtDy*w.mVScale); 9306 } catch (RuntimeException e) { 9307 Slog.w(TAG, "Error updating surface in " + w, e); 9308 if (!recoveringMemory) { 9309 reclaimSomeSurfaceMemoryLocked(w, "update"); 9310 } 9311 } 9312 } 9313 9314 if (w.mLastHidden && !w.mDrawPending 9315 && !w.mCommitDrawPending 9316 && !w.mReadyToShow) { 9317 if (SHOW_TRANSACTIONS) logSurface(w, 9318 "SHOW (performLayout)", null); 9319 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w 9320 + " during relayout"); 9321 if (showSurfaceRobustlyLocked(w)) { 9322 w.mHasDrawn = true; 9323 w.mLastHidden = false; 9324 } else { 9325 w.mOrientationChanging = false; 9326 } 9327 } 9328 if (w.mSurface != null) { 9329 w.mToken.hasVisible = true; 9330 } 9331 } else { 9332 displayed = true; 9333 } 9334 9335 if (displayed) { 9336 if (!covered) { 9337 if (attrs.width == LayoutParams.MATCH_PARENT 9338 && attrs.height == LayoutParams.MATCH_PARENT) { 9339 covered = true; 9340 } 9341 } 9342 if (w.mOrientationChanging) { 9343 if (w.mDrawPending || w.mCommitDrawPending) { 9344 orientationChangeComplete = false; 9345 if (DEBUG_ORIENTATION) Slog.v(TAG, 9346 "Orientation continue waiting for draw in " + w); 9347 } else { 9348 w.mOrientationChanging = false; 9349 if (DEBUG_ORIENTATION) Slog.v(TAG, 9350 "Orientation change complete in " + w); 9351 } 9352 } 9353 w.mToken.hasVisible = true; 9354 } 9355 } else if (w.mOrientationChanging) { 9356 if (DEBUG_ORIENTATION) Slog.v(TAG, 9357 "Orientation change skips hidden " + w); 9358 w.mOrientationChanging = false; 9359 } 9360 9361 final boolean canBeSeen = w.isDisplayedLw(); 9362 9363 if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) { 9364 focusDisplayed = true; 9365 } 9366 9367 final boolean obscuredChanged = w.mObscured != obscured; 9368 9369 // Update effect. 9370 if (!(w.mObscured=obscured)) { 9371 if (w.mSurface != null) { 9372 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 9373 holdScreen = w.mSession; 9374 } 9375 if (!syswin && w.mAttrs.screenBrightness >= 0 9376 && screenBrightness < 0) { 9377 screenBrightness = w.mAttrs.screenBrightness; 9378 } 9379 if (!syswin && w.mAttrs.buttonBrightness >= 0 9380 && buttonBrightness < 0) { 9381 buttonBrightness = w.mAttrs.buttonBrightness; 9382 } 9383 if (canBeSeen 9384 && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG 9385 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD 9386 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) { 9387 syswin = true; 9388 } 9389 } 9390 9391 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 9392 if (opaqueDrawn && w.isFullscreen(dw, dh)) { 9393 // This window completely covers everything behind it, 9394 // so we want to leave all of them as unblurred (for 9395 // performance reasons). 9396 obscured = true; 9397 } else if (opaqueDrawn && w.needsBackgroundFiller(dw, dh)) { 9398 if (SHOW_TRANSACTIONS) Slog.d(TAG, "showing background filler"); 9399 // This window is in compatibility mode, and needs background filler. 9400 obscured = true; 9401 if (mBackgroundFillerSurface == null) { 9402 try { 9403 mBackgroundFillerSurface = new Surface(mFxSession, 0, 9404 "BackGroundFiller", 9405 0, dw, dh, 9406 PixelFormat.OPAQUE, 9407 Surface.FX_SURFACE_NORMAL); 9408 } catch (Exception e) { 9409 Slog.e(TAG, "Exception creating filler surface", e); 9410 } 9411 } 9412 try { 9413 mBackgroundFillerSurface.setPosition(0, 0); 9414 mBackgroundFillerSurface.setSize(dw, dh); 9415 // Using the same layer as Dim because they will never be shown at the 9416 // same time. 9417 mBackgroundFillerSurface.setLayer(w.mAnimLayer - 1); 9418 mBackgroundFillerSurface.show(); 9419 } catch (RuntimeException e) { 9420 Slog.e(TAG, "Exception showing filler surface"); 9421 } 9422 backgroundFillerShown = true; 9423 mBackgroundFillerShown = true; 9424 } else if (canBeSeen && !obscured && 9425 (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) { 9426 if (localLOGV) Slog.v(TAG, "Win " + w 9427 + ": blurring=" + blurring 9428 + " obscured=" + obscured 9429 + " displayed=" + displayed); 9430 if ((attrFlags&FLAG_DIM_BEHIND) != 0) { 9431 if (!dimming) { 9432 //Slog.i(TAG, "DIM BEHIND: " + w); 9433 dimming = true; 9434 if (mDimAnimator == null) { 9435 mDimAnimator = new DimAnimator(mFxSession); 9436 } 9437 mDimAnimator.show(dw, dh); 9438 mDimAnimator.updateParameters(w, currentTime); 9439 } 9440 } 9441 if ((attrFlags&FLAG_BLUR_BEHIND) != 0) { 9442 if (!blurring) { 9443 //Slog.i(TAG, "BLUR BEHIND: " + w); 9444 blurring = true; 9445 if (mBlurSurface == null) { 9446 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " 9447 + mBlurSurface + ": CREATE"); 9448 try { 9449 mBlurSurface = new Surface(mFxSession, 0, 9450 "BlurSurface", 9451 -1, 16, 16, 9452 PixelFormat.OPAQUE, 9453 Surface.FX_SURFACE_BLUR); 9454 } catch (Exception e) { 9455 Slog.e(TAG, "Exception creating Blur surface", e); 9456 } 9457 } 9458 if (mBlurSurface != null) { 9459 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " 9460 + mBlurSurface + ": pos=(0,0) (" + 9461 dw + "x" + dh + "), layer=" + (w.mAnimLayer-1)); 9462 mBlurSurface.setPosition(0, 0); 9463 mBlurSurface.setSize(dw, dh); 9464 mBlurSurface.setLayer(w.mAnimLayer-2); 9465 if (!mBlurShown) { 9466 try { 9467 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " 9468 + mBlurSurface + ": SHOW"); 9469 mBlurSurface.show(); 9470 } catch (RuntimeException e) { 9471 Slog.w(TAG, "Failure showing blur surface", e); 9472 } 9473 mBlurShown = true; 9474 } 9475 } 9476 } 9477 } 9478 } 9479 } 9480 9481 if (obscuredChanged && mWallpaperTarget == w) { 9482 // This is the wallpaper target and its obscured state 9483 // changed... make sure the current wallaper's visibility 9484 // has been updated accordingly. 9485 updateWallpaperVisibilityLocked(); 9486 } 9487 } 9488 9489 if (backgroundFillerShown == false && mBackgroundFillerShown) { 9490 mBackgroundFillerShown = false; 9491 if (SHOW_TRANSACTIONS) Slog.d(TAG, "hiding background filler"); 9492 try { 9493 mBackgroundFillerSurface.hide(); 9494 } catch (RuntimeException e) { 9495 Slog.e(TAG, "Exception hiding filler surface", e); 9496 } 9497 } 9498 9499 if (mDimAnimator != null && mDimAnimator.mDimShown) { 9500 animating |= mDimAnimator.updateSurface(dimming, currentTime, 9501 mDisplayFrozen || !mPolicy.isScreenOn()); 9502 } 9503 9504 if (!blurring && mBlurShown) { 9505 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " + mBlurSurface 9506 + ": HIDE"); 9507 try { 9508 mBlurSurface.hide(); 9509 } catch (IllegalArgumentException e) { 9510 Slog.w(TAG, "Illegal argument exception hiding blur surface"); 9511 } 9512 mBlurShown = false; 9513 } 9514 9515 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION"); 9516 } catch (RuntimeException e) { 9517 Slog.e(TAG, "Unhandled exception in Window Manager", e); 9518 } 9519 9520 mInputMonitor.updateInputWindowsLw(); 9521 9522 Surface.closeTransaction(); 9523 9524 if (mWatermark != null) { 9525 mWatermark.drawIfNeeded(); 9526 } 9527 9528 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 9529 "With display frozen, orientationChangeComplete=" 9530 + orientationChangeComplete); 9531 if (orientationChangeComplete) { 9532 if (mWindowsFreezingScreen) { 9533 mWindowsFreezingScreen = false; 9534 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9535 } 9536 stopFreezingDisplayLocked(); 9537 } 9538 9539 i = mResizingWindows.size(); 9540 if (i > 0) { 9541 do { 9542 i--; 9543 WindowState win = mResizingWindows.get(i); 9544 try { 9545 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 9546 "Reporting new frame to " + win + ": " + win.mFrame); 9547 int diff = 0; 9548 boolean configChanged = 9549 win.mConfiguration != mCurConfiguration 9550 && (win.mConfiguration == null 9551 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0); 9552 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) 9553 && configChanged) { 9554 Slog.i(TAG, "Sending new config to window " + win + ": " 9555 + win.mFrame.width() + "x" + win.mFrame.height() 9556 + " / " + mCurConfiguration + " / 0x" 9557 + Integer.toHexString(diff)); 9558 } 9559 win.mConfiguration = mCurConfiguration; 9560 win.mClient.resized(win.mFrame.width(), 9561 win.mFrame.height(), win.mLastContentInsets, 9562 win.mLastVisibleInsets, win.mDrawPending, 9563 configChanged ? win.mConfiguration : null); 9564 win.mContentInsetsChanged = false; 9565 win.mVisibleInsetsChanged = false; 9566 win.mSurfaceResized = false; 9567 } catch (RemoteException e) { 9568 win.mOrientationChanging = false; 9569 } 9570 } while (i > 0); 9571 mResizingWindows.clear(); 9572 } 9573 9574 // Destroy the surface of any windows that are no longer visible. 9575 boolean wallpaperDestroyed = false; 9576 i = mDestroySurface.size(); 9577 if (i > 0) { 9578 do { 9579 i--; 9580 WindowState win = mDestroySurface.get(i); 9581 win.mDestroying = false; 9582 if (mInputMethodWindow == win) { 9583 mInputMethodWindow = null; 9584 } 9585 if (win == mWallpaperTarget) { 9586 wallpaperDestroyed = true; 9587 } 9588 win.destroySurfaceLocked(); 9589 } while (i > 0); 9590 mDestroySurface.clear(); 9591 } 9592 9593 // Time to remove any exiting tokens? 9594 for (i=mExitingTokens.size()-1; i>=0; i--) { 9595 WindowToken token = mExitingTokens.get(i); 9596 if (!token.hasVisible) { 9597 mExitingTokens.remove(i); 9598 if (token.windowType == TYPE_WALLPAPER) { 9599 mWallpaperTokens.remove(token); 9600 } 9601 } 9602 } 9603 9604 // Time to remove any exiting applications? 9605 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 9606 AppWindowToken token = mExitingAppTokens.get(i); 9607 if (!token.hasVisible && !mClosingApps.contains(token)) { 9608 // Make sure there is no animation running on this token, 9609 // so any windows associated with it will be removed as 9610 // soon as their animations are complete 9611 token.animation = null; 9612 token.animating = false; 9613 mAppTokens.remove(token); 9614 mExitingAppTokens.remove(i); 9615 if (mLastEnterAnimToken == token) { 9616 mLastEnterAnimToken = null; 9617 mLastEnterAnimParams = null; 9618 } 9619 } 9620 } 9621 9622 boolean needRelayout = false; 9623 9624 if (!animating && mAppTransitionRunning) { 9625 // We have finished the animation of an app transition. To do 9626 // this, we have delayed a lot of operations like showing and 9627 // hiding apps, moving apps in Z-order, etc. The app token list 9628 // reflects the correct Z-order, but the window list may now 9629 // be out of sync with it. So here we will just rebuild the 9630 // entire app window list. Fun! 9631 mAppTransitionRunning = false; 9632 needRelayout = true; 9633 rebuildAppWindowListLocked(); 9634 assignLayersLocked(); 9635 // Clear information about apps that were moving. 9636 mToBottomApps.clear(); 9637 } 9638 9639 if (focusDisplayed) { 9640 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 9641 } 9642 if (wallpaperDestroyed) { 9643 needRelayout = adjustWallpaperWindowsLocked() != 0; 9644 } 9645 if (needRelayout) { 9646 requestAnimationLocked(0); 9647 } else if (animating) { 9648 requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis()); 9649 } 9650 9651 mInputMonitor.updateInputWindowsLw(); 9652 9653 if (DEBUG_FREEZE) Slog.v(TAG, "Layout: mDisplayFrozen=" + mDisplayFrozen 9654 + " holdScreen=" + holdScreen); 9655 if (!mDisplayFrozen) { 9656 setHoldScreenLocked(holdScreen != null); 9657 if (screenBrightness < 0 || screenBrightness > 1.0f) { 9658 mPowerManager.setScreenBrightnessOverride(-1); 9659 } else { 9660 mPowerManager.setScreenBrightnessOverride((int) 9661 (screenBrightness * Power.BRIGHTNESS_ON)); 9662 } 9663 if (buttonBrightness < 0 || buttonBrightness > 1.0f) { 9664 mPowerManager.setButtonBrightnessOverride(-1); 9665 } else { 9666 mPowerManager.setButtonBrightnessOverride((int) 9667 (buttonBrightness * Power.BRIGHTNESS_ON)); 9668 } 9669 if (holdScreen != mHoldingScreenOn) { 9670 mHoldingScreenOn = holdScreen; 9671 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen); 9672 mH.sendMessage(m); 9673 } 9674 } 9675 9676 if (mTurnOnScreen) { 9677 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 9678 mPowerManager.userActivity(SystemClock.uptimeMillis(), false, 9679 LocalPowerManager.BUTTON_EVENT, true); 9680 mTurnOnScreen = false; 9681 } 9682 9683 // Check to see if we are now in a state where the screen should 9684 // be enabled, because the window obscured flags have changed. 9685 enableScreenIfNeededLocked(); 9686 } 9687 9688 /** 9689 * Must be called with the main window manager lock held. 9690 */ 9691 void setHoldScreenLocked(boolean holding) { 9692 boolean state = mHoldingScreenWakeLock.isHeld(); 9693 if (holding != state) { 9694 if (holding) { 9695 mHoldingScreenWakeLock.acquire(); 9696 } else { 9697 mPolicy.screenOnStoppedLw(); 9698 mHoldingScreenWakeLock.release(); 9699 } 9700 } 9701 } 9702 9703 void requestAnimationLocked(long delay) { 9704 if (!mAnimationPending) { 9705 mAnimationPending = true; 9706 mH.sendMessageDelayed(mH.obtainMessage(H.ANIMATE), delay); 9707 } 9708 } 9709 9710 /** 9711 * Have the surface flinger show a surface, robustly dealing with 9712 * error conditions. In particular, if there is not enough memory 9713 * to show the surface, then we will try to get rid of other surfaces 9714 * in order to succeed. 9715 * 9716 * @return Returns true if the surface was successfully shown. 9717 */ 9718 boolean showSurfaceRobustlyLocked(WindowState win) { 9719 try { 9720 if (win.mSurface != null) { 9721 win.mSurfaceShown = true; 9722 win.mSurface.show(); 9723 if (win.mTurnOnScreen) { 9724 if (DEBUG_VISIBILITY) Slog.v(TAG, 9725 "Show surface turning screen on: " + win); 9726 win.mTurnOnScreen = false; 9727 mTurnOnScreen = true; 9728 } 9729 } 9730 return true; 9731 } catch (RuntimeException e) { 9732 Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win); 9733 } 9734 9735 reclaimSomeSurfaceMemoryLocked(win, "show"); 9736 9737 return false; 9738 } 9739 9740 void reclaimSomeSurfaceMemoryLocked(WindowState win, String operation) { 9741 final Surface surface = win.mSurface; 9742 9743 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, win.toString(), 9744 win.mSession.mPid, operation); 9745 9746 if (mForceRemoves == null) { 9747 mForceRemoves = new ArrayList<WindowState>(); 9748 } 9749 9750 long callingIdentity = Binder.clearCallingIdentity(); 9751 try { 9752 // There was some problem... first, do a sanity check of the 9753 // window list to make sure we haven't left any dangling surfaces 9754 // around. 9755 int N = mWindows.size(); 9756 boolean leakedSurface = false; 9757 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 9758 for (int i=0; i<N; i++) { 9759 WindowState ws = mWindows.get(i); 9760 if (ws.mSurface != null) { 9761 if (!mSessions.contains(ws.mSession)) { 9762 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 9763 + ws + " surface=" + ws.mSurface 9764 + " token=" + win.mToken 9765 + " pid=" + ws.mSession.mPid 9766 + " uid=" + ws.mSession.mUid); 9767 ws.mSurface.destroy(); 9768 ws.mSurfaceShown = false; 9769 ws.mSurface = null; 9770 mForceRemoves.add(ws); 9771 i--; 9772 N--; 9773 leakedSurface = true; 9774 } else if (win.mAppToken != null && win.mAppToken.clientHidden) { 9775 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 9776 + ws + " surface=" + ws.mSurface 9777 + " token=" + win.mAppToken); 9778 ws.mSurface.destroy(); 9779 ws.mSurfaceShown = false; 9780 ws.mSurface = null; 9781 leakedSurface = true; 9782 } 9783 } 9784 } 9785 9786 boolean killedApps = false; 9787 if (!leakedSurface) { 9788 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 9789 SparseIntArray pidCandidates = new SparseIntArray(); 9790 for (int i=0; i<N; i++) { 9791 WindowState ws = mWindows.get(i); 9792 if (ws.mSurface != null) { 9793 pidCandidates.append(ws.mSession.mPid, ws.mSession.mPid); 9794 } 9795 } 9796 if (pidCandidates.size() > 0) { 9797 int[] pids = new int[pidCandidates.size()]; 9798 for (int i=0; i<pids.length; i++) { 9799 pids[i] = pidCandidates.keyAt(i); 9800 } 9801 try { 9802 if (mActivityManager.killPids(pids, "Free memory")) { 9803 killedApps = true; 9804 } 9805 } catch (RemoteException e) { 9806 } 9807 } 9808 } 9809 9810 if (leakedSurface || killedApps) { 9811 // We managed to reclaim some memory, so get rid of the trouble 9812 // surface and ask the app to request another one. 9813 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 9814 if (surface != null) { 9815 surface.destroy(); 9816 win.mSurfaceShown = false; 9817 win.mSurface = null; 9818 } 9819 9820 try { 9821 win.mClient.dispatchGetNewSurface(); 9822 } catch (RemoteException e) { 9823 } 9824 } 9825 } finally { 9826 Binder.restoreCallingIdentity(callingIdentity); 9827 } 9828 } 9829 9830 private boolean updateFocusedWindowLocked(int mode) { 9831 WindowState newFocus = computeFocusedWindowLocked(); 9832 if (mCurrentFocus != newFocus) { 9833 // This check makes sure that we don't already have the focus 9834 // change message pending. 9835 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9836 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9837 if (localLOGV) Slog.v( 9838 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus); 9839 final WindowState oldFocus = mCurrentFocus; 9840 mCurrentFocus = newFocus; 9841 mLosingFocus.remove(newFocus); 9842 9843 final WindowState imWindow = mInputMethodWindow; 9844 if (newFocus != imWindow && oldFocus != imWindow) { 9845 if (moveInputMethodWindowsIfNeededLocked( 9846 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS && 9847 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) { 9848 mLayoutNeeded = true; 9849 } 9850 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9851 performLayoutLockedInner(); 9852 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9853 // Client will do the layout, but we need to assign layers 9854 // for handleNewWindowLocked() below. 9855 assignLayersLocked(); 9856 } 9857 } 9858 9859 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9860 // If we defer assigning layers, then the caller is responsible for 9861 // doing this part. 9862 finishUpdateFocusedWindowAfterAssignLayersLocked(); 9863 } 9864 return true; 9865 } 9866 return false; 9867 } 9868 9869 private void finishUpdateFocusedWindowAfterAssignLayersLocked() { 9870 mInputMonitor.setInputFocusLw(mCurrentFocus); 9871 } 9872 9873 private WindowState computeFocusedWindowLocked() { 9874 WindowState result = null; 9875 WindowState win; 9876 9877 int i = mWindows.size() - 1; 9878 int nextAppIndex = mAppTokens.size()-1; 9879 WindowToken nextApp = nextAppIndex >= 0 9880 ? mAppTokens.get(nextAppIndex) : null; 9881 9882 while (i >= 0) { 9883 win = mWindows.get(i); 9884 9885 if (localLOGV || DEBUG_FOCUS) Slog.v( 9886 TAG, "Looking for focus: " + i 9887 + " = " + win 9888 + ", flags=" + win.mAttrs.flags 9889 + ", canReceive=" + win.canReceiveKeys()); 9890 9891 AppWindowToken thisApp = win.mAppToken; 9892 9893 // If this window's application has been removed, just skip it. 9894 if (thisApp != null && thisApp.removed) { 9895 i--; 9896 continue; 9897 } 9898 9899 // If there is a focused app, don't allow focus to go to any 9900 // windows below it. If this is an application window, step 9901 // through the app tokens until we find its app. 9902 if (thisApp != null && nextApp != null && thisApp != nextApp 9903 && win.mAttrs.type != TYPE_APPLICATION_STARTING) { 9904 int origAppIndex = nextAppIndex; 9905 while (nextAppIndex > 0) { 9906 if (nextApp == mFocusedApp) { 9907 // Whoops, we are below the focused app... no focus 9908 // for you! 9909 if (localLOGV || DEBUG_FOCUS) Slog.v( 9910 TAG, "Reached focused app: " + mFocusedApp); 9911 return null; 9912 } 9913 nextAppIndex--; 9914 nextApp = mAppTokens.get(nextAppIndex); 9915 if (nextApp == thisApp) { 9916 break; 9917 } 9918 } 9919 if (thisApp != nextApp) { 9920 // Uh oh, the app token doesn't exist! This shouldn't 9921 // happen, but if it does we can get totally hosed... 9922 // so restart at the original app. 9923 nextAppIndex = origAppIndex; 9924 nextApp = mAppTokens.get(nextAppIndex); 9925 } 9926 } 9927 9928 // Dispatch to this window if it is wants key events. 9929 if (win.canReceiveKeys()) { 9930 if (DEBUG_FOCUS) Slog.v( 9931 TAG, "Found focus @ " + i + " = " + win); 9932 result = win; 9933 break; 9934 } 9935 9936 i--; 9937 } 9938 9939 return result; 9940 } 9941 9942 private void startFreezingDisplayLocked() { 9943 if (mDisplayFrozen) { 9944 return; 9945 } 9946 9947 mScreenFrozenLock.acquire(); 9948 9949 long now = SystemClock.uptimeMillis(); 9950 //Slog.i(TAG, "Freezing, gc pending: " + mFreezeGcPending + ", now " + now); 9951 if (mFreezeGcPending != 0) { 9952 if (now > (mFreezeGcPending+1000)) { 9953 //Slog.i(TAG, "Gc! " + now + " > " + (mFreezeGcPending+1000)); 9954 mH.removeMessages(H.FORCE_GC); 9955 Runtime.getRuntime().gc(); 9956 mFreezeGcPending = now; 9957 } 9958 } else { 9959 mFreezeGcPending = now; 9960 } 9961 9962 if (DEBUG_FREEZE) Slog.v(TAG, "*** FREEZING DISPLAY", new RuntimeException()); 9963 9964 mDisplayFrozen = true; 9965 9966 mInputMonitor.freezeInputDispatchingLw(); 9967 9968 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 9969 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 9970 mNextAppTransitionPackage = null; 9971 mAppTransitionReady = true; 9972 } 9973 9974 if (PROFILE_ORIENTATION) { 9975 File file = new File("/data/system/frozen"); 9976 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 9977 } 9978 Surface.freezeDisplay(0); 9979 } 9980 9981 private void stopFreezingDisplayLocked() { 9982 if (!mDisplayFrozen) { 9983 return; 9984 } 9985 9986 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) { 9987 return; 9988 } 9989 9990 if (DEBUG_FREEZE) Slog.v(TAG, "*** UNFREEZING DISPLAY", new RuntimeException()); 9991 9992 mDisplayFrozen = false; 9993 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 9994 if (PROFILE_ORIENTATION) { 9995 Debug.stopMethodTracing(); 9996 } 9997 Surface.unfreezeDisplay(0); 9998 9999 mInputMonitor.thawInputDispatchingLw(); 10000 10001 // While the display is frozen we don't re-compute the orientation 10002 // to avoid inconsistent states. However, something interesting 10003 // could have actually changed during that time so re-evaluate it 10004 // now to catch that. 10005 if (updateOrientationFromAppTokensLocked()) { 10006 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10007 } 10008 10009 // A little kludge: a lot could have happened while the 10010 // display was frozen, so now that we are coming back we 10011 // do a gc so that any remote references the system 10012 // processes holds on others can be released if they are 10013 // no longer needed. 10014 mH.removeMessages(H.FORCE_GC); 10015 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 10016 2000); 10017 10018 mScreenFrozenLock.release(); 10019 } 10020 10021 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 10022 DisplayMetrics dm) { 10023 if (index < tokens.length) { 10024 String str = tokens[index]; 10025 if (str != null && str.length() > 0) { 10026 try { 10027 int val = Integer.parseInt(str); 10028 return val; 10029 } catch (Exception e) { 10030 } 10031 } 10032 } 10033 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 10034 return defDps; 10035 } 10036 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 10037 return val; 10038 } 10039 10040 class Watermark { 10041 final String[] mTokens; 10042 final String mText; 10043 final Paint mTextPaint; 10044 final int mTextWidth; 10045 final int mTextHeight; 10046 final int mTextAscent; 10047 final int mTextDescent; 10048 final int mDeltaX; 10049 final int mDeltaY; 10050 10051 Surface mSurface; 10052 int mLastDW; 10053 int mLastDH; 10054 boolean mDrawNeeded; 10055 10056 Watermark(SurfaceSession session, String[] tokens) { 10057 final DisplayMetrics dm = new DisplayMetrics(); 10058 mDisplay.getMetrics(dm); 10059 10060 if (false) { 10061 Log.i(TAG, "*********************** WATERMARK"); 10062 for (int i=0; i<tokens.length; i++) { 10063 Log.i(TAG, " TOKEN #" + i + ": " + tokens[i]); 10064 } 10065 } 10066 10067 mTokens = tokens; 10068 10069 StringBuilder builder = new StringBuilder(32); 10070 int len = mTokens[0].length(); 10071 len = len & ~1; 10072 for (int i=0; i<len; i+=2) { 10073 int c1 = mTokens[0].charAt(i); 10074 int c2 = mTokens[0].charAt(i+1); 10075 if (c1 >= 'a' && c1 <= 'f') c1 = c1 - 'a' + 10; 10076 else if (c1 >= 'A' && c1 <= 'F') c1 = c1 - 'A' + 10; 10077 else c1 -= '0'; 10078 if (c2 >= 'a' && c2 <= 'f') c2 = c2 - 'a' + 10; 10079 else if (c2 >= 'A' && c2 <= 'F') c2 = c2 - 'A' + 10; 10080 else c2 -= '0'; 10081 builder.append((char)(255-((c1*16)+c2))); 10082 } 10083 mText = builder.toString(); 10084 if (false) { 10085 Log.i(TAG, "Final text: " + mText); 10086 } 10087 10088 int fontSize = getPropertyInt(tokens, 1, 10089 TypedValue.COMPLEX_UNIT_DIP, 20, dm); 10090 10091 mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 10092 mTextPaint.setTextSize(fontSize); 10093 mTextPaint.setTypeface(Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)); 10094 10095 FontMetricsInt fm = mTextPaint.getFontMetricsInt(); 10096 mTextWidth = (int)mTextPaint.measureText(mText); 10097 mTextAscent = fm.ascent; 10098 mTextDescent = fm.descent; 10099 mTextHeight = fm.descent - fm.ascent; 10100 10101 mDeltaX = getPropertyInt(tokens, 2, 10102 TypedValue.COMPLEX_UNIT_PX, mTextWidth*2, dm); 10103 mDeltaY = getPropertyInt(tokens, 3, 10104 TypedValue.COMPLEX_UNIT_PX, mTextHeight*3, dm); 10105 int shadowColor = getPropertyInt(tokens, 4, 10106 TypedValue.COMPLEX_UNIT_PX, 0xb0000000, dm); 10107 int color = getPropertyInt(tokens, 5, 10108 TypedValue.COMPLEX_UNIT_PX, 0x60ffffff, dm); 10109 int shadowRadius = getPropertyInt(tokens, 6, 10110 TypedValue.COMPLEX_UNIT_PX, 7, dm); 10111 int shadowDx = getPropertyInt(tokens, 8, 10112 TypedValue.COMPLEX_UNIT_PX, 0, dm); 10113 int shadowDy = getPropertyInt(tokens, 9, 10114 TypedValue.COMPLEX_UNIT_PX, 0, dm); 10115 10116 mTextPaint.setColor(color); 10117 mTextPaint.setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor); 10118 10119 try { 10120 mSurface = new Surface(session, 0, 10121 "WatermarkSurface", -1, 1, 1, PixelFormat.TRANSLUCENT, 0); 10122 mSurface.setLayer(TYPE_LAYER_MULTIPLIER*100); 10123 mSurface.setPosition(0, 0); 10124 mSurface.show(); 10125 } catch (OutOfResourcesException e) { 10126 } 10127 } 10128 10129 void positionSurface(int dw, int dh) { 10130 if (mLastDW != dw || mLastDH != dh) { 10131 mLastDW = dw; 10132 mLastDH = dh; 10133 mSurface.setSize(dw, dh); 10134 mDrawNeeded = true; 10135 } 10136 } 10137 10138 void drawIfNeeded() { 10139 if (mDrawNeeded) { 10140 final int dw = mLastDW; 10141 final int dh = mLastDH; 10142 10143 mDrawNeeded = false; 10144 Rect dirty = new Rect(0, 0, dw, dh); 10145 Canvas c = null; 10146 try { 10147 c = mSurface.lockCanvas(dirty); 10148 } catch (IllegalArgumentException e) { 10149 } catch (OutOfResourcesException e) { 10150 } 10151 if (c != null) { 10152 int deltaX = mDeltaX; 10153 int deltaY = mDeltaY; 10154 10155 // deltaX shouldn't be close to a round fraction of our 10156 // x step, or else things will line up too much. 10157 int div = (dw+mTextWidth)/deltaX; 10158 int rem = (dw+mTextWidth) - (div*deltaX); 10159 int qdelta = deltaX/4; 10160 if (rem < qdelta || rem > (deltaX-qdelta)) { 10161 deltaX += deltaX/3; 10162 } 10163 10164 int y = -mTextHeight; 10165 int x = -mTextWidth; 10166 while (y < (dh+mTextHeight)) { 10167 c.drawText(mText, x, y, mTextPaint); 10168 x += deltaX; 10169 if (x >= dw) { 10170 x -= (dw+mTextWidth); 10171 y += deltaY; 10172 } 10173 } 10174 mSurface.unlockCanvasAndPost(c); 10175 } 10176 } 10177 } 10178 } 10179 10180 void createWatermark() { 10181 if (mWatermark != null) { 10182 return; 10183 } 10184 10185 File file = new File("/system/etc/setup.conf"); 10186 FileInputStream in = null; 10187 try { 10188 in = new FileInputStream(file); 10189 DataInputStream ind = new DataInputStream(in); 10190 String line = ind.readLine(); 10191 if (line != null) { 10192 String[] toks = line.split("%"); 10193 if (toks != null && toks.length > 0) { 10194 mWatermark = new Watermark(mFxSession, toks); 10195 } 10196 } 10197 } catch (FileNotFoundException e) { 10198 } catch (IOException e) { 10199 } finally { 10200 if (in != null) { 10201 try { 10202 in.close(); 10203 } catch (IOException e) { 10204 } 10205 } 10206 } 10207 } 10208 10209 @Override 10210 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10211 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10212 != PackageManager.PERMISSION_GRANTED) { 10213 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10214 + Binder.getCallingPid() 10215 + ", uid=" + Binder.getCallingUid()); 10216 return; 10217 } 10218 10219 mInputManager.dump(pw); 10220 pw.println(" "); 10221 10222 synchronized(mWindowMap) { 10223 pw.println("Current Window Manager state:"); 10224 for (int i=mWindows.size()-1; i>=0; i--) { 10225 WindowState w = mWindows.get(i); 10226 pw.print(" Window #"); pw.print(i); pw.print(' '); 10227 pw.print(w); pw.println(":"); 10228 w.dump(pw, " "); 10229 } 10230 if (mInputMethodDialogs.size() > 0) { 10231 pw.println(" "); 10232 pw.println(" Input method dialogs:"); 10233 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 10234 WindowState w = mInputMethodDialogs.get(i); 10235 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 10236 } 10237 } 10238 if (mPendingRemove.size() > 0) { 10239 pw.println(" "); 10240 pw.println(" Remove pending for:"); 10241 for (int i=mPendingRemove.size()-1; i>=0; i--) { 10242 WindowState w = mPendingRemove.get(i); 10243 pw.print(" Remove #"); pw.print(i); pw.print(' '); 10244 pw.print(w); pw.println(":"); 10245 w.dump(pw, " "); 10246 } 10247 } 10248 if (mForceRemoves != null && mForceRemoves.size() > 0) { 10249 pw.println(" "); 10250 pw.println(" Windows force removing:"); 10251 for (int i=mForceRemoves.size()-1; i>=0; i--) { 10252 WindowState w = mForceRemoves.get(i); 10253 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10254 pw.print(w); pw.println(":"); 10255 w.dump(pw, " "); 10256 } 10257 } 10258 if (mDestroySurface.size() > 0) { 10259 pw.println(" "); 10260 pw.println(" Windows waiting to destroy their surface:"); 10261 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10262 WindowState w = mDestroySurface.get(i); 10263 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10264 pw.print(w); pw.println(":"); 10265 w.dump(pw, " "); 10266 } 10267 } 10268 if (mLosingFocus.size() > 0) { 10269 pw.println(" "); 10270 pw.println(" Windows losing focus:"); 10271 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10272 WindowState w = mLosingFocus.get(i); 10273 pw.print(" Losing #"); pw.print(i); pw.print(' '); 10274 pw.print(w); pw.println(":"); 10275 w.dump(pw, " "); 10276 } 10277 } 10278 if (mResizingWindows.size() > 0) { 10279 pw.println(" "); 10280 pw.println(" Windows waiting to resize:"); 10281 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10282 WindowState w = mResizingWindows.get(i); 10283 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 10284 pw.print(w); pw.println(":"); 10285 w.dump(pw, " "); 10286 } 10287 } 10288 if (mSessions.size() > 0) { 10289 pw.println(" "); 10290 pw.println(" All active sessions:"); 10291 Iterator<Session> it = mSessions.iterator(); 10292 while (it.hasNext()) { 10293 Session s = it.next(); 10294 pw.print(" Session "); pw.print(s); pw.println(':'); 10295 s.dump(pw, " "); 10296 } 10297 } 10298 if (mTokenMap.size() > 0) { 10299 pw.println(" "); 10300 pw.println(" All tokens:"); 10301 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10302 while (it.hasNext()) { 10303 WindowToken token = it.next(); 10304 pw.print(" Token "); pw.print(token.token); pw.println(':'); 10305 token.dump(pw, " "); 10306 } 10307 } 10308 if (mTokenList.size() > 0) { 10309 pw.println(" "); 10310 pw.println(" Window token list:"); 10311 for (int i=0; i<mTokenList.size(); i++) { 10312 pw.print(" #"); pw.print(i); pw.print(": "); 10313 pw.println(mTokenList.get(i)); 10314 } 10315 } 10316 if (mWallpaperTokens.size() > 0) { 10317 pw.println(" "); 10318 pw.println(" Wallpaper tokens:"); 10319 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 10320 WindowToken token = mWallpaperTokens.get(i); 10321 pw.print(" Wallpaper #"); pw.print(i); 10322 pw.print(' '); pw.print(token); pw.println(':'); 10323 token.dump(pw, " "); 10324 } 10325 } 10326 if (mAppTokens.size() > 0) { 10327 pw.println(" "); 10328 pw.println(" Application tokens in Z order:"); 10329 for (int i=mAppTokens.size()-1; i>=0; i--) { 10330 pw.print(" App #"); pw.print(i); pw.print(": "); 10331 pw.println(mAppTokens.get(i)); 10332 } 10333 } 10334 if (mFinishedStarting.size() > 0) { 10335 pw.println(" "); 10336 pw.println(" Finishing start of application tokens:"); 10337 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10338 WindowToken token = mFinishedStarting.get(i); 10339 pw.print(" Finished Starting #"); pw.print(i); 10340 pw.print(' '); pw.print(token); pw.println(':'); 10341 token.dump(pw, " "); 10342 } 10343 } 10344 if (mExitingTokens.size() > 0) { 10345 pw.println(" "); 10346 pw.println(" Exiting tokens:"); 10347 for (int i=mExitingTokens.size()-1; i>=0; i--) { 10348 WindowToken token = mExitingTokens.get(i); 10349 pw.print(" Exiting #"); pw.print(i); 10350 pw.print(' '); pw.print(token); pw.println(':'); 10351 token.dump(pw, " "); 10352 } 10353 } 10354 if (mExitingAppTokens.size() > 0) { 10355 pw.println(" "); 10356 pw.println(" Exiting application tokens:"); 10357 for (int i=mExitingAppTokens.size()-1; i>=0; i--) { 10358 WindowToken token = mExitingAppTokens.get(i); 10359 pw.print(" Exiting App #"); pw.print(i); 10360 pw.print(' '); pw.print(token); pw.println(':'); 10361 token.dump(pw, " "); 10362 } 10363 } 10364 pw.println(" "); 10365 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10366 pw.print(" mLastFocus="); pw.println(mLastFocus); 10367 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10368 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10369 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10370 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 10371 if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) { 10372 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 10373 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 10374 } 10375 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10376 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10377 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10378 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10379 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10380 pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded); 10381 pw.print(" mBlurShown="); pw.println(mBlurShown); 10382 if (mDimAnimator != null) { 10383 mDimAnimator.printTo(pw); 10384 } else { 10385 pw.println( " no DimAnimator "); 10386 } 10387 pw.print(" mInputMethodAnimLayerAdjustment="); 10388 pw.print(mInputMethodAnimLayerAdjustment); 10389 pw.print(" mWallpaperAnimLayerAdjustment="); 10390 pw.println(mWallpaperAnimLayerAdjustment); 10391 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 10392 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 10393 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10394 pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen); 10395 pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen); 10396 pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig); 10397 pw.print(" mRotation="); pw.print(mRotation); 10398 pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation); 10399 pw.print(", mRequestedRotation="); pw.println(mRequestedRotation); 10400 pw.print(" mAnimationPending="); pw.print(mAnimationPending); 10401 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); 10402 pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale); 10403 pw.print(" mNextAppTransition=0x"); 10404 pw.print(Integer.toHexString(mNextAppTransition)); 10405 pw.print(", mAppTransitionReady="); pw.print(mAppTransitionReady); 10406 pw.print(", mAppTransitionRunning="); pw.print(mAppTransitionRunning); 10407 pw.print(", mAppTransitionTimeout="); pw.println( mAppTransitionTimeout); 10408 if (mNextAppTransitionPackage != null) { 10409 pw.print(" mNextAppTransitionPackage="); 10410 pw.print(mNextAppTransitionPackage); 10411 pw.print(", mNextAppTransitionEnter=0x"); 10412 pw.print(Integer.toHexString(mNextAppTransitionEnter)); 10413 pw.print(", mNextAppTransitionExit=0x"); 10414 pw.print(Integer.toHexString(mNextAppTransitionExit)); 10415 } 10416 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 10417 pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 10418 if (mLastEnterAnimToken != null || mLastEnterAnimToken != null) { 10419 pw.print(" mLastEnterAnimToken="); pw.print(mLastEnterAnimToken); 10420 pw.print(", mLastEnterAnimParams="); pw.println(mLastEnterAnimParams); 10421 } 10422 if (mOpeningApps.size() > 0) { 10423 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10424 } 10425 if (mClosingApps.size() > 0) { 10426 pw.print(" mClosingApps="); pw.println(mClosingApps); 10427 } 10428 if (mToTopApps.size() > 0) { 10429 pw.print(" mToTopApps="); pw.println(mToTopApps); 10430 } 10431 if (mToBottomApps.size() > 0) { 10432 pw.print(" mToBottomApps="); pw.println(mToBottomApps); 10433 } 10434 pw.print(" DisplayWidth="); pw.print(mDisplay.getWidth()); 10435 pw.print(" DisplayHeight="); pw.println(mDisplay.getHeight()); 10436 } 10437 } 10438 10439 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10440 public void monitor() { 10441 synchronized (mWindowMap) { } 10442 synchronized (mKeyguardTokenWatcher) { } 10443 } 10444 10445 /** 10446 * DimAnimator class that controls the dim animation. This holds the surface and 10447 * all state used for dim animation. 10448 */ 10449 private static class DimAnimator { 10450 Surface mDimSurface; 10451 boolean mDimShown = false; 10452 float mDimCurrentAlpha; 10453 float mDimTargetAlpha; 10454 float mDimDeltaPerMs; 10455 long mLastDimAnimTime; 10456 10457 int mLastDimWidth, mLastDimHeight; 10458 10459 DimAnimator (SurfaceSession session) { 10460 if (mDimSurface == null) { 10461 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " 10462 + mDimSurface + ": CREATE"); 10463 try { 10464 mDimSurface = new Surface(session, 0, 10465 "DimSurface", 10466 -1, 16, 16, PixelFormat.OPAQUE, 10467 Surface.FX_SURFACE_DIM); 10468 mDimSurface.setAlpha(0.0f); 10469 } catch (Exception e) { 10470 Slog.e(TAG, "Exception creating Dim surface", e); 10471 } 10472 } 10473 } 10474 10475 /** 10476 * Show the dim surface. 10477 */ 10478 void show(int dw, int dh) { 10479 if (!mDimShown) { 10480 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" + 10481 dw + "x" + dh + ")"); 10482 mDimShown = true; 10483 try { 10484 mLastDimWidth = dw; 10485 mLastDimHeight = dh; 10486 mDimSurface.setPosition(0, 0); 10487 mDimSurface.setSize(dw, dh); 10488 mDimSurface.show(); 10489 } catch (RuntimeException e) { 10490 Slog.w(TAG, "Failure showing dim surface", e); 10491 } 10492 } else if (mLastDimWidth != dw || mLastDimHeight != dh) { 10493 mLastDimWidth = dw; 10494 mLastDimHeight = dh; 10495 mDimSurface.setSize(dw, dh); 10496 } 10497 } 10498 10499 /** 10500 * Set's the dim surface's layer and update dim parameters that will be used in 10501 * {@link updateSurface} after all windows are examined. 10502 */ 10503 void updateParameters(WindowState w, long currentTime) { 10504 mDimSurface.setLayer(w.mAnimLayer-1); 10505 10506 final float target = w.mExiting ? 0 : w.mAttrs.dimAmount; 10507 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface 10508 + ": layer=" + (w.mAnimLayer-1) + " target=" + target); 10509 if (mDimTargetAlpha != target) { 10510 // If the desired dim level has changed, then 10511 // start an animation to it. 10512 mLastDimAnimTime = currentTime; 10513 long duration = (w.mAnimating && w.mAnimation != null) 10514 ? w.mAnimation.computeDurationHint() 10515 : DEFAULT_DIM_DURATION; 10516 if (target > mDimTargetAlpha) { 10517 // This is happening behind the activity UI, 10518 // so we can make it run a little longer to 10519 // give a stronger impression without disrupting 10520 // the user. 10521 duration *= DIM_DURATION_MULTIPLIER; 10522 } 10523 if (duration < 1) { 10524 // Don't divide by zero 10525 duration = 1; 10526 } 10527 mDimTargetAlpha = target; 10528 mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration; 10529 } 10530 } 10531 10532 /** 10533 * Updating the surface's alpha. Returns true if the animation continues, or returns 10534 * false when the animation is finished and the dim surface is hidden. 10535 */ 10536 boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) { 10537 if (!dimming) { 10538 if (mDimTargetAlpha != 0) { 10539 mLastDimAnimTime = currentTime; 10540 mDimTargetAlpha = 0; 10541 mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION; 10542 } 10543 } 10544 10545 boolean animating = false; 10546 if (mLastDimAnimTime != 0) { 10547 mDimCurrentAlpha += mDimDeltaPerMs 10548 * (currentTime-mLastDimAnimTime); 10549 boolean more = true; 10550 if (displayFrozen) { 10551 // If the display is frozen, there is no reason to animate. 10552 more = false; 10553 } else if (mDimDeltaPerMs > 0) { 10554 if (mDimCurrentAlpha > mDimTargetAlpha) { 10555 more = false; 10556 } 10557 } else if (mDimDeltaPerMs < 0) { 10558 if (mDimCurrentAlpha < mDimTargetAlpha) { 10559 more = false; 10560 } 10561 } else { 10562 more = false; 10563 } 10564 10565 // Do we need to continue animating? 10566 if (more) { 10567 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " 10568 + mDimSurface + ": alpha=" + mDimCurrentAlpha); 10569 mLastDimAnimTime = currentTime; 10570 mDimSurface.setAlpha(mDimCurrentAlpha); 10571 animating = true; 10572 } else { 10573 mDimCurrentAlpha = mDimTargetAlpha; 10574 mLastDimAnimTime = 0; 10575 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " 10576 + mDimSurface + ": final alpha=" + mDimCurrentAlpha); 10577 mDimSurface.setAlpha(mDimCurrentAlpha); 10578 if (!dimming) { 10579 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface 10580 + ": HIDE"); 10581 try { 10582 mDimSurface.hide(); 10583 } catch (RuntimeException e) { 10584 Slog.w(TAG, "Illegal argument exception hiding dim surface"); 10585 } 10586 mDimShown = false; 10587 } 10588 } 10589 } 10590 return animating; 10591 } 10592 10593 public void printTo(PrintWriter pw) { 10594 pw.print(" mDimShown="); pw.print(mDimShown); 10595 pw.print(" current="); pw.print(mDimCurrentAlpha); 10596 pw.print(" target="); pw.print(mDimTargetAlpha); 10597 pw.print(" delta="); pw.print(mDimDeltaPerMs); 10598 pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime); 10599 } 10600 } 10601 10602 /** 10603 * Animation that fade in after 0.5 interpolate time, or fade out in reverse order. 10604 * This is used for opening/closing transition for apps in compatible mode. 10605 */ 10606 private static class FadeInOutAnimation extends Animation { 10607 int mWidth; 10608 boolean mFadeIn; 10609 10610 public FadeInOutAnimation(boolean fadeIn) { 10611 setInterpolator(new AccelerateInterpolator()); 10612 setDuration(DEFAULT_FADE_IN_OUT_DURATION); 10613 mFadeIn = fadeIn; 10614 } 10615 10616 @Override 10617 protected void applyTransformation(float interpolatedTime, Transformation t) { 10618 float x = interpolatedTime; 10619 if (!mFadeIn) { 10620 x = 1.0f - x; // reverse the interpolation for fade out 10621 } 10622 if (x < 0.5) { 10623 // move the window out of the screen. 10624 t.getMatrix().setTranslate(mWidth, 0); 10625 } else { 10626 t.getMatrix().setTranslate(0, 0);// show 10627 t.setAlpha((x - 0.5f) * 2); 10628 } 10629 } 10630 10631 @Override 10632 public void initialize(int width, int height, int parentWidth, int parentHeight) { 10633 // width is the screen width {@see AppWindowToken#stepAnimatinoLocked} 10634 mWidth = width; 10635 } 10636 10637 @Override 10638 public int getZAdjustment() { 10639 return Animation.ZORDER_TOP; 10640 } 10641 } 10642 } 10643