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