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