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