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