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