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