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