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