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