WindowManagerService.java revision 7b5a96ba8364d5c180780b2f878f5a2b949cfdac
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.*; 20 21import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 22import android.app.AppOpsManager; 23import android.util.ArraySet; 24import android.util.TimeUtils; 25import android.view.IWindowId; 26 27import android.view.IWindowSessionCallback; 28import android.view.WindowContentFrameStats; 29import com.android.internal.app.IBatteryStats; 30import com.android.internal.policy.PolicyManager; 31import com.android.internal.policy.impl.PhoneWindowManager; 32import com.android.internal.util.FastPrintWriter; 33import com.android.internal.view.IInputContext; 34import com.android.internal.view.IInputMethodClient; 35import com.android.internal.view.IInputMethodManager; 36import com.android.internal.view.WindowManagerPolicyThread; 37import com.android.server.AttributeCache; 38import com.android.server.DisplayThread; 39import com.android.server.EventLogTags; 40import com.android.server.LocalServices; 41import com.android.server.UiThread; 42import com.android.server.Watchdog; 43import com.android.server.am.BatteryStatsService; 44import com.android.server.input.InputManagerService; 45import com.android.server.power.ShutdownThread; 46 47import android.Manifest; 48import android.app.ActivityManagerNative; 49import android.app.IActivityManager; 50import android.app.StatusBarManager; 51import android.app.admin.DevicePolicyManager; 52import android.animation.ValueAnimator; 53import android.content.BroadcastReceiver; 54import android.content.ContentResolver; 55import android.content.Context; 56import android.content.Intent; 57import android.content.IntentFilter; 58import android.content.pm.ActivityInfo; 59import android.content.pm.PackageManager; 60import android.content.res.CompatibilityInfo; 61import android.content.res.Configuration; 62import android.database.ContentObserver; 63import android.graphics.Bitmap; 64import android.graphics.Bitmap.Config; 65import android.graphics.Canvas; 66import android.graphics.Matrix; 67import android.graphics.PixelFormat; 68import android.graphics.Point; 69import android.graphics.Rect; 70import android.graphics.RectF; 71import android.graphics.Region; 72import android.hardware.display.DisplayManager; 73import android.hardware.display.DisplayManagerInternal; 74import android.os.Binder; 75import android.os.Bundle; 76import android.os.Debug; 77import android.os.Handler; 78import android.os.IBinder; 79import android.os.IRemoteCallback; 80import android.os.Looper; 81import android.os.Message; 82import android.os.Parcel; 83import android.os.ParcelFileDescriptor; 84import android.os.PowerManager; 85import android.os.PowerManagerInternal; 86import android.os.Process; 87import android.os.RemoteException; 88import android.os.ServiceManager; 89import android.os.StrictMode; 90import android.os.SystemClock; 91import android.os.SystemProperties; 92import android.os.Trace; 93import android.os.UserHandle; 94import android.os.WorkSource; 95import android.provider.Settings; 96import android.util.DisplayMetrics; 97import android.util.EventLog; 98import android.util.FloatMath; 99import android.util.Log; 100import android.util.SparseArray; 101import android.util.Pair; 102import android.util.Slog; 103import android.util.SparseIntArray; 104import android.util.TypedValue; 105import android.view.Choreographer; 106import android.view.Display; 107import android.view.DisplayInfo; 108import android.view.Gravity; 109import android.view.IApplicationToken; 110import android.view.IInputFilter; 111import android.view.IOnKeyguardExitResult; 112import android.view.IRotationWatcher; 113import android.view.IWindow; 114import android.view.IWindowManager; 115import android.view.IWindowSession; 116import android.view.InputChannel; 117import android.view.InputDevice; 118import android.view.InputEvent; 119import android.view.InputEventReceiver; 120import android.view.KeyEvent; 121import android.view.MagnificationSpec; 122import android.view.MotionEvent; 123import android.view.WindowManagerInternal; 124import android.view.Surface.OutOfResourcesException; 125import android.view.Surface; 126import android.view.SurfaceControl; 127import android.view.SurfaceSession; 128import android.view.View; 129import android.view.ViewTreeObserver; 130import android.view.WindowManager; 131import android.view.WindowManagerGlobal; 132import android.view.WindowManagerPolicy; 133import android.view.WindowManager.LayoutParams; 134import android.view.WindowManagerPolicy.FakeWindow; 135import android.view.WindowManagerPolicy.PointerEventListener; 136import android.view.animation.Animation; 137import android.view.animation.AnimationUtils; 138import android.view.animation.Transformation; 139 140import java.io.BufferedWriter; 141import java.io.DataInputStream; 142import java.io.File; 143import java.io.FileDescriptor; 144import java.io.FileInputStream; 145import java.io.FileNotFoundException; 146import java.io.IOException; 147import java.io.OutputStream; 148import java.io.OutputStreamWriter; 149import java.io.PrintWriter; 150import java.io.StringWriter; 151import java.net.Socket; 152import java.text.DateFormat; 153import java.util.ArrayList; 154import java.util.Date; 155import java.util.HashMap; 156import java.util.Iterator; 157import java.util.List; 158 159/** {@hide} */ 160public class WindowManagerService extends IWindowManager.Stub 161 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs { 162 static final String TAG = "WindowManager"; 163 static final boolean DEBUG = false; 164 static final boolean DEBUG_ADD_REMOVE = false; 165 static final boolean DEBUG_FOCUS = false; 166 static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false; 167 static final boolean DEBUG_ANIM = false; 168 static final boolean DEBUG_LAYOUT = false; 169 static final boolean DEBUG_RESIZE = false; 170 static final boolean DEBUG_LAYERS = false; 171 static final boolean DEBUG_INPUT = false; 172 static final boolean DEBUG_INPUT_METHOD = false; 173 static final boolean DEBUG_VISIBILITY = false; 174 static final boolean DEBUG_WINDOW_MOVEMENT = false; 175 static final boolean DEBUG_TOKEN_MOVEMENT = false; 176 static final boolean DEBUG_ORIENTATION = false; 177 static final boolean DEBUG_APP_ORIENTATION = false; 178 static final boolean DEBUG_CONFIGURATION = false; 179 static final boolean DEBUG_APP_TRANSITIONS = false; 180 static final boolean DEBUG_STARTING_WINDOW = false; 181 static final boolean DEBUG_REORDER = false; 182 static final boolean DEBUG_WALLPAPER = false; 183 static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER; 184 static final boolean DEBUG_DRAG = false; 185 static final boolean DEBUG_SCREEN_ON = false; 186 static final boolean DEBUG_SCREENSHOT = false; 187 static final boolean DEBUG_BOOT = false; 188 static final boolean DEBUG_LAYOUT_REPEATS = true; 189 static final boolean DEBUG_SURFACE_TRACE = false; 190 static final boolean DEBUG_WINDOW_TRACE = false; 191 static final boolean DEBUG_TASK_MOVEMENT = false; 192 static final boolean DEBUG_STACK = false; 193 static final boolean DEBUG_DISPLAY = false; 194 static final boolean SHOW_SURFACE_ALLOC = false; 195 static final boolean SHOW_TRANSACTIONS = false; 196 static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS; 197 static final boolean HIDE_STACK_CRAWLS = true; 198 static final int LAYOUT_REPEAT_THRESHOLD = 4; 199 200 static final boolean PROFILE_ORIENTATION = false; 201 static final boolean localLOGV = DEBUG; 202 203 /** How much to multiply the policy's type layer, to reserve room 204 * for multiple windows of the same type and Z-ordering adjustment 205 * with TYPE_LAYER_OFFSET. */ 206 static final int TYPE_LAYER_MULTIPLIER = 10000; 207 208 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above 209 * or below others in the same layer. */ 210 static final int TYPE_LAYER_OFFSET = 1000; 211 212 /** How much to increment the layer for each window, to reserve room 213 * for effect surfaces between them. 214 */ 215 static final int WINDOW_LAYER_MULTIPLIER = 5; 216 217 /** 218 * Dim surface layer is immediately below target window. 219 */ 220 static final int LAYER_OFFSET_DIM = 1; 221 222 /** 223 * Blur surface layer is immediately below dim layer. 224 */ 225 static final int LAYER_OFFSET_BLUR = 2; 226 227 /** 228 * FocusedStackFrame layer is immediately above focused window. 229 */ 230 static final int LAYER_OFFSET_FOCUSED_STACK = 1; 231 232 /** 233 * Animation thumbnail is as far as possible below the window above 234 * the thumbnail (or in other words as far as possible above the window 235 * below it). 236 */ 237 static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER-1; 238 239 /** 240 * Layer at which to put the rotation freeze snapshot. 241 */ 242 static final int FREEZE_LAYER = (TYPE_LAYER_MULTIPLIER * 200) + 1; 243 244 /** 245 * Layer at which to put the mask for emulated screen sizes. 246 */ 247 static final int MASK_LAYER = TYPE_LAYER_MULTIPLIER * 200; 248 249 /** The maximum length we will accept for a loaded animation duration: 250 * this is 10 seconds. 251 */ 252 static final int MAX_ANIMATION_DURATION = 10*1000; 253 254 /** Amount of time (in milliseconds) to animate the fade-in-out transition for 255 * compatible windows. 256 */ 257 static final int DEFAULT_FADE_IN_OUT_DURATION = 400; 258 259 /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */ 260 static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000; 261 262 /** 263 * If true, the window manager will do its own custom freezing and general 264 * management of the screen during rotation. 265 */ 266 static final boolean CUSTOM_SCREEN_ROTATION = true; 267 268 // Maximum number of milliseconds to wait for input devices to be enumerated before 269 // proceding with safe mode detection. 270 private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000; 271 272 // Default input dispatching timeout in nanoseconds. 273 static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L; 274 275 /** Minimum value for attachStack and resizeStack weight value */ 276 public static final float STACK_WEIGHT_MIN = 0.2f; 277 278 /** Maximum value for attachStack and resizeStack weight value */ 279 public static final float STACK_WEIGHT_MAX = 0.8f; 280 281 static final int UPDATE_FOCUS_NORMAL = 0; 282 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1; 283 static final int UPDATE_FOCUS_PLACING_SURFACES = 2; 284 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3; 285 286 private static final String SYSTEM_SECURE = "ro.secure"; 287 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; 288 289 private static final String DENSITY_OVERRIDE = "ro.config.density_override"; 290 private static final String SIZE_OVERRIDE = "ro.config.size_override"; 291 292 private static final int MAX_SCREENSHOT_RETRIES = 3; 293 294 // The flag describing a full screen app window (where the app takes care of drawing under the 295 // SystemUI bars) 296 private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN = 297 View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 298 299 final private KeyguardDisableHandler mKeyguardDisableHandler; 300 301 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 302 @Override 303 public void onReceive(Context context, Intent intent) { 304 final String action = intent.getAction(); 305 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) { 306 mKeyguardDisableHandler.sendEmptyMessage( 307 KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED); 308 } 309 } 310 }; 311 312 /** 313 * Current user when multi-user is enabled. Don't show windows of 314 * non-current user. Also see mCurrentProfileIds. 315 */ 316 int mCurrentUserId; 317 /** 318 * Users that are profiles of the current user. These are also allowed to show windows 319 * on the current user. 320 */ 321 int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER}; 322 323 final Context mContext; 324 325 final boolean mHaveInputMethods; 326 327 final boolean mAllowBootMessages; 328 329 final boolean mLimitedAlphaCompositing; 330 331 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager(); 332 333 final IActivityManager mActivityManager; 334 335 final IBatteryStats mBatteryStats; 336 337 final AppOpsManager mAppOps; 338 339 final DisplaySettings mDisplaySettings; 340 341 /** 342 * All currently active sessions with clients. 343 */ 344 final ArraySet<Session> mSessions = new ArraySet<Session>(); 345 346 /** 347 * Mapping from an IWindow IBinder to the server's Window object. 348 * This is also used as the lock for all of our state. 349 * NOTE: Never call into methods that lock ActivityManagerService while holding this object. 350 */ 351 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>(); 352 353 /** 354 * Mapping from a token IBinder to a WindowToken object. 355 */ 356 final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>(); 357 358 /** 359 * List of window tokens that have finished starting their application, 360 * and now need to have the policy remove their windows. 361 */ 362 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>(); 363 364 /** 365 * Fake windows added to the window manager. Note: ordered from top to 366 * bottom, opposite of mWindows. 367 */ 368 final ArrayList<FakeWindowImpl> mFakeWindows = new ArrayList<FakeWindowImpl>(); 369 370 /** 371 * Windows that are being resized. Used so we can tell the client about 372 * the resize after closing the transaction in which we resized the 373 * underlying surface. 374 */ 375 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>(); 376 377 /** 378 * Windows whose animations have ended and now must be removed. 379 */ 380 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>(); 381 382 /** 383 * Stacks whose animations have ended and whose tasks, apps, selves may now be removed. 384 */ 385 final ArraySet<TaskStack> mPendingStacksRemove = new ArraySet<TaskStack>(); 386 387 /** 388 * Used when processing mPendingRemove to avoid working on the original array. 389 */ 390 WindowState[] mPendingRemoveTmp = new WindowState[20]; 391 392 /** 393 * Windows whose surface should be destroyed. 394 */ 395 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>(); 396 397 /** 398 * Windows that have lost input focus and are waiting for the new 399 * focus window to be displayed before they are told about this. 400 */ 401 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>(); 402 403 /** 404 * This is set when we have run out of memory, and will either be an empty 405 * list or contain windows that need to be force removed. 406 */ 407 ArrayList<WindowState> mForceRemoves; 408 409 /** 410 * Windows that clients are waiting to have drawn. 411 */ 412 ArrayList<WindowState> mWaitingForDrawn = new ArrayList<WindowState>(); 413 /** 414 * And the callback to make when they've all been drawn. 415 */ 416 Runnable mWaitingForDrawnCallback; 417 418 /** 419 * Windows that have called relayout() while we were running animations, 420 * so we need to tell when the animation is done. 421 */ 422 final ArrayList<WindowState> mRelayoutWhileAnimating = new ArrayList<WindowState>(); 423 424 /** 425 * Used when rebuilding window list to keep track of windows that have 426 * been removed. 427 */ 428 WindowState[] mRebuildTmp = new WindowState[20]; 429 430 /** 431 * Stores for each user whether screencapture is disabled 432 * This array is essentially a cache for all userId for 433 * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled(null, userId)} 434 */ 435 SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<Boolean>(); 436 437 IInputMethodManager mInputMethodManager; 438 439 AccessibilityController mAccessibilityController; 440 441 final SurfaceSession mFxSession; 442 Watermark mWatermark; 443 StrictModeFlash mStrictModeFlash; 444 CircularDisplayMask mCircularDisplayMask; 445 FocusedStackFrame mFocusedStackFrame; 446 447 int mFocusedStackLayer; 448 449 final float[] mTmpFloats = new float[9]; 450 final Rect mTmpContentRect = new Rect(); 451 452 boolean mDisplayReady; 453 boolean mSafeMode; 454 boolean mDisplayEnabled = false; 455 boolean mSystemBooted = false; 456 boolean mForceDisplayEnabled = false; 457 boolean mShowingBootMessages = false; 458 459 String mLastANRState; 460 461 /** All DisplayContents in the world, kept here */ 462 SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>(2); 463 464 int mRotation = 0; 465 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 466 boolean mAltOrientation = false; 467 468 private boolean mKeyguardWaitingForActivityDrawn; 469 470 class RotationWatcher { 471 IRotationWatcher watcher; 472 IBinder.DeathRecipient deathRecipient; 473 RotationWatcher(IRotationWatcher w, IBinder.DeathRecipient d) { 474 watcher = w; 475 deathRecipient = d; 476 } 477 } 478 ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<RotationWatcher>(); 479 int mDeferredRotationPauseCount; 480 481 int mSystemDecorLayer = 0; 482 final Rect mScreenRect = new Rect(); 483 484 boolean mTraversalScheduled = false; 485 boolean mDisplayFrozen = false; 486 long mDisplayFreezeTime = 0; 487 int mLastDisplayFreezeDuration = 0; 488 Object mLastFinishedFreezeSource = null; 489 boolean mWaitingForConfig = false; 490 boolean mWindowsFreezingScreen = false; 491 boolean mClientFreezingScreen = false; 492 int mAppsFreezingScreen = 0; 493 int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 494 495 int mLayoutSeq = 0; 496 497 int mLastStatusBarVisibility = 0; 498 499 // State while inside of layoutAndPlaceSurfacesLocked(). 500 boolean mFocusMayChange; 501 502 Configuration mCurConfiguration = new Configuration(); 503 504 // This is held as long as we have the screen frozen, to give us time to 505 // perform a rotation animation when turning off shows the lock screen which 506 // changes the orientation. 507 private final PowerManager.WakeLock mScreenFrozenLock; 508 509 final AppTransition mAppTransition; 510 boolean mStartingIconInTransition = false; 511 boolean mSkipAppTransitionAnimation = false; 512 513 final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<AppWindowToken>(); 514 final ArraySet<AppWindowToken> mClosingApps = new ArraySet<AppWindowToken>(); 515 516 boolean mIsTouchDevice; 517 518 final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 519 final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics(); 520 final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics(); 521 final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics(); 522 523 final H mH = new H(); 524 525 final Choreographer mChoreographer = Choreographer.getInstance(); 526 527 WindowState mCurrentFocus = null; 528 WindowState mLastFocus = null; 529 530 /** This just indicates the window the input method is on top of, not 531 * necessarily the window its input is going to. */ 532 WindowState mInputMethodTarget = null; 533 534 /** If true hold off on modifying the animation layer of mInputMethodTarget */ 535 boolean mInputMethodTargetWaitingAnim; 536 int mInputMethodAnimLayerAdjustment; 537 538 WindowState mInputMethodWindow = null; 539 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>(); 540 541 boolean mHardKeyboardAvailable; 542 boolean mShowImeWithHardKeyboard; 543 OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; 544 SettingsObserver mSettingsObserver; 545 546 private final class SettingsObserver extends ContentObserver { 547 public SettingsObserver() { 548 super(new Handler()); 549 ContentResolver resolver = mContext.getContentResolver(); 550 resolver.registerContentObserver(Settings.Secure.getUriFor( 551 Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD), false, this); 552 } 553 554 @Override 555 public void onChange(boolean selfChange) { 556 updateShowImeWithHardKeyboard(); 557 } 558 } 559 560 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>(); 561 562 // If non-null, this is the currently visible window that is associated 563 // with the wallpaper. 564 WindowState mWallpaperTarget = null; 565 // If non-null, we are in the middle of animating from one wallpaper target 566 // to another, and this is the lower one in Z-order. 567 WindowState mLowerWallpaperTarget = null; 568 // If non-null, we are in the middle of animating from one wallpaper target 569 // to another, and this is the higher one in Z-order. 570 WindowState mUpperWallpaperTarget = null; 571 int mWallpaperAnimLayerAdjustment; 572 float mLastWallpaperX = -1; 573 float mLastWallpaperY = -1; 574 float mLastWallpaperXStep = -1; 575 float mLastWallpaperYStep = -1; 576 // This is set when we are waiting for a wallpaper to tell us it is done 577 // changing its scroll position. 578 WindowState mWaitingOnWallpaper; 579 // The last time we had a timeout when waiting for a wallpaper. 580 long mLastWallpaperTimeoutTime; 581 // We give a wallpaper up to 150ms to finish scrolling. 582 static final long WALLPAPER_TIMEOUT = 150; 583 // Time we wait after a timeout before trying to wait again. 584 static final long WALLPAPER_TIMEOUT_RECOVERY = 10000; 585 boolean mAnimateWallpaperWithTarget; 586 587 AppWindowToken mFocusedApp = null; 588 589 PowerManager mPowerManager; 590 PowerManagerInternal mPowerManagerInternal; 591 592 float mWindowAnimationScaleSetting = 1.0f; 593 float mTransitionAnimationScaleSetting = 1.0f; 594 float mAnimatorDurationScaleSetting = 1.0f; 595 boolean mAnimationsDisabled = false; 596 597 final InputManagerService mInputManager; 598 final DisplayManagerInternal mDisplayManagerInternal; 599 final DisplayManager mDisplayManager; 600 601 // Who is holding the screen on. 602 Session mHoldingScreenOn; 603 PowerManager.WakeLock mHoldingScreenWakeLock; 604 605 boolean mTurnOnScreen; 606 607 DragState mDragState = null; 608 609 // For frozen screen animations. 610 int mExitAnimId, mEnterAnimId; 611 612 /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple 613 * methods. */ 614 class LayoutFields { 615 static final int SET_UPDATE_ROTATION = 1 << 0; 616 static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1; 617 static final int SET_FORCE_HIDING_CHANGED = 1 << 2; 618 static final int SET_ORIENTATION_CHANGE_COMPLETE = 1 << 3; 619 static final int SET_TURN_ON_SCREEN = 1 << 4; 620 static final int SET_WALLPAPER_ACTION_PENDING = 1 << 5; 621 622 boolean mWallpaperForceHidingChanged = false; 623 boolean mWallpaperMayChange = false; 624 boolean mOrientationChangeComplete = true; 625 Object mLastWindowFreezeSource = null; 626 private Session mHoldScreen = null; 627 private boolean mObscured = false; 628 private boolean mSyswin = false; 629 private float mScreenBrightness = -1; 630 private float mButtonBrightness = -1; 631 private long mUserActivityTimeout = -1; 632 private boolean mUpdateRotation = false; 633 boolean mWallpaperActionPending = false; 634 635 // Set to true when the display contains content to show the user. 636 // When false, the display manager may choose to mirror or blank the display. 637 boolean mDisplayHasContent = false; 638 639 // Only set while traversing the default display based on its content. 640 // Affects the behavior of mirroring on secondary displays. 641 boolean mObscureApplicationContentOnSecondaryDisplays = false; 642 643 float mPreferredRefreshRate = 0; 644 } 645 final LayoutFields mInnerFields = new LayoutFields(); 646 647 boolean mAnimationScheduled; 648 649 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this 650 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */ 651 private int mTransactionSequence; 652 653 /** Only do a maximum of 6 repeated layouts. After that quit */ 654 private int mLayoutRepeatCount; 655 656 final WindowAnimator mAnimator; 657 658 SparseArray<Task> mTaskIdToTask = new SparseArray<Task>(); 659 660 /** All of the TaskStacks in the window manager, unordered. For an ordered list call 661 * DisplayContent.getStacks(). */ 662 SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>(); 663 664 private final PointerEventDispatcher mPointerEventDispatcher; 665 666 private WindowContentFrameStats mTempWindowRenderStats; 667 668 final class DragInputEventReceiver extends InputEventReceiver { 669 public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { 670 super(inputChannel, looper); 671 } 672 673 @Override 674 public void onInputEvent(InputEvent event) { 675 boolean handled = false; 676 try { 677 if (event instanceof MotionEvent 678 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0 679 && mDragState != null) { 680 final MotionEvent motionEvent = (MotionEvent)event; 681 boolean endDrag = false; 682 final float newX = motionEvent.getRawX(); 683 final float newY = motionEvent.getRawY(); 684 685 switch (motionEvent.getAction()) { 686 case MotionEvent.ACTION_DOWN: { 687 if (DEBUG_DRAG) { 688 Slog.w(TAG, "Unexpected ACTION_DOWN in drag layer"); 689 } 690 } break; 691 692 case MotionEvent.ACTION_MOVE: { 693 synchronized (mWindowMap) { 694 // move the surface and tell the involved window(s) where we are 695 mDragState.notifyMoveLw(newX, newY); 696 } 697 } break; 698 699 case MotionEvent.ACTION_UP: { 700 if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at " 701 + newX + "," + newY); 702 synchronized (mWindowMap) { 703 endDrag = mDragState.notifyDropLw(newX, newY); 704 } 705 } break; 706 707 case MotionEvent.ACTION_CANCEL: { 708 if (DEBUG_DRAG) Slog.d(TAG, "Drag cancelled!"); 709 endDrag = true; 710 } break; 711 } 712 713 if (endDrag) { 714 if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state"); 715 // tell all the windows that the drag has ended 716 synchronized (mWindowMap) { 717 mDragState.endDragLw(); 718 } 719 } 720 721 handled = true; 722 } 723 } catch (Exception e) { 724 Slog.e(TAG, "Exception caught by drag handleMotion", e); 725 } finally { 726 finishInputEvent(event, handled); 727 } 728 } 729 } 730 731 /** 732 * Whether the UI is currently running in touch mode (not showing 733 * navigational focus because the user is directly pressing the screen). 734 */ 735 boolean mInTouchMode = true; 736 737 private ViewServer mViewServer; 738 private final ArrayList<WindowChangeListener> mWindowChangeListeners = 739 new ArrayList<WindowChangeListener>(); 740 private boolean mWindowsChanged = false; 741 742 public interface WindowChangeListener { 743 public void windowsChanged(); 744 public void focusChanged(); 745 } 746 747 final Configuration mTempConfiguration = new Configuration(); 748 749 // The desired scaling factor for compatible apps. 750 float mCompatibleScreenScale; 751 752 // If true, only the core apps and services are being launched because the device 753 // is in a special boot mode, such as being encrypted or waiting for a decryption password. 754 // For example, when this flag is true, there will be no wallpaper service. 755 final boolean mOnlyCore; 756 757 public static WindowManagerService main(final Context context, 758 final InputManagerService im, 759 final boolean haveInputMethods, final boolean showBootMsgs, 760 final boolean onlyCore) { 761 final WindowManagerService[] holder = new WindowManagerService[1]; 762 DisplayThread.getHandler().runWithScissors(new Runnable() { 763 @Override 764 public void run() { 765 holder[0] = new WindowManagerService(context, im, 766 haveInputMethods, showBootMsgs, onlyCore); 767 } 768 }, 0); 769 return holder[0]; 770 } 771 772 private void initPolicy() { 773 UiThread.getHandler().runWithScissors(new Runnable() { 774 @Override 775 public void run() { 776 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper()); 777 778 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this); 779 mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer() 780 * TYPE_LAYER_MULTIPLIER 781 + TYPE_LAYER_OFFSET; 782 } 783 }, 0); 784 } 785 786 private WindowManagerService(Context context, InputManagerService inputManager, 787 boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) { 788 mContext = context; 789 mHaveInputMethods = haveInputMethods; 790 mAllowBootMessages = showBootMsgs; 791 mOnlyCore = onlyCore; 792 mLimitedAlphaCompositing = context.getResources().getBoolean( 793 com.android.internal.R.bool.config_sf_limitedAlpha); 794 mInputManager = inputManager; // Must be before createDisplayContentLocked. 795 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); 796 mDisplaySettings = new DisplaySettings(context); 797 mDisplaySettings.readSettingsLocked(); 798 799 LocalServices.addService(WindowManagerPolicy.class, mPolicy); 800 801 mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG)); 802 803 mFxSession = new SurfaceSession(); 804 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); 805 Display[] displays = mDisplayManager.getDisplays(); 806 for (Display display : displays) { 807 createDisplayContentLocked(display); 808 } 809 810 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy); 811 812 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 813 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 814 mPowerManagerInternal.registerLowPowerModeObserver( 815 new PowerManagerInternal.LowPowerModeListener() { 816 @Override 817 public void onLowPowerModeChanged(boolean enabled) { 818 synchronized (mWindowMap) { 819 if (mAnimationsDisabled != enabled) { 820 mAnimationsDisabled = enabled; 821 dispatchNewAnimatorScaleLocked(null); 822 } 823 } 824 } 825 }); 826 mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled(); 827 mScreenFrozenLock = mPowerManager.newWakeLock( 828 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN"); 829 mScreenFrozenLock.setReferenceCounted(false); 830 831 mAppTransition = new AppTransition(context, mH); 832 833 mActivityManager = ActivityManagerNative.getDefault(); 834 mBatteryStats = BatteryStatsService.getService(); 835 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 836 AppOpsManager.OnOpChangedInternalListener opListener = 837 new AppOpsManager.OnOpChangedInternalListener() { 838 @Override public void onOpChanged(int op, String packageName) { 839 updateAppOpsState(); 840 } 841 }; 842 mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null, opListener); 843 mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener); 844 845 // Get persisted window scale setting 846 mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 847 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 848 mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 849 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting); 850 setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(), 851 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting)); 852 853 // Track changes to DevicePolicyManager state so we can enable/disable keyguard. 854 IntentFilter filter = new IntentFilter(); 855 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 856 mContext.registerReceiver(mBroadcastReceiver, filter); 857 858 mSettingsObserver = new SettingsObserver(); 859 updateShowImeWithHardKeyboard(); 860 861 mHoldingScreenWakeLock = mPowerManager.newWakeLock( 862 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG); 863 mHoldingScreenWakeLock.setReferenceCounted(false); 864 865 mAnimator = new WindowAnimator(this); 866 867 LocalServices.addService(WindowManagerInternal.class, new LocalService()); 868 initPolicy(); 869 870 // Add ourself to the Watchdog monitors. 871 Watchdog.getInstance().addMonitor(this); 872 873 SurfaceControl.openTransaction(); 874 try { 875 createWatermarkInTransaction(); 876 mFocusedStackFrame = new FocusedStackFrame( 877 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 878 } finally { 879 SurfaceControl.closeTransaction(); 880 } 881 882 showCircularDisplayMaskIfNeeded(); 883 } 884 885 public InputMonitor getInputMonitor() { 886 return mInputMonitor; 887 } 888 889 @Override 890 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 891 throws RemoteException { 892 try { 893 return super.onTransact(code, data, reply, flags); 894 } catch (RuntimeException e) { 895 // The window manager only throws security exceptions, so let's 896 // log all others. 897 if (!(e instanceof SecurityException)) { 898 Slog.wtf(TAG, "Window Manager Crash", e); 899 } 900 throw e; 901 } 902 } 903 904 private void placeWindowAfter(WindowState pos, WindowState window) { 905 final WindowList windows = pos.getWindowList(); 906 final int i = windows.indexOf(pos); 907 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 908 TAG, "Adding window " + window + " at " 909 + (i+1) + " of " + windows.size() + " (after " + pos + ")"); 910 windows.add(i+1, window); 911 mWindowsChanged = true; 912 } 913 914 private void placeWindowBefore(WindowState pos, WindowState window) { 915 final WindowList windows = pos.getWindowList(); 916 int i = windows.indexOf(pos); 917 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 918 TAG, "Adding window " + window + " at " 919 + i + " of " + windows.size() + " (before " + pos + ")"); 920 if (i < 0) { 921 Slog.w(TAG, "placeWindowBefore: Unable to find " + pos + " in " + windows); 922 i = 0; 923 } 924 windows.add(i, window); 925 mWindowsChanged = true; 926 } 927 928 //This method finds out the index of a window that has the same app token as 929 //win. used for z ordering the windows in mWindows 930 private int findIdxBasedOnAppTokens(WindowState win) { 931 WindowList windows = win.getWindowList(); 932 for(int j = windows.size() - 1; j >= 0; j--) { 933 WindowState wentry = windows.get(j); 934 if(wentry.mAppToken == win.mAppToken) { 935 return j; 936 } 937 } 938 return -1; 939 } 940 941 /** 942 * Return the list of Windows from the passed token on the given Display. 943 * @param token The token with all the windows. 944 * @param displayContent The display we are interested in. 945 * @return List of windows from token that are on displayContent. 946 */ 947 WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) { 948 final WindowList windowList = new WindowList(); 949 final int count = token.windows.size(); 950 for (int i = 0; i < count; i++) { 951 final WindowState win = token.windows.get(i); 952 if (win.getDisplayContent() == displayContent) { 953 windowList.add(win); 954 } 955 } 956 return windowList; 957 } 958 959 /** 960 * Recursive search through a WindowList and all of its windows' children. 961 * @param targetWin The window to search for. 962 * @param windows The list to search. 963 * @return The index of win in windows or of the window that is an ancestor of win. 964 */ 965 private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) { 966 for (int i = windows.size() - 1; i >= 0; i--) { 967 final WindowState w = windows.get(i); 968 if (w == targetWin) { 969 return i; 970 } 971 if (!w.mChildWindows.isEmpty()) { 972 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) { 973 return i; 974 } 975 } 976 } 977 return -1; 978 } 979 980 private int addAppWindowToListLocked(final WindowState win) { 981 final IWindow client = win.mClient; 982 final WindowToken token = win.mToken; 983 final DisplayContent displayContent = win.getDisplayContent(); 984 if (displayContent == null) { 985 // It doesn't matter this display is going away. 986 return 0; 987 } 988 989 final WindowList windows = win.getWindowList(); 990 final int N = windows.size(); 991 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 992 int tokenWindowsPos = 0; 993 int windowListPos = tokenWindowList.size(); 994 if (!tokenWindowList.isEmpty()) { 995 // If this application has existing windows, we 996 // simply place the new window on top of them... but 997 // keep the starting window on top. 998 if (win.mAttrs.type == TYPE_BASE_APPLICATION) { 999 // Base windows go behind everything else. 1000 WindowState lowestWindow = tokenWindowList.get(0); 1001 placeWindowBefore(lowestWindow, win); 1002 tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows); 1003 } else { 1004 AppWindowToken atoken = win.mAppToken; 1005 WindowState lastWindow = tokenWindowList.get(windowListPos - 1); 1006 if (atoken != null && lastWindow == atoken.startingWindow) { 1007 placeWindowBefore(lastWindow, win); 1008 tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows); 1009 } else { 1010 int newIdx = findIdxBasedOnAppTokens(win); 1011 //there is a window above this one associated with the same 1012 //apptoken note that the window could be a floating window 1013 //that was created later or a window at the top of the list of 1014 //windows associated with this token. 1015 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1016 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " + 1017 N); 1018 windows.add(newIdx + 1, win); 1019 if (newIdx < 0) { 1020 // No window from token found on win's display. 1021 tokenWindowsPos = 0; 1022 } else { 1023 tokenWindowsPos = indexOfWinInWindowList( 1024 windows.get(newIdx), token.windows) + 1; 1025 } 1026 mWindowsChanged = true; 1027 } 1028 } 1029 return tokenWindowsPos; 1030 } 1031 1032 // No windows from this token on this display 1033 if (localLOGV) Slog.v(TAG, "Figuring out where to add app window " + client.asBinder() 1034 + " (token=" + token + ")"); 1035 // Figure out where the window should go, based on the 1036 // order of applications. 1037 WindowState pos = null; 1038 1039 final ArrayList<Task> tasks = displayContent.getTasks(); 1040 int taskNdx; 1041 int tokenNdx = -1; 1042 for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 1043 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1044 for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 1045 final AppWindowToken t = tokens.get(tokenNdx); 1046 if (t == token) { 1047 --tokenNdx; 1048 if (tokenNdx < 0) { 1049 --taskNdx; 1050 if (taskNdx >= 0) { 1051 tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1; 1052 } 1053 } 1054 break; 1055 } 1056 1057 // We haven't reached the token yet; if this token 1058 // is not going to the bottom and has windows on this display, we can 1059 // use it as an anchor for when we do reach the token. 1060 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1061 if (!t.sendingToBottom && tokenWindowList.size() > 0) { 1062 pos = tokenWindowList.get(0); 1063 } 1064 } 1065 if (tokenNdx >= 0) { 1066 // early exit 1067 break; 1068 } 1069 } 1070 1071 // We now know the index into the apps. If we found 1072 // an app window above, that gives us the position; else 1073 // we need to look some more. 1074 if (pos != null) { 1075 // Move behind any windows attached to this one. 1076 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1077 if (atoken != null) { 1078 tokenWindowList = 1079 getTokenWindowsOnDisplay(atoken, displayContent); 1080 final int NC = tokenWindowList.size(); 1081 if (NC > 0) { 1082 WindowState bottom = tokenWindowList.get(0); 1083 if (bottom.mSubLayer < 0) { 1084 pos = bottom; 1085 } 1086 } 1087 } 1088 placeWindowBefore(pos, win); 1089 return tokenWindowsPos; 1090 } 1091 1092 // Continue looking down until we find the first 1093 // token that has windows on this display. 1094 for ( ; taskNdx >= 0; --taskNdx) { 1095 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1096 for ( ; tokenNdx >= 0; --tokenNdx) { 1097 final AppWindowToken t = tokens.get(tokenNdx); 1098 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1099 final int NW = tokenWindowList.size(); 1100 if (NW > 0) { 1101 pos = tokenWindowList.get(NW-1); 1102 break; 1103 } 1104 } 1105 if (tokenNdx >= 0) { 1106 // found 1107 break; 1108 } 1109 } 1110 1111 if (pos != null) { 1112 // Move in front of any windows attached to this 1113 // one. 1114 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1115 if (atoken != null) { 1116 final int NC = atoken.windows.size(); 1117 if (NC > 0) { 1118 WindowState top = atoken.windows.get(NC-1); 1119 if (top.mSubLayer >= 0) { 1120 pos = top; 1121 } 1122 } 1123 } 1124 placeWindowAfter(pos, win); 1125 return tokenWindowsPos; 1126 } 1127 1128 // Just search for the start of this layer. 1129 final int myLayer = win.mBaseLayer; 1130 int i; 1131 for (i = 0; i < N; i++) { 1132 WindowState w = windows.get(i); 1133 if (w.mBaseLayer > myLayer) { 1134 break; 1135 } 1136 } 1137 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1138 "Based on layer: Adding window " + win + " at " + i + " of " + N); 1139 windows.add(i, win); 1140 mWindowsChanged = true; 1141 return tokenWindowsPos; 1142 } 1143 1144 private void addFreeWindowToListLocked(final WindowState win) { 1145 final WindowList windows = win.getWindowList(); 1146 1147 // Figure out where window should go, based on layer. 1148 final int myLayer = win.mBaseLayer; 1149 int i; 1150 for (i = windows.size() - 1; i >= 0; i--) { 1151 if (windows.get(i).mBaseLayer <= myLayer) { 1152 break; 1153 } 1154 } 1155 i++; 1156 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1157 "Free window: Adding window " + win + " at " + i + " of " + windows.size()); 1158 windows.add(i, win); 1159 mWindowsChanged = true; 1160 } 1161 1162 private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) { 1163 final WindowToken token = win.mToken; 1164 final DisplayContent displayContent = win.getDisplayContent(); 1165 if (displayContent == null) { 1166 return; 1167 } 1168 final WindowState attached = win.mAttachedWindow; 1169 1170 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 1171 1172 // Figure out this window's ordering relative to the window 1173 // it is attached to. 1174 final int NA = tokenWindowList.size(); 1175 final int sublayer = win.mSubLayer; 1176 int largestSublayer = Integer.MIN_VALUE; 1177 WindowState windowWithLargestSublayer = null; 1178 int i; 1179 for (i = 0; i < NA; i++) { 1180 WindowState w = tokenWindowList.get(i); 1181 final int wSublayer = w.mSubLayer; 1182 if (wSublayer >= largestSublayer) { 1183 largestSublayer = wSublayer; 1184 windowWithLargestSublayer = w; 1185 } 1186 if (sublayer < 0) { 1187 // For negative sublayers, we go below all windows 1188 // in the same sublayer. 1189 if (wSublayer >= sublayer) { 1190 if (addToToken) { 1191 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1192 token.windows.add(i, win); 1193 } 1194 placeWindowBefore(wSublayer >= 0 ? attached : w, win); 1195 break; 1196 } 1197 } else { 1198 // For positive sublayers, we go above all windows 1199 // in the same sublayer. 1200 if (wSublayer > sublayer) { 1201 if (addToToken) { 1202 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1203 token.windows.add(i, win); 1204 } 1205 placeWindowBefore(w, win); 1206 break; 1207 } 1208 } 1209 } 1210 if (i >= NA) { 1211 if (addToToken) { 1212 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1213 token.windows.add(win); 1214 } 1215 if (sublayer < 0) { 1216 placeWindowBefore(attached, win); 1217 } else { 1218 placeWindowAfter(largestSublayer >= 0 1219 ? windowWithLargestSublayer 1220 : attached, 1221 win); 1222 } 1223 } 1224 } 1225 1226 private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) { 1227 if (DEBUG_FOCUS_LIGHT) Slog.d(TAG, "addWindowToListInOrderLocked: win=" + win + 1228 " Callers=" + Debug.getCallers(4)); 1229 if (win.mAttachedWindow == null) { 1230 final WindowToken token = win.mToken; 1231 int tokenWindowsPos = 0; 1232 if (token.appWindowToken != null) { 1233 tokenWindowsPos = addAppWindowToListLocked(win); 1234 } else { 1235 addFreeWindowToListLocked(win); 1236 } 1237 if (addToToken) { 1238 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1239 token.windows.add(tokenWindowsPos, win); 1240 } 1241 } else { 1242 addAttachedWindowToListLocked(win, addToToken); 1243 } 1244 1245 if (win.mAppToken != null && addToToken) { 1246 win.mAppToken.allAppWindows.add(win); 1247 } 1248 } 1249 1250 static boolean canBeImeTarget(WindowState w) { 1251 final int fl = w.mAttrs.flags 1252 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); 1253 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM) 1254 || w.mAttrs.type == TYPE_APPLICATION_STARTING) { 1255 if (DEBUG_INPUT_METHOD) { 1256 Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding()); 1257 if (!w.isVisibleOrAdding()) { 1258 Slog.i(TAG, " mSurface=" + w.mWinAnimator.mSurfaceControl 1259 + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility 1260 + " policyVis=" + w.mPolicyVisibility 1261 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim 1262 + " attachHid=" + w.mAttachedHidden 1263 + " exiting=" + w.mExiting + " destroying=" + w.mDestroying); 1264 if (w.mAppToken != null) { 1265 Slog.i(TAG, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested); 1266 } 1267 } 1268 } 1269 return w.isVisibleOrAdding(); 1270 } 1271 return false; 1272 } 1273 1274 /** 1275 * Dig through the WindowStates and find the one that the Input Method will target. 1276 * @param willMove 1277 * @return The index+1 in mWindows of the discovered target. 1278 */ 1279 int findDesiredInputMethodWindowIndexLocked(boolean willMove) { 1280 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the 1281 // same display. Or even when the current IME/target are not on the same screen as the next 1282 // IME/target. For now only look for input windows on the main screen. 1283 WindowList windows = getDefaultWindowListLocked(); 1284 WindowState w = null; 1285 int i; 1286 for (i = windows.size() - 1; i >= 0; --i) { 1287 WindowState win = windows.get(i); 1288 1289 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i 1290 + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags)); 1291 if (canBeImeTarget(win)) { 1292 w = win; 1293 //Slog.i(TAG, "Putting input method here!"); 1294 1295 // Yet more tricksyness! If this window is a "starting" 1296 // window, we do actually want to be on top of it, but 1297 // it is not -really- where input will go. So if the caller 1298 // is not actually looking to move the IME, look down below 1299 // for a real window to target... 1300 if (!willMove 1301 && w.mAttrs.type == TYPE_APPLICATION_STARTING 1302 && i > 0) { 1303 WindowState wb = windows.get(i-1); 1304 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) { 1305 i--; 1306 w = wb; 1307 } 1308 } 1309 break; 1310 } 1311 } 1312 1313 // Now w is either mWindows[0] or an IME (or null if mWindows is empty). 1314 1315 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w); 1316 1317 // Now, a special case -- if the last target's window is in the 1318 // process of exiting, and is above the new target, keep on the 1319 // last target to avoid flicker. Consider for example a Dialog with 1320 // the IME shown: when the Dialog is dismissed, we want to keep 1321 // the IME above it until it is completely gone so it doesn't drop 1322 // behind the dialog or its full-screen scrim. 1323 final WindowState curTarget = mInputMethodTarget; 1324 if (curTarget != null 1325 && curTarget.isDisplayedLw() 1326 && curTarget.isClosing() 1327 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) { 1328 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing"); 1329 return windows.indexOf(curTarget) + 1; 1330 } 1331 1332 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target=" 1333 + w + " willMove=" + willMove); 1334 1335 if (willMove && w != null) { 1336 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken; 1337 if (token != null) { 1338 1339 // Now some fun for dealing with window animations that 1340 // modify the Z order. We need to look at all windows below 1341 // the current target that are in this app, finding the highest 1342 // visible one in layering. 1343 WindowState highestTarget = null; 1344 int highestPos = 0; 1345 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) { 1346 WindowList curWindows = curTarget.getWindowList(); 1347 int pos = curWindows.indexOf(curTarget); 1348 while (pos >= 0) { 1349 WindowState win = curWindows.get(pos); 1350 if (win.mAppToken != token) { 1351 break; 1352 } 1353 if (!win.mRemoved) { 1354 if (highestTarget == null || win.mWinAnimator.mAnimLayer > 1355 highestTarget.mWinAnimator.mAnimLayer) { 1356 highestTarget = win; 1357 highestPos = pos; 1358 } 1359 } 1360 pos--; 1361 } 1362 } 1363 1364 if (highestTarget != null) { 1365 if (DEBUG_INPUT_METHOD) Slog.v(TAG, mAppTransition + " " + highestTarget 1366 + " animating=" + highestTarget.mWinAnimator.isAnimating() 1367 + " layer=" + highestTarget.mWinAnimator.mAnimLayer 1368 + " new layer=" + w.mWinAnimator.mAnimLayer); 1369 1370 if (mAppTransition.isTransitionSet()) { 1371 // If we are currently setting up for an animation, 1372 // hold everything until we can find out what will happen. 1373 mInputMethodTargetWaitingAnim = true; 1374 mInputMethodTarget = highestTarget; 1375 return highestPos + 1; 1376 } else if (highestTarget.mWinAnimator.isAnimating() && 1377 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) { 1378 // If the window we are currently targeting is involved 1379 // with an animation, and it is on top of the next target 1380 // we will be over, then hold off on moving until 1381 // that is done. 1382 mInputMethodTargetWaitingAnim = true; 1383 mInputMethodTarget = highestTarget; 1384 return highestPos + 1; 1385 } 1386 } 1387 } 1388 } 1389 1390 //Slog.i(TAG, "Placing input method @" + (i+1)); 1391 if (w != null) { 1392 if (willMove) { 1393 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to " 1394 + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4))); 1395 mInputMethodTarget = w; 1396 mInputMethodTargetWaitingAnim = false; 1397 if (w.mAppToken != null) { 1398 setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment); 1399 } else { 1400 setInputMethodAnimLayerAdjustment(0); 1401 } 1402 } 1403 return i+1; 1404 } 1405 if (willMove) { 1406 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null." 1407 + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4))); 1408 mInputMethodTarget = null; 1409 setInputMethodAnimLayerAdjustment(0); 1410 } 1411 return -1; 1412 } 1413 1414 void addInputMethodWindowToListLocked(WindowState win) { 1415 int pos = findDesiredInputMethodWindowIndexLocked(true); 1416 if (pos >= 0) { 1417 win.mTargetAppToken = mInputMethodTarget.mAppToken; 1418 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 1419 TAG, "Adding input method window " + win + " at " + pos); 1420 // TODO(multidisplay): IMEs are only supported on the default display. 1421 getDefaultWindowListLocked().add(pos, win); 1422 mWindowsChanged = true; 1423 moveInputMethodDialogsLocked(pos+1); 1424 return; 1425 } 1426 win.mTargetAppToken = null; 1427 addWindowToListInOrderLocked(win, true); 1428 moveInputMethodDialogsLocked(pos); 1429 } 1430 1431 void setInputMethodAnimLayerAdjustment(int adj) { 1432 if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj); 1433 mInputMethodAnimLayerAdjustment = adj; 1434 WindowState imw = mInputMethodWindow; 1435 if (imw != null) { 1436 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj; 1437 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw 1438 + " anim layer: " + imw.mWinAnimator.mAnimLayer); 1439 int wi = imw.mChildWindows.size(); 1440 while (wi > 0) { 1441 wi--; 1442 WindowState cw = imw.mChildWindows.get(wi); 1443 cw.mWinAnimator.mAnimLayer = cw.mLayer + adj; 1444 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw 1445 + " anim layer: " + cw.mWinAnimator.mAnimLayer); 1446 } 1447 } 1448 int di = mInputMethodDialogs.size(); 1449 while (di > 0) { 1450 di --; 1451 imw = mInputMethodDialogs.get(di); 1452 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj; 1453 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw 1454 + " anim layer: " + imw.mWinAnimator.mAnimLayer); 1455 } 1456 } 1457 1458 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) { 1459 WindowList windows = win.getWindowList(); 1460 int wpos = windows.indexOf(win); 1461 if (wpos >= 0) { 1462 if (wpos < interestingPos) interestingPos--; 1463 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win); 1464 windows.remove(wpos); 1465 mWindowsChanged = true; 1466 int NC = win.mChildWindows.size(); 1467 while (NC > 0) { 1468 NC--; 1469 WindowState cw = win.mChildWindows.get(NC); 1470 int cpos = windows.indexOf(cw); 1471 if (cpos >= 0) { 1472 if (cpos < interestingPos) interestingPos--; 1473 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at " 1474 + cpos + ": " + cw); 1475 windows.remove(cpos); 1476 } 1477 } 1478 } 1479 return interestingPos; 1480 } 1481 1482 private void reAddWindowToListInOrderLocked(WindowState win) { 1483 addWindowToListInOrderLocked(win, false); 1484 // This is a hack to get all of the child windows added as well 1485 // at the right position. Child windows should be rare and 1486 // this case should be rare, so it shouldn't be that big a deal. 1487 WindowList windows = win.getWindowList(); 1488 int wpos = windows.indexOf(win); 1489 if (wpos >= 0) { 1490 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win); 1491 windows.remove(wpos); 1492 mWindowsChanged = true; 1493 reAddWindowLocked(wpos, win); 1494 } 1495 } 1496 1497 void logWindowList(final WindowList windows, String prefix) { 1498 int N = windows.size(); 1499 while (N > 0) { 1500 N--; 1501 Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N)); 1502 } 1503 } 1504 1505 void moveInputMethodDialogsLocked(int pos) { 1506 ArrayList<WindowState> dialogs = mInputMethodDialogs; 1507 1508 // TODO(multidisplay): IMEs are only supported on the default display. 1509 WindowList windows = getDefaultWindowListLocked(); 1510 final int N = dialogs.size(); 1511 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos); 1512 for (int i=0; i<N; i++) { 1513 pos = tmpRemoveWindowLocked(pos, dialogs.get(i)); 1514 } 1515 if (DEBUG_INPUT_METHOD) { 1516 Slog.v(TAG, "Window list w/pos=" + pos); 1517 logWindowList(windows, " "); 1518 } 1519 1520 if (pos >= 0) { 1521 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken; 1522 // Skip windows owned by the input method. 1523 if (mInputMethodWindow != null) { 1524 while (pos < windows.size()) { 1525 WindowState wp = windows.get(pos); 1526 if (wp == mInputMethodWindow || wp.mAttachedWindow == mInputMethodWindow) { 1527 pos++; 1528 continue; 1529 } 1530 break; 1531 } 1532 } 1533 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos); 1534 for (int i=0; i<N; i++) { 1535 WindowState win = dialogs.get(i); 1536 win.mTargetAppToken = targetAppToken; 1537 pos = reAddWindowLocked(pos, win); 1538 } 1539 if (DEBUG_INPUT_METHOD) { 1540 Slog.v(TAG, "Final window list:"); 1541 logWindowList(windows, " "); 1542 } 1543 return; 1544 } 1545 for (int i=0; i<N; i++) { 1546 WindowState win = dialogs.get(i); 1547 win.mTargetAppToken = null; 1548 reAddWindowToListInOrderLocked(win); 1549 if (DEBUG_INPUT_METHOD) { 1550 Slog.v(TAG, "No IM target, final list:"); 1551 logWindowList(windows, " "); 1552 } 1553 } 1554 } 1555 1556 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) { 1557 final WindowState imWin = mInputMethodWindow; 1558 final int DN = mInputMethodDialogs.size(); 1559 if (imWin == null && DN == 0) { 1560 return false; 1561 } 1562 1563 // TODO(multidisplay): IMEs are only supported on the default display. 1564 WindowList windows = getDefaultWindowListLocked(); 1565 1566 int imPos = findDesiredInputMethodWindowIndexLocked(true); 1567 if (imPos >= 0) { 1568 // In this case, the input method windows are to be placed 1569 // immediately above the window they are targeting. 1570 1571 // First check to see if the input method windows are already 1572 // located here, and contiguous. 1573 final int N = windows.size(); 1574 WindowState firstImWin = imPos < N 1575 ? windows.get(imPos) : null; 1576 1577 // Figure out the actual input method window that should be 1578 // at the bottom of their stack. 1579 WindowState baseImWin = imWin != null 1580 ? imWin : mInputMethodDialogs.get(0); 1581 if (baseImWin.mChildWindows.size() > 0) { 1582 WindowState cw = baseImWin.mChildWindows.get(0); 1583 if (cw.mSubLayer < 0) baseImWin = cw; 1584 } 1585 1586 if (firstImWin == baseImWin) { 1587 // The windows haven't moved... but are they still contiguous? 1588 // First find the top IM window. 1589 int pos = imPos+1; 1590 while (pos < N) { 1591 if (!(windows.get(pos)).mIsImWindow) { 1592 break; 1593 } 1594 pos++; 1595 } 1596 pos++; 1597 // Now there should be no more input method windows above. 1598 while (pos < N) { 1599 if ((windows.get(pos)).mIsImWindow) { 1600 break; 1601 } 1602 pos++; 1603 } 1604 if (pos >= N) { 1605 // Z order is good. 1606 // The IM target window may be changed, so update the mTargetAppToken. 1607 if (imWin != null) { 1608 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1609 } 1610 return false; 1611 } 1612 } 1613 1614 if (imWin != null) { 1615 if (DEBUG_INPUT_METHOD) { 1616 Slog.v(TAG, "Moving IM from " + imPos); 1617 logWindowList(windows, " "); 1618 } 1619 imPos = tmpRemoveWindowLocked(imPos, imWin); 1620 if (DEBUG_INPUT_METHOD) { 1621 Slog.v(TAG, "List after removing with new pos " + imPos + ":"); 1622 logWindowList(windows, " "); 1623 } 1624 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1625 reAddWindowLocked(imPos, imWin); 1626 if (DEBUG_INPUT_METHOD) { 1627 Slog.v(TAG, "List after moving IM to " + imPos + ":"); 1628 logWindowList(windows, " "); 1629 } 1630 if (DN > 0) moveInputMethodDialogsLocked(imPos+1); 1631 } else { 1632 moveInputMethodDialogsLocked(imPos); 1633 } 1634 1635 } else { 1636 // In this case, the input method windows go in a fixed layer, 1637 // because they aren't currently associated with a focus window. 1638 1639 if (imWin != null) { 1640 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos); 1641 tmpRemoveWindowLocked(0, imWin); 1642 imWin.mTargetAppToken = null; 1643 reAddWindowToListInOrderLocked(imWin); 1644 if (DEBUG_INPUT_METHOD) { 1645 Slog.v(TAG, "List with no IM target:"); 1646 logWindowList(windows, " "); 1647 } 1648 if (DN > 0) moveInputMethodDialogsLocked(-1); 1649 } else { 1650 moveInputMethodDialogsLocked(-1); 1651 } 1652 1653 } 1654 1655 if (needAssignLayers) { 1656 assignLayersLocked(windows); 1657 } 1658 1659 return true; 1660 } 1661 1662 final boolean isWallpaperVisible(WindowState wallpaperTarget) { 1663 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured=" 1664 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??") 1665 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null) 1666 ? wallpaperTarget.mAppToken.mAppAnimator.animation : null) 1667 + " upper=" + mUpperWallpaperTarget 1668 + " lower=" + mLowerWallpaperTarget); 1669 return (wallpaperTarget != null 1670 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null 1671 && wallpaperTarget.mAppToken.mAppAnimator.animation != null))) 1672 || mUpperWallpaperTarget != null 1673 || mLowerWallpaperTarget != null; 1674 } 1675 1676 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1; 1677 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2; 1678 1679 int adjustWallpaperWindowsLocked() { 1680 mInnerFields.mWallpaperMayChange = false; 1681 boolean targetChanged = false; 1682 1683 // TODO(multidisplay): Wallpapers on main screen only. 1684 final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo(); 1685 final int dw = displayInfo.logicalWidth; 1686 final int dh = displayInfo.logicalHeight; 1687 1688 // First find top-most window that has asked to be on top of the 1689 // wallpaper; all wallpapers go behind it. 1690 final WindowList windows = getDefaultWindowListLocked(); 1691 int N = windows.size(); 1692 WindowState w = null; 1693 WindowState foundW = null; 1694 int foundI = 0; 1695 WindowState topCurW = null; 1696 int topCurI = 0; 1697 int windowDetachedI = -1; 1698 int i = N; 1699 while (i > 0) { 1700 i--; 1701 w = windows.get(i); 1702 if ((w.mAttrs.type == TYPE_WALLPAPER)) { 1703 if (topCurW == null) { 1704 topCurW = w; 1705 topCurI = i; 1706 } 1707 continue; 1708 } 1709 topCurW = null; 1710 if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) { 1711 // If this window's app token is hidden and not animating, 1712 // it is of no interest to us. 1713 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) { 1714 if (DEBUG_WALLPAPER) Slog.v(TAG, 1715 "Skipping hidden and not animating token: " + w); 1716 continue; 1717 } 1718 } 1719 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen=" 1720 + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState); 1721 1722 // If the app is executing an animation because the keyguard is going away, keep the 1723 // wallpaper during the animation so it doesn't flicker out. 1724 final boolean hasWallpaper = (w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 1725 || (w.mAppToken != null 1726 && w.mWinAnimator.keyguardGoingAwayAnimation); 1727 if (hasWallpaper && w.isOnScreen() 1728 && (mWallpaperTarget == w || w.isDrawFinishedLw())) { 1729 if (DEBUG_WALLPAPER) Slog.v(TAG, 1730 "Found wallpaper target: #" + i + "=" + w); 1731 foundW = w; 1732 foundI = i; 1733 if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) { 1734 // The current wallpaper target is animating, so we'll 1735 // look behind it for another possible target and figure 1736 // out what is going on below. 1737 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w 1738 + ": token animating, looking behind."); 1739 continue; 1740 } 1741 break; 1742 } else if (w == mAnimator.mWindowDetachedWallpaper) { 1743 windowDetachedI = i; 1744 } 1745 } 1746 1747 if (foundW == null && windowDetachedI >= 0) { 1748 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 1749 "Found animating detached wallpaper activity: #" + i + "=" + w); 1750 foundW = w; 1751 foundI = windowDetachedI; 1752 } 1753 1754 if (mWallpaperTarget != foundW 1755 && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) { 1756 if (DEBUG_WALLPAPER_LIGHT) { 1757 Slog.v(TAG, "New wallpaper target: " + foundW 1758 + " oldTarget: " + mWallpaperTarget); 1759 } 1760 1761 mLowerWallpaperTarget = null; 1762 mUpperWallpaperTarget = null; 1763 1764 WindowState oldW = mWallpaperTarget; 1765 mWallpaperTarget = foundW; 1766 targetChanged = true; 1767 1768 // Now what is happening... if the current and new targets are 1769 // animating, then we are in our super special mode! 1770 if (foundW != null && oldW != null) { 1771 boolean oldAnim = oldW.isAnimatingLw(); 1772 boolean foundAnim = foundW.isAnimatingLw(); 1773 if (DEBUG_WALLPAPER_LIGHT) { 1774 Slog.v(TAG, "New animation: " + foundAnim 1775 + " old animation: " + oldAnim); 1776 } 1777 if (foundAnim && oldAnim) { 1778 int oldI = windows.indexOf(oldW); 1779 if (DEBUG_WALLPAPER_LIGHT) { 1780 Slog.v(TAG, "New i: " + foundI + " old i: " + oldI); 1781 } 1782 if (oldI >= 0) { 1783 if (DEBUG_WALLPAPER_LIGHT) { 1784 Slog.v(TAG, "Animating wallpapers: old#" + oldI 1785 + "=" + oldW + "; new#" + foundI 1786 + "=" + foundW); 1787 } 1788 1789 // Set the new target correctly. 1790 if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) { 1791 if (DEBUG_WALLPAPER_LIGHT) { 1792 Slog.v(TAG, "Old wallpaper still the target."); 1793 } 1794 mWallpaperTarget = oldW; 1795 foundW = oldW; 1796 foundI = oldI; 1797 } 1798 // Now set the upper and lower wallpaper targets 1799 // correctly, and make sure that we are positioning 1800 // the wallpaper below the lower. 1801 else if (foundI > oldI) { 1802 // The new target is on top of the old one. 1803 if (DEBUG_WALLPAPER_LIGHT) { 1804 Slog.v(TAG, "Found target above old target."); 1805 } 1806 mUpperWallpaperTarget = foundW; 1807 mLowerWallpaperTarget = oldW; 1808 foundW = oldW; 1809 foundI = oldI; 1810 } else { 1811 // The new target is below the old one. 1812 if (DEBUG_WALLPAPER_LIGHT) { 1813 Slog.v(TAG, "Found target below old target."); 1814 } 1815 mUpperWallpaperTarget = oldW; 1816 mLowerWallpaperTarget = foundW; 1817 } 1818 } 1819 } 1820 } 1821 1822 } else if (mLowerWallpaperTarget != null) { 1823 // Is it time to stop animating? 1824 if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) { 1825 if (DEBUG_WALLPAPER_LIGHT) { 1826 Slog.v(TAG, "No longer animating wallpaper targets!"); 1827 } 1828 mLowerWallpaperTarget = null; 1829 mUpperWallpaperTarget = null; 1830 mWallpaperTarget = foundW; 1831 targetChanged = true; 1832 } 1833 } 1834 1835 boolean visible = foundW != null; 1836 if (visible) { 1837 // The window is visible to the compositor... but is it visible 1838 // to the user? That is what the wallpaper cares about. 1839 visible = isWallpaperVisible(foundW); 1840 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible); 1841 1842 // If the wallpaper target is animating, we may need to copy 1843 // its layer adjustment. Only do this if we are not transfering 1844 // between two wallpaper targets. 1845 mWallpaperAnimLayerAdjustment = 1846 (mLowerWallpaperTarget == null && foundW.mAppToken != null) 1847 ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0; 1848 1849 final int maxLayer = mPolicy.getMaxWallpaperLayer() 1850 * TYPE_LAYER_MULTIPLIER 1851 + TYPE_LAYER_OFFSET; 1852 1853 // Now w is the window we are supposed to be behind... but we 1854 // need to be sure to also be behind any of its attached windows, 1855 // AND any starting window associated with it, AND below the 1856 // maximum layer the policy allows for wallpapers. 1857 while (foundI > 0) { 1858 WindowState wb = windows.get(foundI-1); 1859 if (wb.mBaseLayer < maxLayer && 1860 wb.mAttachedWindow != foundW && 1861 (foundW.mAttachedWindow == null || 1862 wb.mAttachedWindow != foundW.mAttachedWindow) && 1863 (wb.mAttrs.type != TYPE_APPLICATION_STARTING || 1864 foundW.mToken == null || wb.mToken != foundW.mToken)) { 1865 // This window is not related to the previous one in any 1866 // interesting way, so stop here. 1867 break; 1868 } 1869 foundW = wb; 1870 foundI--; 1871 } 1872 } else { 1873 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target"); 1874 } 1875 1876 if (foundW == null && topCurW != null) { 1877 // There is no wallpaper target, so it goes at the bottom. 1878 // We will assume it is the same place as last time, if known. 1879 foundW = topCurW; 1880 foundI = topCurI+1; 1881 } else { 1882 // Okay i is the position immediately above the wallpaper. Look at 1883 // what is below it for later. 1884 foundW = foundI > 0 ? windows.get(foundI-1) : null; 1885 } 1886 1887 if (visible) { 1888 if (mWallpaperTarget.mWallpaperX >= 0) { 1889 mLastWallpaperX = mWallpaperTarget.mWallpaperX; 1890 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep; 1891 } 1892 if (mWallpaperTarget.mWallpaperY >= 0) { 1893 mLastWallpaperY = mWallpaperTarget.mWallpaperY; 1894 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep; 1895 } 1896 } 1897 1898 // Start stepping backwards from here, ensuring that our wallpaper windows 1899 // are correctly placed. 1900 int changed = 0; 1901 int curTokenIndex = mWallpaperTokens.size(); 1902 while (curTokenIndex > 0) { 1903 curTokenIndex--; 1904 WindowToken token = mWallpaperTokens.get(curTokenIndex); 1905 if (token.hidden == visible) { 1906 if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, 1907 "Wallpaper token " + token + " hidden=" + !visible); 1908 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED; 1909 token.hidden = !visible; 1910 // Need to do a layout to ensure the wallpaper now has the 1911 // correct size. 1912 getDefaultDisplayContentLocked().layoutNeeded = true; 1913 } 1914 1915 int curWallpaperIndex = token.windows.size(); 1916 while (curWallpaperIndex > 0) { 1917 curWallpaperIndex--; 1918 WindowState wallpaper = token.windows.get(curWallpaperIndex); 1919 1920 if (visible) { 1921 updateWallpaperOffsetLocked(wallpaper, dw, dh, false); 1922 } 1923 1924 // First, make sure the client has the current visibility 1925 // state. 1926 dispatchWallpaperVisibility(wallpaper, visible); 1927 1928 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment; 1929 if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win " 1930 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); 1931 1932 // First, if this window is at the current index, then all 1933 // is well. 1934 if (wallpaper == foundW) { 1935 foundI--; 1936 foundW = foundI > 0 1937 ? windows.get(foundI-1) : null; 1938 continue; 1939 } 1940 1941 // The window didn't match... the current wallpaper window, 1942 // wherever it is, is in the wrong place, so make sure it is 1943 // not in the list. 1944 int oldIndex = windows.indexOf(wallpaper); 1945 if (oldIndex >= 0) { 1946 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at " 1947 + oldIndex + ": " + wallpaper); 1948 windows.remove(oldIndex); 1949 mWindowsChanged = true; 1950 if (oldIndex < foundI) { 1951 foundI--; 1952 } 1953 } 1954 1955 // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost 1956 // layer. For keyguard over wallpaper put the wallpaper under the keyguard. 1957 int insertionIndex = 0; 1958 if (visible && foundW != null) { 1959 final int type = foundW.mAttrs.type; 1960 final int privateFlags = foundW.mAttrs.privateFlags; 1961 if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 1962 || type == TYPE_KEYGUARD_SCRIM) { 1963 insertionIndex = windows.indexOf(foundW); 1964 } 1965 } 1966 if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) { 1967 Slog.v(TAG, "Moving wallpaper " + wallpaper 1968 + " from " + oldIndex + " to " + insertionIndex); 1969 } 1970 1971 windows.add(insertionIndex, wallpaper); 1972 mWindowsChanged = true; 1973 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED; 1974 } 1975 } 1976 1977 /* 1978 final TaskStack targetStack = 1979 mWallpaperTarget == null ? null : mWallpaperTarget.getStack(); 1980 if ((changed & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0 && 1981 targetStack != null && !targetStack.isHomeStack()) { 1982 // If the wallpaper target is not on the home stack then make sure that all windows 1983 // from other non-home stacks are above the wallpaper. 1984 for (i = foundI - 1; i >= 0; --i) { 1985 WindowState win = windows.get(i); 1986 if (!win.isVisibleLw()) { 1987 continue; 1988 } 1989 final TaskStack winStack = win.getStack(); 1990 if (winStack != null && !winStack.isHomeStack() && winStack != targetStack) { 1991 windows.remove(i); 1992 windows.add(foundI + 1, win); 1993 } 1994 } 1995 } 1996 */ 1997 1998 if (targetChanged && DEBUG_WALLPAPER_LIGHT) { 1999 Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget 2000 + " lower=" + mLowerWallpaperTarget + " upper=" 2001 + mUpperWallpaperTarget); 2002 } 2003 2004 return changed; 2005 } 2006 2007 void setWallpaperAnimLayerAdjustmentLocked(int adj) { 2008 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, 2009 "Setting wallpaper layer adj to " + adj); 2010 mWallpaperAnimLayerAdjustment = adj; 2011 int curTokenIndex = mWallpaperTokens.size(); 2012 while (curTokenIndex > 0) { 2013 curTokenIndex--; 2014 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2015 int curWallpaperIndex = token.windows.size(); 2016 while (curWallpaperIndex > 0) { 2017 curWallpaperIndex--; 2018 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2019 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj; 2020 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win " 2021 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); 2022 } 2023 } 2024 } 2025 2026 boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh, 2027 boolean sync) { 2028 boolean changed = false; 2029 boolean rawChanged = false; 2030 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f; 2031 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f; 2032 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw; 2033 int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0; 2034 changed = wallpaperWin.mXOffset != offset; 2035 if (changed) { 2036 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " 2037 + wallpaperWin + " x: " + offset); 2038 wallpaperWin.mXOffset = offset; 2039 } 2040 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) { 2041 wallpaperWin.mWallpaperX = wpx; 2042 wallpaperWin.mWallpaperXStep = wpxs; 2043 rawChanged = true; 2044 } 2045 2046 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f; 2047 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f; 2048 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh; 2049 offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0; 2050 if (wallpaperWin.mYOffset != offset) { 2051 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " 2052 + wallpaperWin + " y: " + offset); 2053 changed = true; 2054 wallpaperWin.mYOffset = offset; 2055 } 2056 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) { 2057 wallpaperWin.mWallpaperY = wpy; 2058 wallpaperWin.mWallpaperYStep = wpys; 2059 rawChanged = true; 2060 } 2061 2062 if (rawChanged && (wallpaperWin.mAttrs.privateFlags & 2063 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) { 2064 try { 2065 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset " 2066 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX 2067 + " y=" + wallpaperWin.mWallpaperY); 2068 if (sync) { 2069 mWaitingOnWallpaper = wallpaperWin; 2070 } 2071 wallpaperWin.mClient.dispatchWallpaperOffsets( 2072 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY, 2073 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync); 2074 if (sync) { 2075 if (mWaitingOnWallpaper != null) { 2076 long start = SystemClock.uptimeMillis(); 2077 if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY) 2078 < start) { 2079 try { 2080 if (DEBUG_WALLPAPER) Slog.v(TAG, 2081 "Waiting for offset complete..."); 2082 mWindowMap.wait(WALLPAPER_TIMEOUT); 2083 } catch (InterruptedException e) { 2084 } 2085 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!"); 2086 if ((start+WALLPAPER_TIMEOUT) 2087 < SystemClock.uptimeMillis()) { 2088 Slog.i(TAG, "Timeout waiting for wallpaper to offset: " 2089 + wallpaperWin); 2090 mLastWallpaperTimeoutTime = start; 2091 } 2092 } 2093 mWaitingOnWallpaper = null; 2094 } 2095 } 2096 } catch (RemoteException e) { 2097 } 2098 } 2099 2100 return changed; 2101 } 2102 2103 void wallpaperOffsetsComplete(IBinder window) { 2104 synchronized (mWindowMap) { 2105 if (mWaitingOnWallpaper != null && 2106 mWaitingOnWallpaper.mClient.asBinder() == window) { 2107 mWaitingOnWallpaper = null; 2108 mWindowMap.notifyAll(); 2109 } 2110 } 2111 } 2112 2113 void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) { 2114 final DisplayContent displayContent = changingTarget.getDisplayContent(); 2115 if (displayContent == null) { 2116 return; 2117 } 2118 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2119 final int dw = displayInfo.logicalWidth; 2120 final int dh = displayInfo.logicalHeight; 2121 2122 WindowState target = mWallpaperTarget; 2123 if (target != null) { 2124 if (target.mWallpaperX >= 0) { 2125 mLastWallpaperX = target.mWallpaperX; 2126 } else if (changingTarget.mWallpaperX >= 0) { 2127 mLastWallpaperX = changingTarget.mWallpaperX; 2128 } 2129 if (target.mWallpaperY >= 0) { 2130 mLastWallpaperY = target.mWallpaperY; 2131 } else if (changingTarget.mWallpaperY >= 0) { 2132 mLastWallpaperY = changingTarget.mWallpaperY; 2133 } 2134 } 2135 2136 int curTokenIndex = mWallpaperTokens.size(); 2137 while (curTokenIndex > 0) { 2138 curTokenIndex--; 2139 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2140 int curWallpaperIndex = token.windows.size(); 2141 while (curWallpaperIndex > 0) { 2142 curWallpaperIndex--; 2143 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2144 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) { 2145 WindowStateAnimator winAnimator = wallpaper.mWinAnimator; 2146 winAnimator.computeShownFrameLocked(); 2147 // No need to lay out the windows - we can just set the wallpaper position 2148 // directly. 2149 winAnimator.setWallpaperOffset(wallpaper.mShownFrame); 2150 // We only want to be synchronous with one wallpaper. 2151 sync = false; 2152 } 2153 } 2154 } 2155 } 2156 2157 /** 2158 * Check wallpaper for visiblity change and notify window if so. 2159 * @param wallpaper The wallpaper to test and notify. 2160 * @param visible Current visibility. 2161 */ 2162 void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) { 2163 if (wallpaper.mWallpaperVisible != visible) { 2164 wallpaper.mWallpaperVisible = visible; 2165 try { 2166 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 2167 "Updating vis of wallpaper " + wallpaper 2168 + ": " + visible + " from:\n" + Debug.getCallers(4, " ")); 2169 wallpaper.mClient.dispatchAppVisibility(visible); 2170 } catch (RemoteException e) { 2171 } 2172 } 2173 } 2174 2175 void updateWallpaperVisibilityLocked() { 2176 final boolean visible = isWallpaperVisible(mWallpaperTarget); 2177 final DisplayContent displayContent = mWallpaperTarget.getDisplayContent(); 2178 if (displayContent == null) { 2179 return; 2180 } 2181 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2182 final int dw = displayInfo.logicalWidth; 2183 final int dh = displayInfo.logicalHeight; 2184 2185 int curTokenIndex = mWallpaperTokens.size(); 2186 while (curTokenIndex > 0) { 2187 curTokenIndex--; 2188 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2189 if (token.hidden == visible) { 2190 token.hidden = !visible; 2191 // Need to do a layout to ensure the wallpaper now has the 2192 // correct size. 2193 getDefaultDisplayContentLocked().layoutNeeded = true; 2194 } 2195 2196 int curWallpaperIndex = token.windows.size(); 2197 while (curWallpaperIndex > 0) { 2198 curWallpaperIndex--; 2199 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2200 if (visible) { 2201 updateWallpaperOffsetLocked(wallpaper, dw, dh, false); 2202 } 2203 2204 dispatchWallpaperVisibility(wallpaper, visible); 2205 } 2206 } 2207 } 2208 2209 public int addWindow(Session session, IWindow client, int seq, 2210 WindowManager.LayoutParams attrs, int viewVisibility, int displayId, 2211 Rect outContentInsets, InputChannel outInputChannel) { 2212 int[] appOp = new int[1]; 2213 int res = mPolicy.checkAddPermission(attrs, appOp); 2214 if (res != WindowManagerGlobal.ADD_OKAY) { 2215 return res; 2216 } 2217 2218 boolean reportNewConfig = false; 2219 WindowState attachedWindow = null; 2220 WindowState win = null; 2221 long origId; 2222 final int type = attrs.type; 2223 2224 synchronized(mWindowMap) { 2225 if (!mDisplayReady) { 2226 throw new IllegalStateException("Display has not been initialialized"); 2227 } 2228 2229 final DisplayContent displayContent = getDisplayContentLocked(displayId); 2230 if (displayContent == null) { 2231 Slog.w(TAG, "Attempted to add window to a display that does not exist: " 2232 + displayId + ". Aborting."); 2233 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2234 } 2235 if (!displayContent.hasAccess(session.mUid)) { 2236 Slog.w(TAG, "Attempted to add window to a display for which the application " 2237 + "does not have access: " + displayId + ". Aborting."); 2238 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2239 } 2240 2241 if (mWindowMap.containsKey(client.asBinder())) { 2242 Slog.w(TAG, "Window " + client + " is already added"); 2243 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 2244 } 2245 2246 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) { 2247 attachedWindow = windowForClientLocked(null, attrs.token, false); 2248 if (attachedWindow == null) { 2249 Slog.w(TAG, "Attempted to add window with token that is not a window: " 2250 + attrs.token + ". Aborting."); 2251 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 2252 } 2253 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW 2254 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) { 2255 Slog.w(TAG, "Attempted to add window with token that is a sub-window: " 2256 + attrs.token + ". Aborting."); 2257 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 2258 } 2259 } 2260 2261 if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) { 2262 Slog.w(TAG, "Attempted to add private presentation window to a non-private display. Aborting."); 2263 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 2264 } 2265 2266 boolean addToken = false; 2267 WindowToken token = mTokenMap.get(attrs.token); 2268 if (token == null) { 2269 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2270 Slog.w(TAG, "Attempted to add application window with unknown token " 2271 + attrs.token + ". Aborting."); 2272 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2273 } 2274 if (type == TYPE_INPUT_METHOD) { 2275 Slog.w(TAG, "Attempted to add input method window with unknown token " 2276 + attrs.token + ". Aborting."); 2277 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2278 } 2279 if (type == TYPE_VOICE_INTERACTION) { 2280 Slog.w(TAG, "Attempted to add voice interaction window with unknown token " 2281 + attrs.token + ". Aborting."); 2282 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2283 } 2284 if (type == TYPE_WALLPAPER) { 2285 Slog.w(TAG, "Attempted to add wallpaper window with unknown token " 2286 + attrs.token + ". Aborting."); 2287 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2288 } 2289 if (type == TYPE_DREAM) { 2290 Slog.w(TAG, "Attempted to add Dream window with unknown token " 2291 + attrs.token + ". Aborting."); 2292 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2293 } 2294 token = new WindowToken(this, attrs.token, -1, false); 2295 addToken = true; 2296 } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2297 AppWindowToken atoken = token.appWindowToken; 2298 if (atoken == null) { 2299 Slog.w(TAG, "Attempted to add window with non-application token " 2300 + token + ". Aborting."); 2301 return WindowManagerGlobal.ADD_NOT_APP_TOKEN; 2302 } else if (atoken.removed) { 2303 Slog.w(TAG, "Attempted to add window with exiting application token " 2304 + token + ". Aborting."); 2305 return WindowManagerGlobal.ADD_APP_EXITING; 2306 } 2307 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) { 2308 // No need for this guy! 2309 if (localLOGV) Slog.v( 2310 TAG, "**** NO NEED TO START: " + attrs.getTitle()); 2311 return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED; 2312 } 2313 } else if (type == TYPE_INPUT_METHOD) { 2314 if (token.windowType != TYPE_INPUT_METHOD) { 2315 Slog.w(TAG, "Attempted to add input method window with bad token " 2316 + attrs.token + ". Aborting."); 2317 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2318 } 2319 } else if (type == TYPE_VOICE_INTERACTION) { 2320 if (token.windowType != TYPE_VOICE_INTERACTION) { 2321 Slog.w(TAG, "Attempted to add voice interaction window with bad token " 2322 + attrs.token + ". Aborting."); 2323 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2324 } 2325 } else if (type == TYPE_WALLPAPER) { 2326 if (token.windowType != TYPE_WALLPAPER) { 2327 Slog.w(TAG, "Attempted to add wallpaper window with bad token " 2328 + attrs.token + ". Aborting."); 2329 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2330 } 2331 } else if (type == TYPE_DREAM) { 2332 if (token.windowType != TYPE_DREAM) { 2333 Slog.w(TAG, "Attempted to add Dream window with bad token " 2334 + attrs.token + ". Aborting."); 2335 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2336 } 2337 } else if (token.appWindowToken != null) { 2338 Slog.i(TAG, "Non-null appWindowToken for system window of type=" + type); 2339 // app token should be null for any other window types. 2340 token.appWindowToken = null; 2341 } 2342 2343 win = new WindowState(this, session, client, token, 2344 attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent); 2345 if (win.mDeathRecipient == null) { 2346 // Client has apparently died, so there is no reason to 2347 // continue. 2348 Slog.w(TAG, "Adding window client " + client.asBinder() 2349 + " that is dead, aborting."); 2350 return WindowManagerGlobal.ADD_APP_EXITING; 2351 } 2352 2353 if (win.getDisplayContent() == null) { 2354 Slog.w(TAG, "Adding window to Display that has been removed."); 2355 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2356 } 2357 2358 mPolicy.adjustWindowParamsLw(win.mAttrs); 2359 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs)); 2360 2361 res = mPolicy.prepareAddWindowLw(win, attrs); 2362 if (res != WindowManagerGlobal.ADD_OKAY) { 2363 return res; 2364 } 2365 2366 if (outInputChannel != null && (attrs.inputFeatures 2367 & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) { 2368 String name = win.makeInputChannelName(); 2369 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); 2370 win.setInputChannel(inputChannels[0]); 2371 inputChannels[1].transferTo(outInputChannel); 2372 2373 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle); 2374 } 2375 2376 // From now on, no exceptions or errors allowed! 2377 2378 res = WindowManagerGlobal.ADD_OKAY; 2379 2380 origId = Binder.clearCallingIdentity(); 2381 2382 if (addToken) { 2383 Slog.w("BadTokenDebug", "addWindow: Adding token=" + token + " attrs.token=" + attrs.token); 2384 mTokenMap.put(attrs.token, token); 2385 } 2386 win.attach(); 2387 mWindowMap.put(client.asBinder(), win); 2388 if (win.mAppOp != AppOpsManager.OP_NONE) { 2389 if (mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage()) 2390 != AppOpsManager.MODE_ALLOWED) { 2391 win.setAppOpVisibilityLw(false); 2392 } 2393 } 2394 2395 if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) { 2396 token.appWindowToken.startingWindow = win; 2397 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken 2398 + " startingWindow=" + win); 2399 } 2400 2401 boolean imMayMove = true; 2402 2403 if (type == TYPE_INPUT_METHOD) { 2404 win.mGivenInsetsPending = true; 2405 mInputMethodWindow = win; 2406 addInputMethodWindowToListLocked(win); 2407 imMayMove = false; 2408 } else if (type == TYPE_INPUT_METHOD_DIALOG) { 2409 mInputMethodDialogs.add(win); 2410 addWindowToListInOrderLocked(win, true); 2411 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true)); 2412 imMayMove = false; 2413 } else { 2414 addWindowToListInOrderLocked(win, true); 2415 if (type == TYPE_WALLPAPER) { 2416 mLastWallpaperTimeoutTime = 0; 2417 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2418 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2419 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2420 } else if (mWallpaperTarget != null 2421 && mWallpaperTarget.mLayer >= win.mBaseLayer) { 2422 // If there is currently a wallpaper being shown, and 2423 // the base layer of the new window is below the current 2424 // layer of the target window, then adjust the wallpaper. 2425 // This is to avoid a new window being placed between the 2426 // wallpaper and its target. 2427 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2428 } 2429 } 2430 2431 win.mWinAnimator.mEnterAnimationPending = true; 2432 2433 if (displayContent.isDefaultDisplay) { 2434 mPolicy.getContentInsetHintLw(attrs, outContentInsets); 2435 } else { 2436 outContentInsets.setEmpty(); 2437 } 2438 2439 if (mInTouchMode) { 2440 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE; 2441 } 2442 if (win.mAppToken == null || !win.mAppToken.clientHidden) { 2443 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE; 2444 } 2445 2446 mInputMonitor.setUpdateInputWindowsNeededLw(); 2447 2448 boolean focusChanged = false; 2449 if (win.canReceiveKeys()) { 2450 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, 2451 false /*updateInputWindows*/); 2452 if (focusChanged) { 2453 imMayMove = false; 2454 } 2455 } 2456 2457 if (imMayMove) { 2458 moveInputMethodWindowsIfNeededLocked(false); 2459 } 2460 2461 assignLayersLocked(displayContent.getWindowList()); 2462 // Don't do layout here, the window must call 2463 // relayout to be displayed, so we'll do it there. 2464 2465 if (focusChanged) { 2466 mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/); 2467 } 2468 mInputMonitor.updateInputWindowsLw(false /*force*/); 2469 2470 if (localLOGV) Slog.v( 2471 TAG, "New client " + client.asBinder() 2472 + ": window=" + win); 2473 2474 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) { 2475 reportNewConfig = true; 2476 } 2477 } 2478 2479 if (reportNewConfig) { 2480 sendNewConfiguration(); 2481 } 2482 2483 Binder.restoreCallingIdentity(origId); 2484 2485 return res; 2486 } 2487 2488 /** 2489 * Returns whether screen capture is disabled for all windows of a specific user. 2490 */ 2491 boolean isScreenCaptureDisabledLocked(int userId) { 2492 Boolean disabled = mScreenCaptureDisabled.get(userId); 2493 if (disabled == null) { 2494 return false; 2495 } 2496 return disabled; 2497 } 2498 2499 /** 2500 * Set mScreenCaptureDisabled for specific user 2501 */ 2502 @Override 2503 public void setScreenCaptureDisabled(int userId, boolean disabled) { 2504 int callingUid = Binder.getCallingUid(); 2505 if (callingUid != Process.SYSTEM_UID) { 2506 throw new SecurityException("Only system can call setScreenCaptureDisabled."); 2507 } 2508 2509 synchronized(mWindowMap) { 2510 mScreenCaptureDisabled.put(userId, disabled); 2511 } 2512 } 2513 2514 public void removeWindow(Session session, IWindow client) { 2515 synchronized(mWindowMap) { 2516 WindowState win = windowForClientLocked(session, client, false); 2517 if (win == null) { 2518 return; 2519 } 2520 removeWindowLocked(session, win); 2521 } 2522 } 2523 2524 public void removeWindowLocked(Session session, WindowState win) { 2525 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2526 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Starting window removed " + win); 2527 } 2528 2529 if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v( 2530 TAG, "Remove " + win + " client=" 2531 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder())) 2532 + ", surface=" + win.mWinAnimator.mSurfaceControl + " Callers=" 2533 + Debug.getCallers(4)); 2534 2535 final long origId = Binder.clearCallingIdentity(); 2536 2537 win.disposeInputChannel(); 2538 2539 if (DEBUG_APP_TRANSITIONS) Slog.v( 2540 TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurfaceControl 2541 + " mExiting=" + win.mExiting 2542 + " isAnimating=" + win.mWinAnimator.isAnimating() 2543 + " app-animation=" 2544 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null) 2545 + " inPendingTransaction=" 2546 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false) 2547 + " mDisplayFrozen=" + mDisplayFrozen); 2548 // Visibility of the removed window. Will be used later to update orientation later on. 2549 boolean wasVisible = false; 2550 // First, see if we need to run an animation. If we do, we have 2551 // to hold off on removing the window until the animation is done. 2552 // If the display is frozen, just remove immediately, since the 2553 // animation wouldn't be seen. 2554 if (win.mHasSurface && okToDisplay()) { 2555 // If we are not currently running the exit animation, we 2556 // need to see about starting one. 2557 wasVisible = win.isWinVisibleLw(); 2558 if (wasVisible) { 2559 2560 int transit = WindowManagerPolicy.TRANSIT_EXIT; 2561 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2562 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 2563 } 2564 // Try starting an animation. 2565 if (win.mWinAnimator.applyAnimationLocked(transit, false)) { 2566 win.mExiting = true; 2567 } 2568 //TODO (multidisplay): Magnification is supported only for the default display. 2569 if (mAccessibilityController != null 2570 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 2571 mAccessibilityController.onWindowTransitionLocked(win, transit); 2572 } 2573 } 2574 if (win.mExiting || win.mWinAnimator.isAnimating()) { 2575 // The exit animation is running... wait for it! 2576 //Slog.i(TAG, "*** Running exit animation..."); 2577 win.mExiting = true; 2578 win.mRemoveOnExit = true; 2579 final DisplayContent displayContent = win.getDisplayContent(); 2580 if (displayContent != null) { 2581 displayContent.layoutNeeded = true; 2582 } 2583 final boolean focusChanged = updateFocusedWindowLocked( 2584 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/); 2585 performLayoutAndPlaceSurfacesLocked(); 2586 if (win.mAppToken != null) { 2587 win.mAppToken.updateReportedVisibilityLocked(); 2588 } 2589 if (focusChanged) { 2590 mInputMonitor.updateInputWindowsLw(false /*force*/); 2591 } 2592 //dump(); 2593 Binder.restoreCallingIdentity(origId); 2594 return; 2595 } 2596 } 2597 2598 removeWindowInnerLocked(session, win); 2599 // Removing a visible window will effect the computed orientation 2600 // So just update orientation if needed. 2601 if (wasVisible && updateOrientationFromAppTokensLocked(false)) { 2602 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 2603 } 2604 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 2605 Binder.restoreCallingIdentity(origId); 2606 } 2607 2608 void removeWindowInnerLocked(Session session, WindowState win) { 2609 if (win.mRemoved) { 2610 // Nothing to do. 2611 return; 2612 } 2613 2614 for (int i=win.mChildWindows.size()-1; i>=0; i--) { 2615 WindowState cwin = win.mChildWindows.get(i); 2616 Slog.w(TAG, "Force-removing child win " + cwin + " from container " 2617 + win); 2618 removeWindowInnerLocked(cwin.mSession, cwin); 2619 } 2620 2621 win.mRemoved = true; 2622 2623 if (mInputMethodTarget == win) { 2624 moveInputMethodWindowsIfNeededLocked(false); 2625 } 2626 2627 if (false) { 2628 RuntimeException e = new RuntimeException("here"); 2629 e.fillInStackTrace(); 2630 Slog.w(TAG, "Removing window " + win, e); 2631 } 2632 2633 mPolicy.removeWindowLw(win); 2634 win.removeLocked(); 2635 2636 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win); 2637 mWindowMap.remove(win.mClient.asBinder()); 2638 if (win.mAppOp != AppOpsManager.OP_NONE) { 2639 mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage()); 2640 } 2641 2642 mPendingRemove.remove(win); 2643 mResizingWindows.remove(win); 2644 mWindowsChanged = true; 2645 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win); 2646 2647 if (mInputMethodWindow == win) { 2648 mInputMethodWindow = null; 2649 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) { 2650 mInputMethodDialogs.remove(win); 2651 } 2652 2653 final WindowToken token = win.mToken; 2654 final AppWindowToken atoken = win.mAppToken; 2655 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token); 2656 token.windows.remove(win); 2657 if (atoken != null) { 2658 atoken.allAppWindows.remove(win); 2659 } 2660 if (localLOGV) Slog.v( 2661 TAG, "**** Removing window " + win + ": count=" 2662 + token.windows.size()); 2663 if (token.windows.size() == 0) { 2664 if (!token.explicit) { 2665 WindowToken wtoken = mTokenMap.remove(token.token); 2666 Slog.w("BadTokenDebug", "removeWindowInnerLocked: Removing token=" + token + " removed=" + 2667 wtoken + " Callers=" + Debug.getCallers(4)); 2668 } else if (atoken != null) { 2669 atoken.firstWindowDrawn = false; 2670 } 2671 } 2672 2673 if (atoken != null) { 2674 if (atoken.startingWindow == win) { 2675 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling startingWindow " + win); 2676 atoken.startingWindow = null; 2677 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) { 2678 // If this is the last window and we had requested a starting 2679 // transition window, well there is no point now. 2680 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling last startingWindow"); 2681 atoken.startingData = null; 2682 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) { 2683 // If this is the last window except for a starting transition 2684 // window, we need to get rid of the starting transition. 2685 scheduleRemoveStartingWindow(atoken); 2686 } 2687 } 2688 2689 if (win.mAttrs.type == TYPE_WALLPAPER) { 2690 mLastWallpaperTimeoutTime = 0; 2691 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2692 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2693 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2694 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2695 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2696 } 2697 2698 final WindowList windows = win.getWindowList(); 2699 if (windows != null) { 2700 windows.remove(win); 2701 if (!mInLayout) { 2702 assignLayersLocked(windows); 2703 final DisplayContent displayContent = win.getDisplayContent(); 2704 if (displayContent != null) { 2705 displayContent.layoutNeeded = true; 2706 } 2707 performLayoutAndPlaceSurfacesLocked(); 2708 if (win.mAppToken != null) { 2709 win.mAppToken.updateReportedVisibilityLocked(); 2710 } 2711 } 2712 } 2713 2714 mInputMonitor.updateInputWindowsLw(true /*force*/); 2715 } 2716 2717 public void updateAppOpsState() { 2718 synchronized(mWindowMap) { 2719 final int numDisplays = mDisplayContents.size(); 2720 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 2721 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 2722 final int numWindows = windows.size(); 2723 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 2724 final WindowState win = windows.get(winNdx); 2725 if (win.mAppOp != AppOpsManager.OP_NONE) { 2726 final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(), 2727 win.getOwningPackage()); 2728 win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED); 2729 } 2730 } 2731 } 2732 } 2733 } 2734 2735 static void logSurface(WindowState w, String msg, RuntimeException where) { 2736 String str = " SURFACE " + msg + ": " + w; 2737 if (where != null) { 2738 Slog.i(TAG, str, where); 2739 } else { 2740 Slog.i(TAG, str); 2741 } 2742 } 2743 2744 static void logSurface(SurfaceControl s, String title, String msg, RuntimeException where) { 2745 String str = " SURFACE " + s + ": " + msg + " / " + title; 2746 if (where != null) { 2747 Slog.i(TAG, str, where); 2748 } else { 2749 Slog.i(TAG, str); 2750 } 2751 } 2752 2753 void setTransparentRegionWindow(Session session, IWindow client, Region region) { 2754 long origId = Binder.clearCallingIdentity(); 2755 try { 2756 synchronized (mWindowMap) { 2757 WindowState w = windowForClientLocked(session, client, false); 2758 if ((w != null) && w.mHasSurface) { 2759 w.mWinAnimator.setTransparentRegionHintLocked(region); 2760 } 2761 } 2762 } finally { 2763 Binder.restoreCallingIdentity(origId); 2764 } 2765 } 2766 2767 void setInsetsWindow(Session session, IWindow client, 2768 int touchableInsets, Rect contentInsets, 2769 Rect visibleInsets, Region touchableRegion) { 2770 long origId = Binder.clearCallingIdentity(); 2771 try { 2772 synchronized (mWindowMap) { 2773 WindowState w = windowForClientLocked(session, client, false); 2774 if (w != null) { 2775 w.mGivenInsetsPending = false; 2776 w.mGivenContentInsets.set(contentInsets); 2777 w.mGivenVisibleInsets.set(visibleInsets); 2778 w.mGivenTouchableRegion.set(touchableRegion); 2779 w.mTouchableInsets = touchableInsets; 2780 if (w.mGlobalScale != 1) { 2781 w.mGivenContentInsets.scale(w.mGlobalScale); 2782 w.mGivenVisibleInsets.scale(w.mGlobalScale); 2783 w.mGivenTouchableRegion.scale(w.mGlobalScale); 2784 } 2785 final DisplayContent displayContent = w.getDisplayContent(); 2786 if (displayContent != null) { 2787 displayContent.layoutNeeded = true; 2788 } 2789 performLayoutAndPlaceSurfacesLocked(); 2790 } 2791 } 2792 } finally { 2793 Binder.restoreCallingIdentity(origId); 2794 } 2795 } 2796 2797 public void getWindowDisplayFrame(Session session, IWindow client, 2798 Rect outDisplayFrame) { 2799 synchronized(mWindowMap) { 2800 WindowState win = windowForClientLocked(session, client, false); 2801 if (win == null) { 2802 outDisplayFrame.setEmpty(); 2803 return; 2804 } 2805 outDisplayFrame.set(win.mDisplayFrame); 2806 } 2807 } 2808 2809 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y, 2810 float xStep, float yStep) { 2811 if (window.mWallpaperX != x || window.mWallpaperY != y) { 2812 window.mWallpaperX = x; 2813 window.mWallpaperY = y; 2814 window.mWallpaperXStep = xStep; 2815 window.mWallpaperYStep = yStep; 2816 updateWallpaperOffsetLocked(window, true); 2817 } 2818 } 2819 2820 void wallpaperCommandComplete(IBinder window, Bundle result) { 2821 synchronized (mWindowMap) { 2822 if (mWaitingOnWallpaper != null && 2823 mWaitingOnWallpaper.mClient.asBinder() == window) { 2824 mWaitingOnWallpaper = null; 2825 mWindowMap.notifyAll(); 2826 } 2827 } 2828 } 2829 2830 public Bundle sendWindowWallpaperCommandLocked(WindowState window, 2831 String action, int x, int y, int z, Bundle extras, boolean sync) { 2832 if (window == mWallpaperTarget || window == mLowerWallpaperTarget 2833 || window == mUpperWallpaperTarget) { 2834 boolean doWait = sync; 2835 int curTokenIndex = mWallpaperTokens.size(); 2836 while (curTokenIndex > 0) { 2837 curTokenIndex--; 2838 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2839 int curWallpaperIndex = token.windows.size(); 2840 while (curWallpaperIndex > 0) { 2841 curWallpaperIndex--; 2842 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2843 try { 2844 wallpaper.mClient.dispatchWallpaperCommand(action, 2845 x, y, z, extras, sync); 2846 // We only want to be synchronous with one wallpaper. 2847 sync = false; 2848 } catch (RemoteException e) { 2849 } 2850 } 2851 } 2852 2853 if (doWait) { 2854 // XXX Need to wait for result. 2855 } 2856 } 2857 2858 return null; 2859 } 2860 2861 public void setUniverseTransformLocked(WindowState window, float alpha, 2862 float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) { 2863 Transformation transform = window.mWinAnimator.mUniverseTransform; 2864 transform.setAlpha(alpha); 2865 Matrix matrix = transform.getMatrix(); 2866 matrix.getValues(mTmpFloats); 2867 mTmpFloats[Matrix.MTRANS_X] = offx; 2868 mTmpFloats[Matrix.MTRANS_Y] = offy; 2869 mTmpFloats[Matrix.MSCALE_X] = dsdx; 2870 mTmpFloats[Matrix.MSKEW_Y] = dtdx; 2871 mTmpFloats[Matrix.MSKEW_X] = dsdy; 2872 mTmpFloats[Matrix.MSCALE_Y] = dtdy; 2873 matrix.setValues(mTmpFloats); 2874 final DisplayContent displayContent = window.getDisplayContent(); 2875 if (displayContent == null) { 2876 return; 2877 } 2878 2879 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2880 final RectF dispRect = new RectF(0, 0, 2881 displayInfo.logicalWidth, displayInfo.logicalHeight); 2882 matrix.mapRect(dispRect); 2883 window.mGivenTouchableRegion.set(0, 0, 2884 displayInfo.logicalWidth, displayInfo.logicalHeight); 2885 window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top, 2886 (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE); 2887 window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; 2888 displayContent.layoutNeeded = true; 2889 performLayoutAndPlaceSurfacesLocked(); 2890 } 2891 2892 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) { 2893 synchronized (mWindowMap) { 2894 if (mAccessibilityController != null) { 2895 WindowState window = mWindowMap.get(token); 2896 //TODO (multidisplay): Magnification is supported only for the default display. 2897 if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 2898 mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle); 2899 } 2900 } 2901 } 2902 } 2903 2904 public IWindowId getWindowId(IBinder token) { 2905 synchronized (mWindowMap) { 2906 WindowState window = mWindowMap.get(token); 2907 return window != null ? window.mWindowId : null; 2908 } 2909 } 2910 2911 public int relayoutWindow(Session session, IWindow client, int seq, 2912 WindowManager.LayoutParams attrs, int requestedWidth, 2913 int requestedHeight, int viewVisibility, int flags, 2914 Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, 2915 Rect outVisibleInsets, Rect outStableInsets, Configuration outConfig, 2916 Surface outSurface) { 2917 boolean toBeDisplayed = false; 2918 boolean inTouchMode; 2919 boolean configChanged; 2920 boolean surfaceChanged = false; 2921 boolean animating; 2922 boolean hasStatusBarPermission = 2923 mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 2924 == PackageManager.PERMISSION_GRANTED; 2925 2926 long origId = Binder.clearCallingIdentity(); 2927 2928 synchronized(mWindowMap) { 2929 WindowState win = windowForClientLocked(session, client, false); 2930 if (win == null) { 2931 return 0; 2932 } 2933 WindowStateAnimator winAnimator = win.mWinAnimator; 2934 if (win.mRequestedWidth != requestedWidth 2935 || win.mRequestedHeight != requestedHeight) { 2936 win.mLayoutNeeded = true; 2937 win.mRequestedWidth = requestedWidth; 2938 win.mRequestedHeight = requestedHeight; 2939 } 2940 2941 if (attrs != null) { 2942 mPolicy.adjustWindowParamsLw(attrs); 2943 } 2944 2945 // if they don't have the permission, mask out the status bar bits 2946 int systemUiVisibility = 0; 2947 if (attrs != null) { 2948 systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility); 2949 if ((systemUiVisibility & StatusBarManager.DISABLE_MASK) != 0) { 2950 if (!hasStatusBarPermission) { 2951 systemUiVisibility &= ~StatusBarManager.DISABLE_MASK; 2952 } 2953 } 2954 } 2955 2956 if (attrs != null && seq == win.mSeq) { 2957 win.mSystemUiVisibility = systemUiVisibility; 2958 } 2959 2960 winAnimator.mSurfaceDestroyDeferred = 2961 (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0; 2962 2963 int attrChanges = 0; 2964 int flagChanges = 0; 2965 if (attrs != null) { 2966 if (win.mAttrs.type != attrs.type) { 2967 throw new IllegalArgumentException( 2968 "Window type can not be changed after the window is added."); 2969 } 2970 flagChanges = win.mAttrs.flags ^= attrs.flags; 2971 attrChanges = win.mAttrs.copyFrom(attrs); 2972 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED 2973 | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) { 2974 win.mLayoutNeeded = true; 2975 } 2976 } 2977 2978 if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility 2979 + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs); 2980 2981 win.mEnforceSizeCompat = 2982 (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0; 2983 2984 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) { 2985 winAnimator.mAlpha = attrs.alpha; 2986 } 2987 2988 final boolean scaledWindow = 2989 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0); 2990 2991 if (scaledWindow) { 2992 // requested{Width|Height} Surface's physical size 2993 // attrs.{width|height} Size on screen 2994 win.mHScale = (attrs.width != requestedWidth) ? 2995 (attrs.width / (float)requestedWidth) : 1.0f; 2996 win.mVScale = (attrs.height != requestedHeight) ? 2997 (attrs.height / (float)requestedHeight) : 1.0f; 2998 } else { 2999 win.mHScale = win.mVScale = 1; 3000 } 3001 3002 boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0; 3003 3004 final boolean isDefaultDisplay = win.isDefaultDisplay(); 3005 boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility 3006 || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0) 3007 || (!win.mRelayoutCalled)); 3008 3009 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility 3010 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0; 3011 wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0; 3012 3013 win.mRelayoutCalled = true; 3014 final int oldVisibility = win.mViewVisibility; 3015 win.mViewVisibility = viewVisibility; 3016 if (DEBUG_SCREEN_ON) { 3017 RuntimeException stack = new RuntimeException(); 3018 stack.fillInStackTrace(); 3019 Slog.i(TAG, "Relayout " + win + ": oldVis=" + oldVisibility 3020 + " newVis=" + viewVisibility, stack); 3021 } 3022 if (viewVisibility == View.VISIBLE && 3023 (win.mAppToken == null || !win.mAppToken.clientHidden)) { 3024 toBeDisplayed = !win.isVisibleLw(); 3025 if (win.mExiting) { 3026 winAnimator.cancelExitAnimationForNextAnimationLocked(); 3027 win.mExiting = false; 3028 } 3029 if (win.mDestroying) { 3030 win.mDestroying = false; 3031 mDestroySurface.remove(win); 3032 } 3033 if (oldVisibility == View.GONE) { 3034 winAnimator.mEnterAnimationPending = true; 3035 } 3036 if (toBeDisplayed) { 3037 if (win.isDrawnLw() && okToDisplay()) { 3038 winAnimator.applyEnterAnimationLocked(); 3039 } 3040 if ((win.mAttrs.flags 3041 & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) { 3042 if (DEBUG_VISIBILITY) Slog.v(TAG, 3043 "Relayout window turning screen on: " + win); 3044 win.mTurnOnScreen = true; 3045 } 3046 if (win.isConfigChanged()) { 3047 if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win 3048 + " visible with new config: " + mCurConfiguration); 3049 outConfig.setTo(mCurConfiguration); 3050 } 3051 } 3052 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) { 3053 // To change the format, we need to re-build the surface. 3054 winAnimator.destroySurfaceLocked(); 3055 toBeDisplayed = true; 3056 surfaceChanged = true; 3057 } 3058 try { 3059 if (!win.mHasSurface) { 3060 surfaceChanged = true; 3061 } 3062 SurfaceControl surfaceControl = winAnimator.createSurfaceLocked(); 3063 if (surfaceControl != null) { 3064 outSurface.copyFrom(surfaceControl); 3065 if (SHOW_TRANSACTIONS) Slog.i(TAG, 3066 " OUT SURFACE " + outSurface + ": copied"); 3067 } else { 3068 // For some reason there isn't a surface. Clear the 3069 // caller's object so they see the same state. 3070 outSurface.release(); 3071 } 3072 } catch (Exception e) { 3073 mInputMonitor.updateInputWindowsLw(true /*force*/); 3074 3075 Slog.w(TAG, "Exception thrown when creating surface for client " 3076 + client + " (" + win.mAttrs.getTitle() + ")", 3077 e); 3078 Binder.restoreCallingIdentity(origId); 3079 return 0; 3080 } 3081 if (toBeDisplayed) { 3082 focusMayChange = isDefaultDisplay; 3083 } 3084 if (win.mAttrs.type == TYPE_INPUT_METHOD 3085 && mInputMethodWindow == null) { 3086 mInputMethodWindow = win; 3087 imMayMove = true; 3088 } 3089 if (win.mAttrs.type == TYPE_BASE_APPLICATION 3090 && win.mAppToken != null 3091 && win.mAppToken.startingWindow != null) { 3092 // Special handling of starting window over the base 3093 // window of the app: propagate lock screen flags to it, 3094 // to provide the correct semantics while starting. 3095 final int mask = 3096 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED 3097 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD 3098 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; 3099 WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs; 3100 sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask); 3101 } 3102 } else { 3103 winAnimator.mEnterAnimationPending = false; 3104 if (winAnimator.mSurfaceControl != null) { 3105 if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win 3106 + ": mExiting=" + win.mExiting); 3107 // If we are not currently running the exit animation, we 3108 // need to see about starting one. 3109 if (!win.mExiting) { 3110 surfaceChanged = true; 3111 // Try starting an animation; if there isn't one, we 3112 // can destroy the surface right away. 3113 int transit = WindowManagerPolicy.TRANSIT_EXIT; 3114 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 3115 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 3116 } 3117 if (win.isWinVisibleLw() && 3118 winAnimator.applyAnimationLocked(transit, false)) { 3119 focusMayChange = isDefaultDisplay; 3120 win.mExiting = true; 3121 } else if (win.mWinAnimator.isAnimating()) { 3122 // Currently in a hide animation... turn this into 3123 // an exit. 3124 win.mExiting = true; 3125 } else if (win == mWallpaperTarget) { 3126 // If the wallpaper is currently behind this 3127 // window, we need to change both of them inside 3128 // of a transaction to avoid artifacts. 3129 win.mExiting = true; 3130 win.mWinAnimator.mAnimating = true; 3131 } else { 3132 if (mInputMethodWindow == win) { 3133 mInputMethodWindow = null; 3134 } 3135 winAnimator.destroySurfaceLocked(); 3136 } 3137 //TODO (multidisplay): Magnification is supported only for the default 3138 if (mAccessibilityController != null 3139 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 3140 mAccessibilityController.onWindowTransitionLocked(win, transit); 3141 } 3142 } 3143 } 3144 3145 outSurface.release(); 3146 if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win); 3147 } 3148 3149 if (focusMayChange) { 3150 //System.out.println("Focus may change: " + win.mAttrs.getTitle()); 3151 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 3152 false /*updateInputWindows*/)) { 3153 imMayMove = false; 3154 } 3155 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus); 3156 } 3157 3158 // updateFocusedWindowLocked() already assigned layers so we only need to 3159 // reassign them at this point if the IM window state gets shuffled 3160 if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) { 3161 // Little hack here -- we -should- be able to rely on the 3162 // function to return true if the IME has moved and needs 3163 // its layer recomputed. However, if the IME was hidden 3164 // and isn't actually moved in the list, its layer may be 3165 // out of data so we make sure to recompute it. 3166 assignLayersLocked(win.getWindowList()); 3167 } 3168 3169 if (wallpaperMayMove) { 3170 getDefaultDisplayContentLocked().pendingLayoutChanges |= 3171 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 3172 } 3173 3174 final DisplayContent displayContent = win.getDisplayContent(); 3175 if (displayContent != null) { 3176 displayContent.layoutNeeded = true; 3177 } 3178 win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0; 3179 configChanged = updateOrientationFromAppTokensLocked(false); 3180 performLayoutAndPlaceSurfacesLocked(); 3181 if (toBeDisplayed && win.mIsWallpaper) { 3182 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 3183 updateWallpaperOffsetLocked(win, 3184 displayInfo.logicalWidth, displayInfo.logicalHeight, false); 3185 } 3186 if (win.mAppToken != null) { 3187 win.mAppToken.updateReportedVisibilityLocked(); 3188 } 3189 outFrame.set(win.mCompatFrame); 3190 outOverscanInsets.set(win.mOverscanInsets); 3191 outContentInsets.set(win.mContentInsets); 3192 outVisibleInsets.set(win.mVisibleInsets); 3193 outStableInsets.set(win.mStableInsets); 3194 if (localLOGV) Slog.v( 3195 TAG, "Relayout given client " + client.asBinder() 3196 + ", requestedWidth=" + requestedWidth 3197 + ", requestedHeight=" + requestedHeight 3198 + ", viewVisibility=" + viewVisibility 3199 + "\nRelayout returning frame=" + outFrame 3200 + ", surface=" + outSurface); 3201 3202 if (localLOGV || DEBUG_FOCUS) Slog.v( 3203 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange); 3204 3205 inTouchMode = mInTouchMode; 3206 animating = mAnimator.mAnimating && win.mWinAnimator.isAnimating(); 3207 if (animating && !mRelayoutWhileAnimating.contains(win)) { 3208 mRelayoutWhileAnimating.add(win); 3209 } 3210 3211 mInputMonitor.updateInputWindowsLw(true /*force*/); 3212 3213 if (DEBUG_LAYOUT) { 3214 Slog.v(TAG, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString()); 3215 } 3216 } 3217 3218 if (configChanged) { 3219 sendNewConfiguration(); 3220 } 3221 3222 Binder.restoreCallingIdentity(origId); 3223 3224 return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0) 3225 | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0) 3226 | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0) 3227 | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0); 3228 } 3229 3230 public void performDeferredDestroyWindow(Session session, IWindow client) { 3231 long origId = Binder.clearCallingIdentity(); 3232 3233 try { 3234 synchronized (mWindowMap) { 3235 WindowState win = windowForClientLocked(session, client, false); 3236 if (win == null) { 3237 return; 3238 } 3239 win.mWinAnimator.destroyDeferredSurfaceLocked(); 3240 } 3241 } finally { 3242 Binder.restoreCallingIdentity(origId); 3243 } 3244 } 3245 3246 public boolean outOfMemoryWindow(Session session, IWindow client) { 3247 long origId = Binder.clearCallingIdentity(); 3248 3249 try { 3250 synchronized (mWindowMap) { 3251 WindowState win = windowForClientLocked(session, client, false); 3252 if (win == null) { 3253 return false; 3254 } 3255 return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false); 3256 } 3257 } finally { 3258 Binder.restoreCallingIdentity(origId); 3259 } 3260 } 3261 3262 public void finishDrawingWindow(Session session, IWindow client) { 3263 final long origId = Binder.clearCallingIdentity(); 3264 try { 3265 synchronized (mWindowMap) { 3266 WindowState win = windowForClientLocked(session, client, false); 3267 if (win != null && win.mWinAnimator.finishDrawingLocked()) { 3268 if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 3269 getDefaultDisplayContentLocked().pendingLayoutChanges |= 3270 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 3271 } 3272 final DisplayContent displayContent = win.getDisplayContent(); 3273 if (displayContent != null) { 3274 displayContent.layoutNeeded = true; 3275 } 3276 requestTraversalLocked(); 3277 } 3278 } 3279 } finally { 3280 Binder.restoreCallingIdentity(origId); 3281 } 3282 } 3283 3284 private boolean applyAnimationLocked(AppWindowToken atoken, 3285 WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction) { 3286 // Only apply an animation if the display isn't frozen. If it is 3287 // frozen, there is no reason to animate and it can cause strange 3288 // artifacts when we unfreeze the display if some different animation 3289 // is running. 3290 if (okToDisplay()) { 3291 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 3292 final int width = displayInfo.appWidth; 3293 final int height = displayInfo.appHeight; 3294 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation: atoken=" 3295 + atoken); 3296 3297 // Determine the visible rect to calculate the thumbnail clip 3298 WindowState win = atoken.findMainWindow(); 3299 Rect containingFrame = new Rect(0, 0, width, height); 3300 Rect contentInsets = new Rect(); 3301 boolean isFullScreen = true; 3302 if (win != null) { 3303 if (win.mContainingFrame != null) { 3304 containingFrame.set(win.mContainingFrame); 3305 } 3306 if (win.mContentInsets != null) { 3307 contentInsets.set(win.mContentInsets); 3308 } 3309 isFullScreen = 3310 ((win.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN) == 3311 SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN); 3312 } 3313 3314 if (atoken.mLaunchTaskBehind) { 3315 // Differentiate the two animations. This one which is briefly on the screen 3316 // gets the !enter animation, and the other activity which remains on the 3317 // screen gets the enter animation. Both appear in the mOpeningApps set. 3318 enter = false; 3319 } 3320 Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height, 3321 mCurConfiguration.orientation, containingFrame, contentInsets, isFullScreen, 3322 isVoiceInteraction); 3323 if (a != null) { 3324 if (DEBUG_ANIM) { 3325 RuntimeException e = null; 3326 if (!HIDE_STACK_CRAWLS) { 3327 e = new RuntimeException(); 3328 e.fillInStackTrace(); 3329 } 3330 Slog.v(TAG, "Loaded animation " + a + " for " + atoken, e); 3331 } 3332 atoken.mAppAnimator.setAnimation(a, width, height); 3333 } 3334 } else { 3335 atoken.mAppAnimator.clearAnimation(); 3336 } 3337 3338 return atoken.mAppAnimator.animation != null; 3339 } 3340 3341 // ------------------------------------------------------------- 3342 // Application Window Tokens 3343 // ------------------------------------------------------------- 3344 3345 public void validateAppTokens(int stackId, List<TaskGroup> tasks) { 3346 synchronized (mWindowMap) { 3347 int t = tasks.size() - 1; 3348 if (t < 0) { 3349 Slog.w(TAG, "validateAppTokens: empty task list"); 3350 return; 3351 } 3352 3353 TaskGroup task = tasks.get(0); 3354 int taskId = task.taskId; 3355 Task targetTask = mTaskIdToTask.get(taskId); 3356 DisplayContent displayContent = targetTask.getDisplayContent(); 3357 if (displayContent == null) { 3358 Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId); 3359 return; 3360 } 3361 3362 final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks(); 3363 int taskNdx; 3364 for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) { 3365 AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens; 3366 task = tasks.get(t); 3367 List<IApplicationToken> tokens = task.tokens; 3368 3369 DisplayContent lastDisplayContent = displayContent; 3370 displayContent = mTaskIdToTask.get(taskId).getDisplayContent(); 3371 if (displayContent != lastDisplayContent) { 3372 Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!"); 3373 return; 3374 } 3375 3376 int tokenNdx; 3377 int v; 3378 for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1; 3379 tokenNdx >= 0 && v >= 0; ) { 3380 final AppWindowToken atoken = localTokens.get(tokenNdx); 3381 if (atoken.removed) { 3382 --tokenNdx; 3383 continue; 3384 } 3385 if (tokens.get(v) != atoken.token) { 3386 break; 3387 } 3388 --tokenNdx; 3389 v--; 3390 } 3391 3392 if (tokenNdx >= 0 || v >= 0) { 3393 break; 3394 } 3395 } 3396 3397 if (taskNdx >= 0 || t >= 0) { 3398 Slog.w(TAG, "validateAppTokens: Mismatch! ActivityManager=" + tasks); 3399 Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager=" + localTasks); 3400 Slog.w(TAG, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4)); 3401 } 3402 } 3403 } 3404 3405 public void validateStackOrder(Integer[] remoteStackIds) { 3406 // TODO: 3407 } 3408 3409 boolean checkCallingPermission(String permission, String func) { 3410 // Quick check: if the calling permission is me, it's all okay. 3411 if (Binder.getCallingPid() == Process.myPid()) { 3412 return true; 3413 } 3414 3415 if (mContext.checkCallingPermission(permission) 3416 == PackageManager.PERMISSION_GRANTED) { 3417 return true; 3418 } 3419 String msg = "Permission Denial: " + func + " from pid=" 3420 + Binder.getCallingPid() 3421 + ", uid=" + Binder.getCallingUid() 3422 + " requires " + permission; 3423 Slog.w(TAG, msg); 3424 return false; 3425 } 3426 3427 boolean okToDisplay() { 3428 return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully(); 3429 } 3430 3431 AppWindowToken findAppWindowToken(IBinder token) { 3432 WindowToken wtoken = mTokenMap.get(token); 3433 if (wtoken == null) { 3434 return null; 3435 } 3436 return wtoken.appWindowToken; 3437 } 3438 3439 @Override 3440 public void addWindowToken(IBinder token, int type) { 3441 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3442 "addWindowToken()")) { 3443 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3444 } 3445 3446 synchronized(mWindowMap) { 3447 WindowToken wtoken = mTokenMap.get(token); 3448 if (wtoken != null) { 3449 Slog.w(TAG, "Attempted to add existing input method token: " + token); 3450 return; 3451 } 3452 wtoken = new WindowToken(this, token, type, true); 3453 Slog.w("BadTokenDebug", "addWindowToken: Adding token=" + token + " wtoken=" + wtoken); 3454 mTokenMap.put(token, wtoken); 3455 if (type == TYPE_WALLPAPER) { 3456 mWallpaperTokens.add(wtoken); 3457 } 3458 } 3459 } 3460 3461 @Override 3462 public void removeWindowToken(IBinder token) { 3463 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3464 "removeWindowToken()")) { 3465 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3466 } 3467 3468 final long origId = Binder.clearCallingIdentity(); 3469 synchronized(mWindowMap) { 3470 DisplayContent displayContent = null; 3471 WindowToken wtoken = mTokenMap.remove(token); 3472 Slog.w("BadTokenDebug", "removeWindowToken: Removing token=" + token + " removed=" + wtoken 3473 + " Callers=" + Debug.getCallers(3)); 3474 if (wtoken != null) { 3475 boolean delayed = false; 3476 if (!wtoken.hidden) { 3477 final int N = wtoken.windows.size(); 3478 boolean changed = false; 3479 3480 for (int i=0; i<N; i++) { 3481 WindowState win = wtoken.windows.get(i); 3482 displayContent = win.getDisplayContent(); 3483 3484 if (win.mWinAnimator.isAnimating()) { 3485 delayed = true; 3486 } 3487 3488 if (win.isVisibleNow()) { 3489 win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, 3490 false); 3491 //TODO (multidisplay): Magnification is supported only for the default 3492 if (mAccessibilityController != null && win.isDefaultDisplay()) { 3493 mAccessibilityController.onWindowTransitionLocked(win, 3494 WindowManagerPolicy.TRANSIT_EXIT); 3495 } 3496 changed = true; 3497 if (displayContent != null) { 3498 displayContent.layoutNeeded = true; 3499 } 3500 } 3501 } 3502 3503 wtoken.hidden = true; 3504 3505 if (changed) { 3506 performLayoutAndPlaceSurfacesLocked(); 3507 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, 3508 false /*updateInputWindows*/); 3509 } 3510 3511 if (delayed) { 3512 if (displayContent != null) { 3513 displayContent.mExitingTokens.add(wtoken); 3514 } 3515 } else if (wtoken.windowType == TYPE_WALLPAPER) { 3516 mWallpaperTokens.remove(wtoken); 3517 } 3518 } 3519 3520 mInputMonitor.updateInputWindowsLw(true /*force*/); 3521 } else { 3522 Slog.w(TAG, "Attempted to remove non-existing token: " + token); 3523 } 3524 } 3525 Binder.restoreCallingIdentity(origId); 3526 } 3527 3528 private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) { 3529 if (DEBUG_STACK) Slog.i(TAG, "createTask: taskId=" + taskId + " stackId=" + stackId 3530 + " atoken=" + atoken); 3531 final TaskStack stack = mStackIdToStack.get(stackId); 3532 if (stack == null) { 3533 throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId); 3534 } 3535 EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId); 3536 Task task = new Task(atoken, stack, userId); 3537 mTaskIdToTask.put(taskId, task); 3538 stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */); 3539 return task; 3540 } 3541 3542 @Override 3543 public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId, 3544 int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId, 3545 int configChanges, boolean voiceInteraction, boolean launchTaskBehind) { 3546 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3547 "addAppToken()")) { 3548 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3549 } 3550 3551 // Get the dispatching timeout here while we are not holding any locks so that it 3552 // can be cached by the AppWindowToken. The timeout value is used later by the 3553 // input dispatcher in code that does hold locks. If we did not cache the value 3554 // here we would run the chance of introducing a deadlock between the window manager 3555 // (which holds locks while updating the input dispatcher state) and the activity manager 3556 // (which holds locks while querying the application token). 3557 long inputDispatchingTimeoutNanos; 3558 try { 3559 inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L; 3560 } catch (RemoteException ex) { 3561 Slog.w(TAG, "Could not get dispatching timeout.", ex); 3562 inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 3563 } 3564 3565 synchronized(mWindowMap) { 3566 AppWindowToken atoken = findAppWindowToken(token.asBinder()); 3567 if (atoken != null) { 3568 Slog.w(TAG, "Attempted to add existing app token: " + token); 3569 return; 3570 } 3571 atoken = new AppWindowToken(this, token, voiceInteraction); 3572 atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos; 3573 atoken.groupId = taskId; 3574 atoken.appFullscreen = fullscreen; 3575 atoken.showWhenLocked = showWhenLocked; 3576 atoken.requestedOrientation = requestedOrientation; 3577 atoken.layoutConfigChanges = (configChanges & 3578 (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0; 3579 atoken.mLaunchTaskBehind = launchTaskBehind; 3580 if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken 3581 + " to stack=" + stackId + " task=" + taskId + " at " + addPos); 3582 3583 Task task = mTaskIdToTask.get(taskId); 3584 if (task == null) { 3585 createTask(taskId, stackId, userId, atoken); 3586 } else { 3587 task.addAppToken(addPos, atoken); 3588 } 3589 3590 Slog.w("BadTokenDebug", "addAppToken: Adding token=" + token.asBinder() + " atoken=" + atoken); 3591 mTokenMap.put(token.asBinder(), atoken); 3592 3593 // Application tokens start out hidden. 3594 atoken.hidden = true; 3595 atoken.hiddenRequested = true; 3596 3597 //dump(); 3598 } 3599 } 3600 3601 @Override 3602 public void setAppGroupId(IBinder token, int groupId) { 3603 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3604 "setAppGroupId()")) { 3605 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3606 } 3607 3608 synchronized(mWindowMap) { 3609 final AppWindowToken atoken = findAppWindowToken(token); 3610 if (atoken == null) { 3611 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token); 3612 return; 3613 } 3614 final Task oldTask = mTaskIdToTask.get(atoken.groupId); 3615 oldTask.removeAppToken(atoken); 3616 3617 atoken.groupId = groupId; 3618 Task newTask = mTaskIdToTask.get(groupId); 3619 if (newTask == null) { 3620 newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken); 3621 } else { 3622 newTask.mAppTokens.add(atoken); 3623 } 3624 } 3625 } 3626 3627 public int getOrientationFromWindowsLocked() { 3628 if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 3629 // If the display is frozen, some activities may be in the middle 3630 // of restarting, and thus have removed their old window. If the 3631 // window has the flag to hide the lock screen, then the lock screen 3632 // can re-appear and inflict its own orientation on us. Keep the 3633 // orientation stable until this all settles down. 3634 return mLastWindowForcedOrientation; 3635 } 3636 3637 // TODO(multidisplay): Change to the correct display. 3638 final WindowList windows = getDefaultWindowListLocked(); 3639 int pos = windows.size() - 1; 3640 while (pos >= 0) { 3641 WindowState win = windows.get(pos); 3642 pos--; 3643 if (win.mAppToken != null) { 3644 // We hit an application window. so the orientation will be determined by the 3645 // app window. No point in continuing further. 3646 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3647 } 3648 if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) { 3649 continue; 3650 } 3651 int req = win.mAttrs.screenOrientation; 3652 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) || 3653 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){ 3654 continue; 3655 } 3656 3657 if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req); 3658 return (mLastWindowForcedOrientation=req); 3659 } 3660 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3661 } 3662 3663 public int getOrientationFromAppTokensLocked() { 3664 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3665 boolean findingBehind = false; 3666 boolean lastFullscreen = false; 3667 // TODO: Multi window. 3668 DisplayContent displayContent = getDefaultDisplayContentLocked(); 3669 final ArrayList<Task> tasks = displayContent.getTasks(); 3670 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 3671 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 3672 final int firstToken = tokens.size() - 1; 3673 for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) { 3674 final AppWindowToken atoken = tokens.get(tokenNdx); 3675 3676 if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken); 3677 3678 // if we're about to tear down this window and not seek for 3679 // the behind activity, don't use it for orientation 3680 if (!findingBehind 3681 && (!atoken.hidden && atoken.hiddenRequested)) { 3682 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken 3683 + " -- going to hide"); 3684 continue; 3685 } 3686 3687 if (tokenNdx == firstToken) { 3688 // If we have hit a new Task, and the bottom 3689 // of the previous group didn't explicitly say to use 3690 // the orientation behind it, and the last app was 3691 // full screen, then we'll stick with the 3692 // user's orientation. 3693 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND 3694 && lastFullscreen) { 3695 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3696 + " -- end of group, return " + lastOrientation); 3697 return lastOrientation; 3698 } 3699 } 3700 3701 // We ignore any hidden applications on the top. 3702 if (atoken.hiddenRequested || atoken.willBeHidden) { 3703 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken 3704 + " -- hidden on top"); 3705 continue; 3706 } 3707 3708 if (tokenNdx == 0) { 3709 // Last token in this task. 3710 lastOrientation = atoken.requestedOrientation; 3711 } 3712 3713 int or = atoken.requestedOrientation; 3714 // If this application is fullscreen, and didn't explicitly say 3715 // to use the orientation behind it, then just take whatever 3716 // orientation it has and ignores whatever is under it. 3717 lastFullscreen = atoken.appFullscreen; 3718 if (lastFullscreen 3719 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { 3720 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3721 + " -- full screen, return " + or); 3722 return or; 3723 } 3724 // If this application has requested an explicit orientation, 3725 // then use it. 3726 if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 3727 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { 3728 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3729 + " -- explicitly set, return " + or); 3730 return or; 3731 } 3732 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND); 3733 } 3734 } 3735 if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation"); 3736 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3737 } 3738 3739 @Override 3740 public Configuration updateOrientationFromAppTokens( 3741 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3742 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3743 "updateOrientationFromAppTokens()")) { 3744 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3745 } 3746 3747 Configuration config = null; 3748 long ident = Binder.clearCallingIdentity(); 3749 3750 synchronized(mWindowMap) { 3751 config = updateOrientationFromAppTokensLocked(currentConfig, 3752 freezeThisOneIfNeeded); 3753 } 3754 3755 Binder.restoreCallingIdentity(ident); 3756 return config; 3757 } 3758 3759 private Configuration updateOrientationFromAppTokensLocked( 3760 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3761 Configuration config = null; 3762 3763 if (updateOrientationFromAppTokensLocked(false)) { 3764 if (freezeThisOneIfNeeded != null) { 3765 AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded); 3766 if (atoken != null) { 3767 startAppFreezingScreenLocked(atoken); 3768 } 3769 } 3770 config = computeNewConfigurationLocked(); 3771 3772 } else if (currentConfig != null) { 3773 // No obvious action we need to take, but if our current 3774 // state mismatches the activity manager's, update it, 3775 // disregarding font scale, which should remain set to 3776 // the value of the previous configuration. 3777 mTempConfiguration.setToDefaults(); 3778 mTempConfiguration.fontScale = currentConfig.fontScale; 3779 if (computeScreenConfigurationLocked(mTempConfiguration)) { 3780 if (currentConfig.diff(mTempConfiguration) != 0) { 3781 mWaitingForConfig = true; 3782 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 3783 displayContent.layoutNeeded = true; 3784 int anim[] = new int[2]; 3785 if (displayContent.isDimming()) { 3786 anim[0] = anim[1] = 0; 3787 } else { 3788 mPolicy.selectRotationAnimationLw(anim); 3789 } 3790 startFreezingDisplayLocked(false, anim[0], anim[1]); 3791 config = new Configuration(mTempConfiguration); 3792 } 3793 } 3794 } 3795 3796 return config; 3797 } 3798 3799 /* 3800 * Determine the new desired orientation of the display, returning 3801 * a non-null new Configuration if it has changed from the current 3802 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL 3803 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE 3804 * SCREEN. This will typically be done for you if you call 3805 * sendNewConfiguration(). 3806 * 3807 * The orientation is computed from non-application windows first. If none of 3808 * the non-application windows specify orientation, the orientation is computed from 3809 * application tokens. 3810 * @see android.view.IWindowManager#updateOrientationFromAppTokens( 3811 * android.os.IBinder) 3812 */ 3813 boolean updateOrientationFromAppTokensLocked(boolean inTransaction) { 3814 long ident = Binder.clearCallingIdentity(); 3815 try { 3816 int req = getOrientationFromWindowsLocked(); 3817 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) { 3818 req = getOrientationFromAppTokensLocked(); 3819 } 3820 3821 if (req != mForcedAppOrientation) { 3822 mForcedAppOrientation = req; 3823 //send a message to Policy indicating orientation change to take 3824 //action like disabling/enabling sensors etc., 3825 mPolicy.setCurrentOrientationLw(req); 3826 if (updateRotationUncheckedLocked(inTransaction)) { 3827 // changed 3828 return true; 3829 } 3830 } 3831 3832 return false; 3833 } finally { 3834 Binder.restoreCallingIdentity(ident); 3835 } 3836 } 3837 3838 @Override 3839 public void setNewConfiguration(Configuration config) { 3840 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3841 "setNewConfiguration()")) { 3842 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3843 } 3844 3845 synchronized(mWindowMap) { 3846 mCurConfiguration = new Configuration(config); 3847 if (mWaitingForConfig) { 3848 mWaitingForConfig = false; 3849 mLastFinishedFreezeSource = "new-config"; 3850 } 3851 performLayoutAndPlaceSurfacesLocked(); 3852 } 3853 } 3854 3855 @Override 3856 public void setAppOrientation(IApplicationToken token, int requestedOrientation) { 3857 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3858 "setAppOrientation()")) { 3859 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3860 } 3861 3862 synchronized(mWindowMap) { 3863 AppWindowToken atoken = findAppWindowToken(token.asBinder()); 3864 if (atoken == null) { 3865 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token); 3866 return; 3867 } 3868 3869 atoken.requestedOrientation = requestedOrientation; 3870 } 3871 } 3872 3873 @Override 3874 public int getAppOrientation(IApplicationToken token) { 3875 synchronized(mWindowMap) { 3876 AppWindowToken wtoken = findAppWindowToken(token.asBinder()); 3877 if (wtoken == null) { 3878 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3879 } 3880 3881 return wtoken.requestedOrientation; 3882 } 3883 } 3884 3885 /** Call while in a Surface transaction. */ 3886 void setFocusedStackLayer() { 3887 mFocusedStackLayer = 0; 3888 if (mFocusedApp != null) { 3889 final WindowList windows = mFocusedApp.allAppWindows; 3890 for (int i = windows.size() - 1; i >= 0; --i) { 3891 final WindowState win = windows.get(i); 3892 final int animLayer = win.mWinAnimator.mAnimLayer; 3893 if (win.mAttachedWindow == null && win.isVisibleLw() && 3894 animLayer > mFocusedStackLayer) { 3895 mFocusedStackLayer = animLayer + LAYER_OFFSET_FOCUSED_STACK; 3896 } 3897 } 3898 } 3899 if (DEBUG_LAYERS) Slog.v(TAG, "Setting FocusedStackFrame to layer=" + 3900 mFocusedStackLayer); 3901 mFocusedStackFrame.setLayer(mFocusedStackLayer); 3902 } 3903 3904 void setFocusedStackFrame() { 3905 final TaskStack stack; 3906 if (mFocusedApp != null) { 3907 Task task = mTaskIdToTask.get(mFocusedApp.groupId); 3908 stack = task.mStack; 3909 final DisplayContent displayContent = task.getDisplayContent(); 3910 if (displayContent != null) { 3911 displayContent.setTouchExcludeRegion(stack); 3912 } 3913 } else { 3914 stack = null; 3915 } 3916 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame"); 3917 SurfaceControl.openTransaction(); 3918 try { 3919 if (stack == null) { 3920 mFocusedStackFrame.setVisibility(false); 3921 } else { 3922 mFocusedStackFrame.setBounds(stack); 3923 final boolean multipleStacks = !stack.isFullscreen(); 3924 mFocusedStackFrame.setVisibility(multipleStacks); 3925 } 3926 } finally { 3927 SurfaceControl.closeTransaction(); 3928 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame"); 3929 } 3930 } 3931 3932 @Override 3933 public void setFocusedApp(IBinder token, boolean moveFocusNow) { 3934 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3935 "setFocusedApp()")) { 3936 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3937 } 3938 3939 synchronized(mWindowMap) { 3940 final AppWindowToken newFocus; 3941 if (token == null) { 3942 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp); 3943 newFocus = null; 3944 } else { 3945 newFocus = findAppWindowToken(token); 3946 if (newFocus == null) { 3947 Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token); 3948 } 3949 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus 3950 + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow); 3951 } 3952 3953 final boolean changed = mFocusedApp != newFocus; 3954 if (changed) { 3955 mFocusedApp = newFocus; 3956 mInputMonitor.setFocusedAppLw(newFocus); 3957 } 3958 3959 if (moveFocusNow && changed) { 3960 final long origId = Binder.clearCallingIdentity(); 3961 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 3962 Binder.restoreCallingIdentity(origId); 3963 } 3964 } 3965 } 3966 3967 @Override 3968 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) { 3969 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3970 "prepareAppTransition()")) { 3971 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3972 } 3973 3974 synchronized(mWindowMap) { 3975 if (DEBUG_APP_TRANSITIONS) Slog.v( 3976 TAG, "Prepare app transition: transit=" + transit 3977 + " " + mAppTransition 3978 + " alwaysKeepCurrent=" + alwaysKeepCurrent 3979 + " Callers=" + Debug.getCallers(3)); 3980 if (!mAppTransition.isTransitionSet() || mAppTransition.isTransitionNone()) { 3981 mAppTransition.setAppTransition(transit); 3982 } else if (!alwaysKeepCurrent) { 3983 if (transit == AppTransition.TRANSIT_TASK_OPEN 3984 && mAppTransition.isTransitionEqual( 3985 AppTransition.TRANSIT_TASK_CLOSE)) { 3986 // Opening a new task always supersedes a close for the anim. 3987 mAppTransition.setAppTransition(transit); 3988 } else if (transit == AppTransition.TRANSIT_ACTIVITY_OPEN 3989 && mAppTransition.isTransitionEqual( 3990 AppTransition.TRANSIT_ACTIVITY_CLOSE)) { 3991 // Opening a new activity always supersedes a close for the anim. 3992 mAppTransition.setAppTransition(transit); 3993 } 3994 } 3995 if (okToDisplay()) { 3996 mAppTransition.prepare(); 3997 mStartingIconInTransition = false; 3998 mSkipAppTransitionAnimation = false; 3999 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 4000 mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000); 4001 } 4002 } 4003 } 4004 4005 @Override 4006 public int getPendingAppTransition() { 4007 return mAppTransition.getAppTransition(); 4008 } 4009 4010 @Override 4011 public void overridePendingAppTransition(String packageName, 4012 int enterAnim, int exitAnim, IRemoteCallback startedCallback) { 4013 synchronized(mWindowMap) { 4014 mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim, 4015 startedCallback); 4016 } 4017 } 4018 4019 @Override 4020 public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, 4021 int startHeight) { 4022 synchronized(mWindowMap) { 4023 mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth, 4024 startHeight); 4025 } 4026 } 4027 4028 @Override 4029 public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, 4030 int startY, IRemoteCallback startedCallback, boolean scaleUp) { 4031 synchronized(mWindowMap) { 4032 mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY, 4033 startedCallback, scaleUp); 4034 } 4035 } 4036 4037 @Override 4038 public void executeAppTransition() { 4039 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4040 "executeAppTransition()")) { 4041 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4042 } 4043 4044 synchronized(mWindowMap) { 4045 if (DEBUG_APP_TRANSITIONS) Slog.w(TAG, "Execute app transition: " + mAppTransition, 4046 new RuntimeException("here").fillInStackTrace()); 4047 if (mAppTransition.isTransitionSet()) { 4048 mAppTransition.setReady(); 4049 final long origId = Binder.clearCallingIdentity(); 4050 try { 4051 performLayoutAndPlaceSurfacesLocked(); 4052 } finally { 4053 Binder.restoreCallingIdentity(origId); 4054 } 4055 } 4056 } 4057 } 4058 4059 @Override 4060 public void setAppStartingWindow(IBinder token, String pkg, 4061 int theme, CompatibilityInfo compatInfo, 4062 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, 4063 int windowFlags, IBinder transferFrom, boolean createIfNeeded) { 4064 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4065 "setAppStartingWindow()")) { 4066 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4067 } 4068 4069 synchronized(mWindowMap) { 4070 if (DEBUG_STARTING_WINDOW) Slog.v( 4071 TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg 4072 + " transferFrom=" + transferFrom); 4073 4074 AppWindowToken wtoken = findAppWindowToken(token); 4075 if (wtoken == null) { 4076 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token); 4077 return; 4078 } 4079 4080 // If the display is frozen, we won't do anything until the 4081 // actual window is displayed so there is no reason to put in 4082 // the starting window. 4083 if (!okToDisplay()) { 4084 return; 4085 } 4086 4087 if (wtoken.startingData != null) { 4088 return; 4089 } 4090 4091 if (transferFrom != null) { 4092 AppWindowToken ttoken = findAppWindowToken(transferFrom); 4093 if (ttoken != null) { 4094 WindowState startingWindow = ttoken.startingWindow; 4095 if (startingWindow != null) { 4096 if (mStartingIconInTransition) { 4097 // In this case, the starting icon has already 4098 // been displayed, so start letting windows get 4099 // shown immediately without any more transitions. 4100 mSkipAppTransitionAnimation = true; 4101 } 4102 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4103 "Moving existing starting " + startingWindow + " from " + ttoken 4104 + " to " + wtoken); 4105 final long origId = Binder.clearCallingIdentity(); 4106 4107 // Transfer the starting window over to the new 4108 // token. 4109 wtoken.startingData = ttoken.startingData; 4110 wtoken.startingView = ttoken.startingView; 4111 wtoken.startingDisplayed = ttoken.startingDisplayed; 4112 ttoken.startingDisplayed = false; 4113 wtoken.startingWindow = startingWindow; 4114 wtoken.reportedVisible = ttoken.reportedVisible; 4115 ttoken.startingData = null; 4116 ttoken.startingView = null; 4117 ttoken.startingWindow = null; 4118 ttoken.startingMoved = true; 4119 startingWindow.mToken = wtoken; 4120 startingWindow.mRootToken = wtoken; 4121 startingWindow.mAppToken = wtoken; 4122 startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator; 4123 4124 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) { 4125 Slog.v(TAG, "Removing starting window: " + startingWindow); 4126 } 4127 startingWindow.getWindowList().remove(startingWindow); 4128 mWindowsChanged = true; 4129 if (DEBUG_ADD_REMOVE) Slog.v(TAG, 4130 "Removing starting " + startingWindow + " from " + ttoken); 4131 ttoken.windows.remove(startingWindow); 4132 ttoken.allAppWindows.remove(startingWindow); 4133 addWindowToListInOrderLocked(startingWindow, true); 4134 4135 // Propagate other interesting state between the 4136 // tokens. If the old token is displayed, we should 4137 // immediately force the new one to be displayed. If 4138 // it is animating, we need to move that animation to 4139 // the new one. 4140 if (ttoken.allDrawn) { 4141 wtoken.allDrawn = true; 4142 wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn; 4143 } 4144 if (ttoken.firstWindowDrawn) { 4145 wtoken.firstWindowDrawn = true; 4146 } 4147 if (!ttoken.hidden) { 4148 wtoken.hidden = false; 4149 wtoken.hiddenRequested = false; 4150 wtoken.willBeHidden = false; 4151 } 4152 if (wtoken.clientHidden != ttoken.clientHidden) { 4153 wtoken.clientHidden = ttoken.clientHidden; 4154 wtoken.sendAppVisibilityToClients(); 4155 } 4156 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4157 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4158 if (tAppAnimator.animation != null) { 4159 wAppAnimator.animation = tAppAnimator.animation; 4160 wAppAnimator.animating = tAppAnimator.animating; 4161 wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment; 4162 tAppAnimator.animation = null; 4163 tAppAnimator.animLayerAdjustment = 0; 4164 wAppAnimator.updateLayers(); 4165 tAppAnimator.updateLayers(); 4166 } 4167 4168 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4169 true /*updateInputWindows*/); 4170 getDefaultDisplayContentLocked().layoutNeeded = true; 4171 performLayoutAndPlaceSurfacesLocked(); 4172 Binder.restoreCallingIdentity(origId); 4173 return; 4174 } else if (ttoken.startingData != null) { 4175 // The previous app was getting ready to show a 4176 // starting window, but hasn't yet done so. Steal it! 4177 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4178 "Moving pending starting from " + ttoken 4179 + " to " + wtoken); 4180 wtoken.startingData = ttoken.startingData; 4181 ttoken.startingData = null; 4182 ttoken.startingMoved = true; 4183 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4184 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4185 // want to process the message ASAP, before any other queued 4186 // messages. 4187 mH.sendMessageAtFrontOfQueue(m); 4188 return; 4189 } 4190 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4191 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4192 if (tAppAnimator.thumbnail != null) { 4193 // The old token is animating with a thumbnail, transfer 4194 // that to the new token. 4195 if (wAppAnimator.thumbnail != null) { 4196 wAppAnimator.thumbnail.destroy(); 4197 } 4198 wAppAnimator.thumbnail = tAppAnimator.thumbnail; 4199 wAppAnimator.thumbnailX = tAppAnimator.thumbnailX; 4200 wAppAnimator.thumbnailY = tAppAnimator.thumbnailY; 4201 wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer; 4202 wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation; 4203 tAppAnimator.thumbnail = null; 4204 } 4205 } 4206 } 4207 4208 // There is no existing starting window, and the caller doesn't 4209 // want us to create one, so that's it! 4210 if (!createIfNeeded) { 4211 return; 4212 } 4213 4214 // If this is a translucent window, then don't 4215 // show a starting window -- the current effect (a full-screen 4216 // opaque starting window that fades away to the real contents 4217 // when it is ready) does not work for this. 4218 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x" 4219 + Integer.toHexString(theme)); 4220 if (theme != 0) { 4221 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme, 4222 com.android.internal.R.styleable.Window, mCurrentUserId); 4223 if (ent == null) { 4224 // Whoops! App doesn't exist. Um. Okay. We'll just 4225 // pretend like we didn't see that. 4226 return; 4227 } 4228 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent=" 4229 + ent.array.getBoolean( 4230 com.android.internal.R.styleable.Window_windowIsTranslucent, false) 4231 + " Floating=" 4232 + ent.array.getBoolean( 4233 com.android.internal.R.styleable.Window_windowIsFloating, false) 4234 + " ShowWallpaper=" 4235 + ent.array.getBoolean( 4236 com.android.internal.R.styleable.Window_windowShowWallpaper, false)); 4237 if (ent.array.getBoolean( 4238 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) { 4239 return; 4240 } 4241 if (ent.array.getBoolean( 4242 com.android.internal.R.styleable.Window_windowIsFloating, false)) { 4243 return; 4244 } 4245 if (ent.array.getBoolean( 4246 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) { 4247 if (mWallpaperTarget == null) { 4248 // If this theme is requesting a wallpaper, and the wallpaper 4249 // is not curently visible, then this effectively serves as 4250 // an opaque window and our starting window transition animation 4251 // can still work. We just need to make sure the starting window 4252 // is also showing the wallpaper. 4253 windowFlags |= FLAG_SHOW_WALLPAPER; 4254 } else { 4255 return; 4256 } 4257 } 4258 } 4259 4260 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData"); 4261 mStartingIconInTransition = true; 4262 wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel, 4263 labelRes, icon, logo, windowFlags); 4264 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4265 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4266 // want to process the message ASAP, before any other queued 4267 // messages. 4268 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING"); 4269 mH.sendMessageAtFrontOfQueue(m); 4270 } 4271 } 4272 4273 public void removeAppStartingWindow(IBinder token) { 4274 synchronized (mWindowMap) { 4275 AppWindowToken wtoken = mTokenMap.get(token).appWindowToken; 4276 if (wtoken.startingWindow != null) { 4277 scheduleRemoveStartingWindow(wtoken); 4278 } 4279 } 4280 } 4281 4282 @Override 4283 public void setAppWillBeHidden(IBinder token) { 4284 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4285 "setAppWillBeHidden()")) { 4286 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4287 } 4288 4289 AppWindowToken wtoken; 4290 4291 synchronized(mWindowMap) { 4292 wtoken = findAppWindowToken(token); 4293 if (wtoken == null) { 4294 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token); 4295 return; 4296 } 4297 wtoken.willBeHidden = true; 4298 } 4299 } 4300 4301 public void setAppFullscreen(IBinder token, boolean toOpaque) { 4302 AppWindowToken atoken = findAppWindowToken(token); 4303 if (atoken != null) { 4304 atoken.appFullscreen = toOpaque; 4305 // When making translucent, wait until windows below have been drawn. 4306 if (toOpaque) { 4307 // Making opaque so do it now. 4308 setWindowOpaque(token, true); 4309 } 4310 requestTraversal(); 4311 } 4312 } 4313 4314 public void setWindowOpaque(IBinder token, boolean isOpaque) { 4315 AppWindowToken wtoken = findAppWindowToken(token); 4316 if (wtoken != null) { 4317 WindowState win = wtoken.findMainWindow(); 4318 if (win != null) { 4319 win.mWinAnimator.setOpaque(isOpaque); 4320 } 4321 } 4322 } 4323 4324 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp, 4325 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) { 4326 boolean delayed = false; 4327 4328 if (wtoken.clientHidden == visible) { 4329 wtoken.clientHidden = !visible; 4330 wtoken.sendAppVisibilityToClients(); 4331 } 4332 4333 wtoken.willBeHidden = false; 4334 if (wtoken.hidden == visible) { 4335 boolean changed = false; 4336 if (DEBUG_APP_TRANSITIONS) Slog.v( 4337 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden 4338 + " performLayout=" + performLayout); 4339 4340 boolean runningAppAnimation = false; 4341 4342 if (transit != AppTransition.TRANSIT_UNSET) { 4343 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { 4344 wtoken.mAppAnimator.animation = null; 4345 } 4346 if (applyAnimationLocked(wtoken, lp, transit, visible, isVoiceInteraction)) { 4347 delayed = runningAppAnimation = true; 4348 } 4349 WindowState window = wtoken.findMainWindow(); 4350 //TODO (multidisplay): Magnification is supported only for the default display. 4351 if (window != null && mAccessibilityController != null 4352 && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 4353 mAccessibilityController.onAppWindowTransitionLocked(window, transit); 4354 } 4355 changed = true; 4356 } 4357 4358 final int N = wtoken.allAppWindows.size(); 4359 for (int i=0; i<N; i++) { 4360 WindowState win = wtoken.allAppWindows.get(i); 4361 if (win == wtoken.startingWindow) { 4362 continue; 4363 } 4364 4365 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible()); 4366 //win.dump(" "); 4367 if (visible) { 4368 if (!win.isVisibleNow()) { 4369 if (!runningAppAnimation) { 4370 win.mWinAnimator.applyAnimationLocked( 4371 WindowManagerPolicy.TRANSIT_ENTER, true); 4372 //TODO (multidisplay): Magnification is supported only for the default 4373 if (mAccessibilityController != null 4374 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4375 mAccessibilityController.onWindowTransitionLocked(win, 4376 WindowManagerPolicy.TRANSIT_ENTER); 4377 } 4378 } 4379 changed = true; 4380 final DisplayContent displayContent = win.getDisplayContent(); 4381 if (displayContent != null) { 4382 displayContent.layoutNeeded = true; 4383 } 4384 } 4385 } else if (win.isVisibleNow()) { 4386 if (!runningAppAnimation) { 4387 win.mWinAnimator.applyAnimationLocked( 4388 WindowManagerPolicy.TRANSIT_EXIT, false); 4389 //TODO (multidisplay): Magnification is supported only for the default 4390 if (mAccessibilityController != null 4391 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4392 mAccessibilityController.onWindowTransitionLocked(win, 4393 WindowManagerPolicy.TRANSIT_EXIT); 4394 } 4395 } 4396 changed = true; 4397 final DisplayContent displayContent = win.getDisplayContent(); 4398 if (displayContent != null) { 4399 displayContent.layoutNeeded = true; 4400 } 4401 } 4402 } 4403 4404 wtoken.hidden = wtoken.hiddenRequested = !visible; 4405 if (!visible) { 4406 unsetAppFreezingScreenLocked(wtoken, true, true); 4407 } else { 4408 // If we are being set visible, and the starting window is 4409 // not yet displayed, then make sure it doesn't get displayed. 4410 WindowState swin = wtoken.startingWindow; 4411 if (swin != null && !swin.isDrawnLw()) { 4412 swin.mPolicyVisibility = false; 4413 swin.mPolicyVisibilityAfterAnim = false; 4414 } 4415 } 4416 4417 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken 4418 + ": hidden=" + wtoken.hidden + " hiddenRequested=" 4419 + wtoken.hiddenRequested); 4420 4421 if (changed) { 4422 mInputMonitor.setUpdateInputWindowsNeededLw(); 4423 if (performLayout) { 4424 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4425 false /*updateInputWindows*/); 4426 performLayoutAndPlaceSurfacesLocked(); 4427 } 4428 mInputMonitor.updateInputWindowsLw(false /*force*/); 4429 } 4430 } 4431 4432 if (wtoken.mAppAnimator.animation != null) { 4433 delayed = true; 4434 } 4435 4436 for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) { 4437 if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) { 4438 delayed = true; 4439 } 4440 } 4441 4442 return delayed; 4443 } 4444 4445 @Override 4446 public void setAppVisibility(IBinder token, boolean visible) { 4447 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4448 "setAppVisibility()")) { 4449 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4450 } 4451 4452 AppWindowToken wtoken; 4453 4454 synchronized(mWindowMap) { 4455 wtoken = findAppWindowToken(token); 4456 if (wtoken == null) { 4457 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token); 4458 return; 4459 } 4460 4461 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG, "setAppVisibility(" + 4462 token + ", visible=" + visible + "): " + mAppTransition + 4463 " hidden=" + wtoken.hidden + " hiddenRequested=" + 4464 wtoken.hiddenRequested, HIDE_STACK_CRAWLS ? 4465 null : new RuntimeException("here").fillInStackTrace()); 4466 4467 // If we are preparing an app transition, then delay changing 4468 // the visibility of this token until we execute that transition. 4469 if (okToDisplay() && mAppTransition.isTransitionSet()) { 4470 wtoken.hiddenRequested = !visible; 4471 4472 if (!wtoken.startingDisplayed) { 4473 if (DEBUG_APP_TRANSITIONS) Slog.v( 4474 TAG, "Setting dummy animation on: " + wtoken); 4475 wtoken.mAppAnimator.setDummyAnimation(); 4476 } 4477 mOpeningApps.remove(wtoken); 4478 mClosingApps.remove(wtoken); 4479 wtoken.waitingToShow = wtoken.waitingToHide = false; 4480 wtoken.inPendingTransaction = true; 4481 if (visible) { 4482 mOpeningApps.add(wtoken); 4483 wtoken.startingMoved = false; 4484 wtoken.mEnteringAnimation = true; 4485 4486 // If the token is currently hidden (should be the 4487 // common case), then we need to set up to wait for 4488 // its windows to be ready. 4489 if (wtoken.hidden) { 4490 wtoken.allDrawn = false; 4491 wtoken.deferClearAllDrawn = false; 4492 wtoken.waitingToShow = true; 4493 4494 if (wtoken.clientHidden) { 4495 // In the case where we are making an app visible 4496 // but holding off for a transition, we still need 4497 // to tell the client to make its windows visible so 4498 // they get drawn. Otherwise, we will wait on 4499 // performing the transition until all windows have 4500 // been drawn, they never will be, and we are sad. 4501 wtoken.clientHidden = false; 4502 wtoken.sendAppVisibilityToClients(); 4503 } 4504 } 4505 } else { 4506 mClosingApps.add(wtoken); 4507 wtoken.mEnteringAnimation = false; 4508 4509 // If the token is currently visible (should be the 4510 // common case), then set up to wait for it to be hidden. 4511 if (!wtoken.hidden) { 4512 wtoken.waitingToHide = true; 4513 } 4514 } 4515 if (mAppTransition.getAppTransition() == AppTransition.TRANSIT_TASK_OPEN_BEHIND) { 4516 // We're launchingBehind, add the launching activity to mOpeningApps. 4517 final WindowState win = 4518 findFocusedWindowLocked(getDefaultDisplayContentLocked()); 4519 if (win != null) { 4520 final AppWindowToken focusedToken = win.mAppToken; 4521 if (focusedToken != null) { 4522 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "TRANSIT_TASK_OPEN_BEHIND, " + 4523 " adding " + focusedToken + " to mOpeningApps"); 4524 // Force animation to be loaded. 4525 focusedToken.hidden = true; 4526 mOpeningApps.add(focusedToken); 4527 } 4528 } 4529 } 4530 return; 4531 } 4532 4533 final long origId = Binder.clearCallingIdentity(); 4534 setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET, 4535 true, wtoken.voiceInteraction); 4536 wtoken.updateReportedVisibilityLocked(); 4537 Binder.restoreCallingIdentity(origId); 4538 } 4539 } 4540 4541 void unsetAppFreezingScreenLocked(AppWindowToken wtoken, 4542 boolean unfreezeSurfaceNow, boolean force) { 4543 if (wtoken.mAppAnimator.freezingScreen) { 4544 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken 4545 + " force=" + force); 4546 final int N = wtoken.allAppWindows.size(); 4547 boolean unfrozeWindows = false; 4548 for (int i=0; i<N; i++) { 4549 WindowState w = wtoken.allAppWindows.get(i); 4550 if (w.mAppFreezing) { 4551 w.mAppFreezing = false; 4552 if (w.mHasSurface && !w.mOrientationChanging) { 4553 if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w); 4554 w.mOrientationChanging = true; 4555 mInnerFields.mOrientationChangeComplete = false; 4556 } 4557 w.mLastFreezeDuration = 0; 4558 unfrozeWindows = true; 4559 final DisplayContent displayContent = w.getDisplayContent(); 4560 if (displayContent != null) { 4561 displayContent.layoutNeeded = true; 4562 } 4563 } 4564 } 4565 if (force || unfrozeWindows) { 4566 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken); 4567 wtoken.mAppAnimator.freezingScreen = false; 4568 wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime() 4569 - mDisplayFreezeTime); 4570 mAppsFreezingScreen--; 4571 mLastFinishedFreezeSource = wtoken; 4572 } 4573 if (unfreezeSurfaceNow) { 4574 if (unfrozeWindows) { 4575 performLayoutAndPlaceSurfacesLocked(); 4576 } 4577 stopFreezingDisplayLocked(); 4578 } 4579 } 4580 } 4581 4582 private void startAppFreezingScreenLocked(AppWindowToken wtoken) { 4583 if (DEBUG_ORIENTATION) { 4584 RuntimeException e = null; 4585 if (!HIDE_STACK_CRAWLS) { 4586 e = new RuntimeException(); 4587 e.fillInStackTrace(); 4588 } 4589 Slog.i(TAG, "Set freezing of " + wtoken.appToken 4590 + ": hidden=" + wtoken.hidden + " freezing=" 4591 + wtoken.mAppAnimator.freezingScreen, e); 4592 } 4593 if (!wtoken.hiddenRequested) { 4594 if (!wtoken.mAppAnimator.freezingScreen) { 4595 wtoken.mAppAnimator.freezingScreen = true; 4596 wtoken.mAppAnimator.lastFreezeDuration = 0; 4597 mAppsFreezingScreen++; 4598 if (mAppsFreezingScreen == 1) { 4599 startFreezingDisplayLocked(false, 0, 0); 4600 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 4601 mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000); 4602 } 4603 } 4604 final int N = wtoken.allAppWindows.size(); 4605 for (int i=0; i<N; i++) { 4606 WindowState w = wtoken.allAppWindows.get(i); 4607 w.mAppFreezing = true; 4608 } 4609 } 4610 } 4611 4612 @Override 4613 public void startAppFreezingScreen(IBinder token, int configChanges) { 4614 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4615 "setAppFreezingScreen()")) { 4616 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4617 } 4618 4619 synchronized(mWindowMap) { 4620 if (configChanges == 0 && okToDisplay()) { 4621 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token); 4622 return; 4623 } 4624 4625 AppWindowToken wtoken = findAppWindowToken(token); 4626 if (wtoken == null || wtoken.appToken == null) { 4627 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken); 4628 return; 4629 } 4630 final long origId = Binder.clearCallingIdentity(); 4631 startAppFreezingScreenLocked(wtoken); 4632 Binder.restoreCallingIdentity(origId); 4633 } 4634 } 4635 4636 @Override 4637 public void stopAppFreezingScreen(IBinder token, boolean force) { 4638 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4639 "setAppFreezingScreen()")) { 4640 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4641 } 4642 4643 synchronized(mWindowMap) { 4644 AppWindowToken wtoken = findAppWindowToken(token); 4645 if (wtoken == null || wtoken.appToken == null) { 4646 return; 4647 } 4648 final long origId = Binder.clearCallingIdentity(); 4649 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token 4650 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen); 4651 unsetAppFreezingScreenLocked(wtoken, true, force); 4652 Binder.restoreCallingIdentity(origId); 4653 } 4654 } 4655 4656 void removeAppFromTaskLocked(AppWindowToken wtoken) { 4657 wtoken.removeAllWindows(); 4658 4659 final Task task = mTaskIdToTask.get(wtoken.groupId); 4660 if (task != null) { 4661 if (!task.removeAppToken(wtoken)) { 4662 Slog.e(TAG, "removeAppFromTaskLocked: token=" + wtoken + " not found."); 4663 } 4664 } 4665 } 4666 4667 @Override 4668 public void removeAppToken(IBinder token) { 4669 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4670 "removeAppToken()")) { 4671 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4672 } 4673 4674 AppWindowToken wtoken = null; 4675 AppWindowToken startingToken = null; 4676 boolean delayed = false; 4677 4678 final long origId = Binder.clearCallingIdentity(); 4679 synchronized(mWindowMap) { 4680 WindowToken basewtoken = mTokenMap.remove(token); 4681 Slog.w("BadTokenDebug", "removeAppToke: Removing token=" + token + " removed=" + basewtoken); 4682 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) { 4683 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken); 4684 delayed = setTokenVisibilityLocked(wtoken, null, false, 4685 AppTransition.TRANSIT_UNSET, true, wtoken.voiceInteraction); 4686 wtoken.inPendingTransaction = false; 4687 mOpeningApps.remove(wtoken); 4688 wtoken.waitingToShow = false; 4689 if (mClosingApps.contains(wtoken)) { 4690 delayed = true; 4691 } else if (mAppTransition.isTransitionSet()) { 4692 mClosingApps.add(wtoken); 4693 wtoken.waitingToHide = true; 4694 delayed = true; 4695 } 4696 if (DEBUG_APP_TRANSITIONS) Slog.v( 4697 TAG, "Removing app " + wtoken + " delayed=" + delayed 4698 + " animation=" + wtoken.mAppAnimator.animation 4699 + " animating=" + wtoken.mAppAnimator.animating); 4700 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: " 4701 + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4)); 4702 final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack; 4703 if (delayed) { 4704 // set the token aside because it has an active animation to be finished 4705 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4706 "removeAppToken make exiting: " + wtoken); 4707 stack.mExitingAppTokens.add(wtoken); 4708 wtoken.mDeferRemoval = true; 4709 } else { 4710 // Make sure there is no animation running on this token, 4711 // so any windows associated with it will be removed as 4712 // soon as their animations are complete 4713 wtoken.mAppAnimator.clearAnimation(); 4714 wtoken.mAppAnimator.animating = false; 4715 removeAppFromTaskLocked(wtoken); 4716 } 4717 4718 wtoken.removed = true; 4719 if (wtoken.startingData != null) { 4720 startingToken = wtoken; 4721 } 4722 unsetAppFreezingScreenLocked(wtoken, true, true); 4723 if (mFocusedApp == wtoken) { 4724 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Removing focused app token:" + wtoken); 4725 mFocusedApp = null; 4726 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 4727 mInputMonitor.setFocusedAppLw(null); 4728 } 4729 } else { 4730 Slog.w(TAG, "Attempted to remove non-existing app token: " + token); 4731 } 4732 4733 if (!delayed && wtoken != null) { 4734 wtoken.updateReportedVisibilityLocked(); 4735 } 4736 } 4737 Binder.restoreCallingIdentity(origId); 4738 4739 // Will only remove if startingToken non null. 4740 scheduleRemoveStartingWindow(startingToken); 4741 } 4742 4743 void scheduleRemoveStartingWindow(AppWindowToken wtoken) { 4744 if (wtoken != null && wtoken.startingWindow != null) { 4745 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) + 4746 ": Schedule remove starting " + wtoken + (wtoken != null ? 4747 " startingWindow=" + wtoken.startingWindow : "")); 4748 Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken); 4749 mH.sendMessage(m); 4750 } 4751 } 4752 4753 private boolean tmpRemoveAppWindowsLocked(WindowToken token) { 4754 WindowList windows = token.windows; 4755 final int NW = windows.size(); 4756 if (NW > 0) { 4757 mWindowsChanged = true; 4758 } 4759 for (int i = 0; i < NW; i++) { 4760 WindowState win = windows.get(i); 4761 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win); 4762 win.getWindowList().remove(win); 4763 int j = win.mChildWindows.size(); 4764 while (j > 0) { 4765 j--; 4766 WindowState cwin = win.mChildWindows.get(j); 4767 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 4768 "Tmp removing child window " + cwin); 4769 cwin.getWindowList().remove(cwin); 4770 } 4771 } 4772 return NW > 0; 4773 } 4774 4775 void dumpAppTokensLocked() { 4776 final int numStacks = mStackIdToStack.size(); 4777 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 4778 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 4779 Slog.v(TAG, " Stack #" + stack.mStackId + " tasks from bottom to top:"); 4780 final ArrayList<Task> tasks = stack.getTasks(); 4781 final int numTasks = tasks.size(); 4782 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4783 final Task task = tasks.get(taskNdx); 4784 Slog.v(TAG, " Task #" + task.taskId + " activities from bottom to top:"); 4785 AppTokenList tokens = task.mAppTokens; 4786 final int numTokens = tokens.size(); 4787 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 4788 Slog.v(TAG, " activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token); 4789 } 4790 } 4791 } 4792 } 4793 4794 void dumpWindowsLocked() { 4795 final int numDisplays = mDisplayContents.size(); 4796 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 4797 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 4798 Slog.v(TAG, " Display #" + displayContent.getDisplayId()); 4799 final WindowList windows = displayContent.getWindowList(); 4800 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 4801 Slog.v(TAG, " #" + winNdx + ": " + windows.get(winNdx)); 4802 } 4803 } 4804 } 4805 4806 private int findAppWindowInsertionPointLocked(AppWindowToken target) { 4807 final int taskId = target.groupId; 4808 Task targetTask = mTaskIdToTask.get(taskId); 4809 if (targetTask == null) { 4810 Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId=" 4811 + taskId); 4812 return 0; 4813 } 4814 DisplayContent displayContent = targetTask.getDisplayContent(); 4815 if (displayContent == null) { 4816 Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target); 4817 return 0; 4818 } 4819 final WindowList windows = displayContent.getWindowList(); 4820 final int NW = windows.size(); 4821 4822 boolean found = false; 4823 final ArrayList<Task> tasks = displayContent.getTasks(); 4824 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 4825 final Task task = tasks.get(taskNdx); 4826 if (!found && task.taskId != taskId) { 4827 continue; 4828 } 4829 AppTokenList tokens = task.mAppTokens; 4830 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 4831 final AppWindowToken wtoken = tokens.get(tokenNdx); 4832 if (!found && wtoken == target) { 4833 found = true; 4834 } 4835 if (found) { 4836 // Find the first app token below the new position that has 4837 // a window displayed. 4838 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token); 4839 if (wtoken.sendingToBottom) { 4840 if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom"); 4841 continue; 4842 } 4843 for (int i = wtoken.windows.size() - 1; i >= 0; --i) { 4844 WindowState win = wtoken.windows.get(i); 4845 for (int j = win.mChildWindows.size() - 1; j >= 0; --j) { 4846 WindowState cwin = win.mChildWindows.get(j); 4847 if (cwin.mSubLayer >= 0) { 4848 for (int pos = NW - 1; pos >= 0; pos--) { 4849 if (windows.get(pos) == cwin) { 4850 if (DEBUG_REORDER) Slog.v(TAG, 4851 "Found child win @" + (pos + 1)); 4852 return pos + 1; 4853 } 4854 } 4855 } 4856 } 4857 for (int pos = NW - 1; pos >= 0; pos--) { 4858 if (windows.get(pos) == win) { 4859 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1)); 4860 return pos + 1; 4861 } 4862 } 4863 } 4864 } 4865 } 4866 } 4867 // Never put an app window underneath wallpaper. 4868 for (int pos = NW - 1; pos >= 0; pos--) { 4869 if (windows.get(pos).mIsWallpaper) { 4870 if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos); 4871 return pos + 1; 4872 } 4873 } 4874 return 0; 4875 } 4876 4877 private final int reAddWindowLocked(int index, WindowState win) { 4878 final WindowList windows = win.getWindowList(); 4879 final int NCW = win.mChildWindows.size(); 4880 boolean added = false; 4881 for (int j=0; j<NCW; j++) { 4882 WindowState cwin = win.mChildWindows.get(j); 4883 if (!added && cwin.mSubLayer >= 0) { 4884 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at " 4885 + index + ": " + cwin); 4886 win.mRebuilding = false; 4887 windows.add(index, win); 4888 index++; 4889 added = true; 4890 } 4891 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4892 + index + ": " + cwin); 4893 cwin.mRebuilding = false; 4894 windows.add(index, cwin); 4895 index++; 4896 } 4897 if (!added) { 4898 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4899 + index + ": " + win); 4900 win.mRebuilding = false; 4901 windows.add(index, win); 4902 index++; 4903 } 4904 mWindowsChanged = true; 4905 return index; 4906 } 4907 4908 private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index, 4909 WindowToken token) { 4910 final int NW = token.windows.size(); 4911 for (int i=0; i<NW; i++) { 4912 final WindowState win = token.windows.get(i); 4913 final DisplayContent winDisplayContent = win.getDisplayContent(); 4914 if (winDisplayContent == displayContent || winDisplayContent == null) { 4915 win.mDisplayContent = displayContent; 4916 index = reAddWindowLocked(index, win); 4917 } 4918 } 4919 return index; 4920 } 4921 4922 void tmpRemoveTaskWindowsLocked(Task task) { 4923 AppTokenList tokens = task.mAppTokens; 4924 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 4925 tmpRemoveAppWindowsLocked(tokens.get(tokenNdx)); 4926 } 4927 } 4928 4929 void moveStackWindowsLocked(DisplayContent displayContent) { 4930 // First remove all of the windows from the list. 4931 final ArrayList<Task> tasks = displayContent.getTasks(); 4932 final int numTasks = tasks.size(); 4933 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4934 tmpRemoveTaskWindowsLocked(tasks.get(taskNdx)); 4935 } 4936 4937 // And now add them back at the correct place. 4938 // Where to start adding? 4939 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4940 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 4941 final int numTokens = tokens.size(); 4942 if (numTokens == 0) { 4943 continue; 4944 } 4945 int pos = findAppWindowInsertionPointLocked(tokens.get(0)); 4946 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 4947 final AppWindowToken wtoken = tokens.get(tokenNdx); 4948 if (wtoken != null) { 4949 final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken); 4950 if (newPos != pos) { 4951 displayContent.layoutNeeded = true; 4952 } 4953 pos = newPos; 4954 } 4955 } 4956 } 4957 4958 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4959 false /*updateInputWindows*/)) { 4960 assignLayersLocked(displayContent.getWindowList()); 4961 } 4962 4963 mInputMonitor.setUpdateInputWindowsNeededLw(); 4964 performLayoutAndPlaceSurfacesLocked(); 4965 mInputMonitor.updateInputWindowsLw(false /*force*/); 4966 4967 //dump(); 4968 } 4969 4970 public void moveTaskToTop(int taskId) { 4971 final long origId = Binder.clearCallingIdentity(); 4972 try { 4973 synchronized(mWindowMap) { 4974 Task task = mTaskIdToTask.get(taskId); 4975 if (task == null) { 4976 // Normal behavior, addAppToken will be called next and task will be created. 4977 return; 4978 } 4979 final TaskStack stack = task.mStack; 4980 final DisplayContent displayContent = task.getDisplayContent(); 4981 displayContent.moveStack(stack, true); 4982 if (displayContent.isDefaultDisplay) { 4983 final TaskStack homeStack = displayContent.getHomeStack(); 4984 if (homeStack != stack) { 4985 // When a non-home stack moves to the top, the home stack moves to the 4986 // bottom. 4987 displayContent.moveStack(homeStack, false); 4988 } 4989 } 4990 stack.moveTaskToTop(task); 4991 } 4992 } finally { 4993 Binder.restoreCallingIdentity(origId); 4994 } 4995 } 4996 4997 public void moveTaskToBottom(int taskId) { 4998 final long origId = Binder.clearCallingIdentity(); 4999 try { 5000 synchronized(mWindowMap) { 5001 Task task = mTaskIdToTask.get(taskId); 5002 if (task == null) { 5003 Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId 5004 + " not found in mTaskIdToTask"); 5005 return; 5006 } 5007 final TaskStack stack = task.mStack; 5008 stack.moveTaskToBottom(task); 5009 moveStackWindowsLocked(stack.getDisplayContent()); 5010 } 5011 } finally { 5012 Binder.restoreCallingIdentity(origId); 5013 } 5014 } 5015 5016 /** 5017 * Create a new TaskStack and place it on a DisplayContent. 5018 * @param stackId The unique identifier of the new stack. 5019 * @param displayId The unique identifier of the DisplayContent. 5020 */ 5021 public void attachStack(int stackId, int displayId) { 5022 final long origId = Binder.clearCallingIdentity(); 5023 try { 5024 synchronized (mWindowMap) { 5025 final DisplayContent displayContent = mDisplayContents.get(displayId); 5026 if (displayContent != null) { 5027 TaskStack stack = mStackIdToStack.get(stackId); 5028 if (stack == null) { 5029 if (DEBUG_STACK) Slog.d(TAG, "attachStack: stackId=" + stackId); 5030 stack = new TaskStack(this, stackId); 5031 mStackIdToStack.put(stackId, stack); 5032 } 5033 stack.attachDisplayContent(displayContent); 5034 displayContent.attachStack(stack); 5035 moveStackWindowsLocked(displayContent); 5036 final WindowList windows = displayContent.getWindowList(); 5037 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 5038 windows.get(winNdx).reportResized(); 5039 } 5040 } 5041 } 5042 } finally { 5043 Binder.restoreCallingIdentity(origId); 5044 } 5045 } 5046 5047 void detachStackLocked(DisplayContent displayContent, TaskStack stack) { 5048 displayContent.detachStack(stack); 5049 stack.detachDisplay(); 5050 } 5051 5052 public void detachStack(int stackId) { 5053 synchronized (mWindowMap) { 5054 TaskStack stack = mStackIdToStack.get(stackId); 5055 if (stack != null) { 5056 final DisplayContent displayContent = stack.getDisplayContent(); 5057 if (displayContent != null) { 5058 if (stack.isAnimating()) { 5059 stack.mDeferDetach = true; 5060 return; 5061 } 5062 detachStackLocked(displayContent, stack); 5063 } 5064 } 5065 } 5066 } 5067 5068 public void removeStack(int stackId) { 5069 mStackIdToStack.remove(stackId); 5070 } 5071 5072 void removeTaskLocked(Task task) { 5073 final int taskId = task.taskId; 5074 final TaskStack stack = task.mStack; 5075 if (stack.isAnimating()) { 5076 if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId); 5077 task.mDeferRemoval = true; 5078 return; 5079 } 5080 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId); 5081 EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask"); 5082 task.mDeferRemoval = false; 5083 task.mStack.removeTask(task); 5084 mTaskIdToTask.delete(task.taskId); 5085 } 5086 5087 public void removeTask(int taskId) { 5088 synchronized (mWindowMap) { 5089 Task task = mTaskIdToTask.get(taskId); 5090 if (task == null) { 5091 if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId); 5092 return; 5093 } 5094 removeTaskLocked(task); 5095 } 5096 } 5097 5098 public void addTask(int taskId, int stackId, boolean toTop) { 5099 synchronized (mWindowMap) { 5100 if (DEBUG_STACK) Slog.i(TAG, "addTask: adding taskId=" + taskId 5101 + " to " + (toTop ? "top" : "bottom")); 5102 Task task = mTaskIdToTask.get(taskId); 5103 if (task == null) { 5104 return; 5105 } 5106 TaskStack stack = mStackIdToStack.get(stackId); 5107 stack.addTask(task, toTop); 5108 final DisplayContent displayContent = stack.getDisplayContent(); 5109 displayContent.layoutNeeded = true; 5110 performLayoutAndPlaceSurfacesLocked(); 5111 } 5112 } 5113 5114 public void resizeStack(int stackId, Rect bounds) { 5115 synchronized (mWindowMap) { 5116 final TaskStack stack = mStackIdToStack.get(stackId); 5117 if (stack == null) { 5118 throw new IllegalArgumentException("resizeStack: stackId " + stackId 5119 + " not found."); 5120 } 5121 if (stack.setBounds(bounds)) { 5122 stack.resizeWindows(); 5123 stack.getDisplayContent().layoutNeeded = true; 5124 performLayoutAndPlaceSurfacesLocked(); 5125 } 5126 } 5127 } 5128 5129 public void getStackBounds(int stackId, Rect bounds) { 5130 final TaskStack stack = mStackIdToStack.get(stackId); 5131 if (stack != null) { 5132 stack.getBounds(bounds); 5133 return; 5134 } 5135 bounds.setEmpty(); 5136 } 5137 5138 // ------------------------------------------------------------- 5139 // Misc IWindowSession methods 5140 // ------------------------------------------------------------- 5141 5142 @Override 5143 public void startFreezingScreen(int exitAnim, int enterAnim) { 5144 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5145 "startFreezingScreen()")) { 5146 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5147 } 5148 5149 synchronized(mWindowMap) { 5150 if (!mClientFreezingScreen) { 5151 mClientFreezingScreen = true; 5152 final long origId = Binder.clearCallingIdentity(); 5153 try { 5154 startFreezingDisplayLocked(false, exitAnim, enterAnim); 5155 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 5156 mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000); 5157 } finally { 5158 Binder.restoreCallingIdentity(origId); 5159 } 5160 } 5161 } 5162 } 5163 5164 @Override 5165 public void stopFreezingScreen() { 5166 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5167 "stopFreezingScreen()")) { 5168 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5169 } 5170 5171 synchronized(mWindowMap) { 5172 if (mClientFreezingScreen) { 5173 mClientFreezingScreen = false; 5174 mLastFinishedFreezeSource = "client"; 5175 final long origId = Binder.clearCallingIdentity(); 5176 try { 5177 stopFreezingDisplayLocked(); 5178 } finally { 5179 Binder.restoreCallingIdentity(origId); 5180 } 5181 } 5182 } 5183 } 5184 5185 @Override 5186 public void disableKeyguard(IBinder token, String tag) { 5187 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5188 != PackageManager.PERMISSION_GRANTED) { 5189 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5190 } 5191 5192 if (token == null) { 5193 throw new IllegalArgumentException("token == null"); 5194 } 5195 5196 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5197 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag))); 5198 } 5199 5200 @Override 5201 public void reenableKeyguard(IBinder token) { 5202 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5203 != PackageManager.PERMISSION_GRANTED) { 5204 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5205 } 5206 5207 if (token == null) { 5208 throw new IllegalArgumentException("token == null"); 5209 } 5210 5211 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5212 KeyguardDisableHandler.KEYGUARD_REENABLE, token)); 5213 } 5214 5215 /** 5216 * @see android.app.KeyguardManager#exitKeyguardSecurely 5217 */ 5218 @Override 5219 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) { 5220 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5221 != PackageManager.PERMISSION_GRANTED) { 5222 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5223 } 5224 5225 if (callback == null) { 5226 throw new IllegalArgumentException("callback == null"); 5227 } 5228 5229 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() { 5230 @Override 5231 public void onKeyguardExitResult(boolean success) { 5232 try { 5233 callback.onKeyguardExitResult(success); 5234 } catch (RemoteException e) { 5235 // Client has died, we don't care. 5236 } 5237 } 5238 }); 5239 } 5240 5241 @Override 5242 public boolean inKeyguardRestrictedInputMode() { 5243 return mPolicy.inKeyguardRestrictedKeyInputMode(); 5244 } 5245 5246 @Override 5247 public boolean isKeyguardLocked() { 5248 return mPolicy.isKeyguardLocked(); 5249 } 5250 5251 @Override 5252 public boolean isKeyguardSecure() { 5253 return mPolicy.isKeyguardSecure(); 5254 } 5255 5256 @Override 5257 public void dismissKeyguard() { 5258 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5259 != PackageManager.PERMISSION_GRANTED) { 5260 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5261 } 5262 synchronized(mWindowMap) { 5263 mPolicy.dismissKeyguardLw(); 5264 } 5265 } 5266 5267 @Override 5268 public void keyguardGoingAway(boolean disableWindowAnimations, 5269 boolean keyguardGoingToNotificationShade) { 5270 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5271 != PackageManager.PERMISSION_GRANTED) { 5272 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5273 } 5274 synchronized (mWindowMap) { 5275 mAnimator.mKeyguardGoingAway = true; 5276 mAnimator.mKeyguardGoingAwayToNotificationShade = keyguardGoingToNotificationShade; 5277 mAnimator.mKeyguardGoingAwayDisableWindowAnimations = disableWindowAnimations; 5278 requestTraversalLocked(); 5279 } 5280 } 5281 5282 public void keyguardWaitingForActivityDrawn() { 5283 synchronized (mWindowMap) { 5284 mKeyguardWaitingForActivityDrawn = true; 5285 } 5286 } 5287 5288 public void notifyActivityDrawnForKeyguard() { 5289 synchronized (mWindowMap) { 5290 if (mKeyguardWaitingForActivityDrawn) { 5291 mPolicy.notifyActivityDrawnForKeyguardLw(); 5292 mKeyguardWaitingForActivityDrawn = false; 5293 } 5294 } 5295 } 5296 5297 void showGlobalActions() { 5298 mPolicy.showGlobalActions(); 5299 } 5300 5301 @Override 5302 public void closeSystemDialogs(String reason) { 5303 synchronized(mWindowMap) { 5304 final int numDisplays = mDisplayContents.size(); 5305 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5306 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5307 final int numWindows = windows.size(); 5308 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5309 final WindowState w = windows.get(winNdx); 5310 if (w.mHasSurface) { 5311 try { 5312 w.mClient.closeSystemDialogs(reason); 5313 } catch (RemoteException e) { 5314 } 5315 } 5316 } 5317 } 5318 } 5319 } 5320 5321 static float fixScale(float scale) { 5322 if (scale < 0) scale = 0; 5323 else if (scale > 20) scale = 20; 5324 return Math.abs(scale); 5325 } 5326 5327 @Override 5328 public void setAnimationScale(int which, float scale) { 5329 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5330 "setAnimationScale()")) { 5331 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5332 } 5333 5334 scale = fixScale(scale); 5335 switch (which) { 5336 case 0: mWindowAnimationScaleSetting = scale; break; 5337 case 1: mTransitionAnimationScaleSetting = scale; break; 5338 case 2: mAnimatorDurationScaleSetting = scale; break; 5339 } 5340 5341 // Persist setting 5342 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5343 } 5344 5345 @Override 5346 public void setAnimationScales(float[] scales) { 5347 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5348 "setAnimationScale()")) { 5349 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5350 } 5351 5352 if (scales != null) { 5353 if (scales.length >= 1) { 5354 mWindowAnimationScaleSetting = fixScale(scales[0]); 5355 } 5356 if (scales.length >= 2) { 5357 mTransitionAnimationScaleSetting = fixScale(scales[1]); 5358 } 5359 if (scales.length >= 3) { 5360 mAnimatorDurationScaleSetting = fixScale(scales[2]); 5361 dispatchNewAnimatorScaleLocked(null); 5362 } 5363 } 5364 5365 // Persist setting 5366 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5367 } 5368 5369 private void setAnimatorDurationScale(float scale) { 5370 mAnimatorDurationScaleSetting = scale; 5371 ValueAnimator.setDurationScale(scale); 5372 } 5373 5374 public float getWindowAnimationScaleLocked() { 5375 return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting; 5376 } 5377 5378 public float getTransitionAnimationScaleLocked() { 5379 return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting; 5380 } 5381 5382 @Override 5383 public float getAnimationScale(int which) { 5384 switch (which) { 5385 case 0: return mWindowAnimationScaleSetting; 5386 case 1: return mTransitionAnimationScaleSetting; 5387 case 2: return mAnimatorDurationScaleSetting; 5388 } 5389 return 0; 5390 } 5391 5392 @Override 5393 public float[] getAnimationScales() { 5394 return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting, 5395 mAnimatorDurationScaleSetting }; 5396 } 5397 5398 @Override 5399 public float getCurrentAnimatorScale() { 5400 synchronized(mWindowMap) { 5401 return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting; 5402 } 5403 } 5404 5405 void dispatchNewAnimatorScaleLocked(Session session) { 5406 mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget(); 5407 } 5408 5409 @Override 5410 public void registerPointerEventListener(PointerEventListener listener) { 5411 mPointerEventDispatcher.registerInputEventListener(listener); 5412 } 5413 5414 @Override 5415 public void unregisterPointerEventListener(PointerEventListener listener) { 5416 mPointerEventDispatcher.unregisterInputEventListener(listener); 5417 } 5418 5419 // Called by window manager policy. Not exposed externally. 5420 @Override 5421 public int getLidState() { 5422 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 5423 InputManagerService.SW_LID); 5424 if (sw > 0) { 5425 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 5426 return LID_CLOSED; 5427 } else if (sw == 0) { 5428 // Switch state: AKEY_STATE_UP. 5429 return LID_OPEN; 5430 } else { 5431 // Switch state: AKEY_STATE_UNKNOWN. 5432 return LID_ABSENT; 5433 } 5434 } 5435 5436 // Called by window manager policy. Not exposed externally. 5437 @Override 5438 public void switchKeyboardLayout(int deviceId, int direction) { 5439 mInputManager.switchKeyboardLayout(deviceId, direction); 5440 } 5441 5442 // Called by window manager policy. Not exposed externally. 5443 @Override 5444 public void shutdown(boolean confirm) { 5445 ShutdownThread.shutdown(mContext, confirm); 5446 } 5447 5448 // Called by window manager policy. Not exposed externally. 5449 @Override 5450 public void rebootSafeMode(boolean confirm) { 5451 ShutdownThread.rebootSafeMode(mContext, confirm); 5452 } 5453 5454 public void setCurrentProfileIds(final int[] currentProfileIds) { 5455 synchronized (mWindowMap) { 5456 mCurrentProfileIds = currentProfileIds; 5457 } 5458 } 5459 5460 public void setCurrentUser(final int newUserId, final int[] currentProfileIds) { 5461 synchronized (mWindowMap) { 5462 mCurrentUserId = newUserId; 5463 mCurrentProfileIds = currentProfileIds; 5464 mAppTransition.setCurrentUser(newUserId); 5465 mPolicy.setCurrentUserLw(newUserId); 5466 5467 // Hide windows that should not be seen by the new user. 5468 final int numDisplays = mDisplayContents.size(); 5469 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5470 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 5471 displayContent.switchUserStacks(newUserId); 5472 rebuildAppWindowListLocked(displayContent); 5473 } 5474 performLayoutAndPlaceSurfacesLocked(); 5475 } 5476 } 5477 5478 /* Called by WindowState */ 5479 boolean isCurrentProfileLocked(int userId) { 5480 if (userId == mCurrentUserId) return true; 5481 for (int i = 0; i < mCurrentProfileIds.length; i++) { 5482 if (mCurrentProfileIds[i] == userId) return true; 5483 } 5484 return false; 5485 } 5486 5487 public void enableScreenAfterBoot() { 5488 synchronized(mWindowMap) { 5489 if (DEBUG_BOOT) { 5490 RuntimeException here = new RuntimeException("here"); 5491 here.fillInStackTrace(); 5492 Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled 5493 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5494 + " mShowingBootMessages=" + mShowingBootMessages 5495 + " mSystemBooted=" + mSystemBooted, here); 5496 } 5497 if (mSystemBooted) { 5498 return; 5499 } 5500 mSystemBooted = true; 5501 hideBootMessagesLocked(); 5502 // If the screen still doesn't come up after 30 seconds, give 5503 // up and turn it on. 5504 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000); 5505 } 5506 5507 mPolicy.systemBooted(); 5508 5509 performEnableScreen(); 5510 } 5511 5512 @Override 5513 public void enableScreenIfNeeded() { 5514 synchronized (mWindowMap) { 5515 enableScreenIfNeededLocked(); 5516 } 5517 } 5518 5519 void enableScreenIfNeededLocked() { 5520 if (DEBUG_BOOT) { 5521 RuntimeException here = new RuntimeException("here"); 5522 here.fillInStackTrace(); 5523 Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled 5524 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5525 + " mShowingBootMessages=" + mShowingBootMessages 5526 + " mSystemBooted=" + mSystemBooted, here); 5527 } 5528 if (mDisplayEnabled) { 5529 return; 5530 } 5531 if (!mSystemBooted && !mShowingBootMessages) { 5532 return; 5533 } 5534 mH.sendEmptyMessage(H.ENABLE_SCREEN); 5535 } 5536 5537 public void performBootTimeout() { 5538 synchronized(mWindowMap) { 5539 if (mDisplayEnabled) { 5540 return; 5541 } 5542 Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled"); 5543 mForceDisplayEnabled = true; 5544 } 5545 performEnableScreen(); 5546 } 5547 5548 public void performEnableScreen() { 5549 synchronized(mWindowMap) { 5550 if (DEBUG_BOOT) { 5551 RuntimeException here = new RuntimeException("here"); 5552 here.fillInStackTrace(); 5553 Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled 5554 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5555 + " mShowingBootMessages=" + mShowingBootMessages 5556 + " mSystemBooted=" + mSystemBooted 5557 + " mOnlyCore=" + mOnlyCore, here); 5558 } 5559 if (mDisplayEnabled) { 5560 return; 5561 } 5562 if (!mSystemBooted && !mShowingBootMessages) { 5563 return; 5564 } 5565 5566 if (!mForceDisplayEnabled) { 5567 // Don't enable the screen until all existing windows 5568 // have been drawn. 5569 boolean haveBootMsg = false; 5570 boolean haveApp = false; 5571 // if the wallpaper service is disabled on the device, we're never going to have 5572 // wallpaper, don't bother waiting for it 5573 boolean haveWallpaper = false; 5574 boolean wallpaperEnabled = mContext.getResources().getBoolean( 5575 com.android.internal.R.bool.config_enableWallpaperService) 5576 && !mOnlyCore; 5577 boolean haveKeyguard = true; 5578 // TODO(multidisplay): Expand to all displays? 5579 final WindowList windows = getDefaultWindowListLocked(); 5580 final int N = windows.size(); 5581 for (int i=0; i<N; i++) { 5582 WindowState w = windows.get(i); 5583 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 5584 return; 5585 } 5586 if (w.isDrawnLw()) { 5587 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { 5588 haveBootMsg = true; 5589 } else if (w.mAttrs.type == TYPE_APPLICATION) { 5590 haveApp = true; 5591 } else if (w.mAttrs.type == TYPE_WALLPAPER) { 5592 haveWallpaper = true; 5593 } else if (w.mAttrs.type == TYPE_STATUS_BAR) { 5594 haveKeyguard = mPolicy.isKeyguardDrawnLw(); 5595 } 5596 } 5597 } 5598 5599 if (DEBUG_SCREEN_ON || DEBUG_BOOT) { 5600 Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages 5601 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp 5602 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled 5603 + " haveKeyguard=" + haveKeyguard); 5604 } 5605 5606 // If we are turning on the screen to show the boot message, 5607 // don't do it until the boot message is actually displayed. 5608 if (!mSystemBooted && !haveBootMsg) { 5609 return; 5610 } 5611 5612 // If we are turning on the screen after the boot is completed 5613 // normally, don't do so until we have the application and 5614 // wallpaper. 5615 if (mSystemBooted && ((!haveApp && !haveKeyguard) || 5616 (wallpaperEnabled && !haveWallpaper))) { 5617 return; 5618 } 5619 } 5620 5621 mDisplayEnabled = true; 5622 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!"); 5623 if (false) { 5624 StringWriter sw = new StringWriter(); 5625 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 5626 this.dump(null, pw, null); 5627 pw.flush(); 5628 Slog.i(TAG, sw.toString()); 5629 } 5630 try { 5631 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); 5632 if (surfaceFlinger != null) { 5633 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); 5634 Parcel data = Parcel.obtain(); 5635 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 5636 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED 5637 data, null, 0); 5638 data.recycle(); 5639 } 5640 } catch (RemoteException ex) { 5641 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); 5642 } 5643 5644 // Enable input dispatch. 5645 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled); 5646 } 5647 5648 mPolicy.enableScreenAfterBoot(); 5649 5650 // Make sure the last requested orientation has been applied. 5651 updateRotationUnchecked(false, false); 5652 } 5653 5654 public void showBootMessage(final CharSequence msg, final boolean always) { 5655 boolean first = false; 5656 synchronized(mWindowMap) { 5657 if (DEBUG_BOOT) { 5658 RuntimeException here = new RuntimeException("here"); 5659 here.fillInStackTrace(); 5660 Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always 5661 + " mAllowBootMessages=" + mAllowBootMessages 5662 + " mShowingBootMessages=" + mShowingBootMessages 5663 + " mSystemBooted=" + mSystemBooted, here); 5664 } 5665 if (!mAllowBootMessages) { 5666 return; 5667 } 5668 if (!mShowingBootMessages) { 5669 if (!always) { 5670 return; 5671 } 5672 first = true; 5673 } 5674 if (mSystemBooted) { 5675 return; 5676 } 5677 mShowingBootMessages = true; 5678 mPolicy.showBootMessage(msg, always); 5679 } 5680 if (first) { 5681 performEnableScreen(); 5682 } 5683 } 5684 5685 public void hideBootMessagesLocked() { 5686 if (DEBUG_BOOT) { 5687 RuntimeException here = new RuntimeException("here"); 5688 here.fillInStackTrace(); 5689 Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled 5690 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5691 + " mShowingBootMessages=" + mShowingBootMessages 5692 + " mSystemBooted=" + mSystemBooted, here); 5693 } 5694 if (mShowingBootMessages) { 5695 mShowingBootMessages = false; 5696 mPolicy.hideBootMessages(); 5697 } 5698 } 5699 5700 @Override 5701 public void setInTouchMode(boolean mode) { 5702 synchronized(mWindowMap) { 5703 mInTouchMode = mode; 5704 } 5705 } 5706 5707 public void showCircularDisplayMaskIfNeeded() { 5708 // we're fullscreen and not hosted in an ActivityView 5709 if (mContext.getResources().getBoolean( 5710 com.android.internal.R.bool.config_windowIsRound) 5711 && mContext.getResources().getBoolean( 5712 com.android.internal.R.bool.config_windowShowCircularMask)) { 5713 mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK)); 5714 } 5715 } 5716 5717 public void showCircularMask() { 5718 synchronized(mWindowMap) { 5719 5720 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5721 ">>> OPEN TRANSACTION showDisplayMask"); 5722 SurfaceControl.openTransaction(); 5723 try { 5724 // TODO(multi-display): support multiple displays 5725 if (mCircularDisplayMask == null) { 5726 int screenOffset = (int) mContext.getResources().getDimensionPixelSize( 5727 com.android.internal.R.dimen.circular_display_mask_offset); 5728 5729 mCircularDisplayMask = new CircularDisplayMask( 5730 getDefaultDisplayContentLocked().getDisplay(), 5731 mFxSession, 5732 mPolicy.windowTypeToLayerLw( 5733 WindowManager.LayoutParams.TYPE_POINTER) 5734 * TYPE_LAYER_MULTIPLIER + 10, screenOffset); 5735 } 5736 mCircularDisplayMask.setVisibility(true); 5737 } finally { 5738 SurfaceControl.closeTransaction(); 5739 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5740 "<<< CLOSE TRANSACTION showDisplayMask"); 5741 } 5742 } 5743 } 5744 5745 // TODO: more accounting of which pid(s) turned it on, keep count, 5746 // only allow disables from pids which have count on, etc. 5747 @Override 5748 public void showStrictModeViolation(boolean on) { 5749 int pid = Binder.getCallingPid(); 5750 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid)); 5751 } 5752 5753 private void showStrictModeViolation(int arg, int pid) { 5754 final boolean on = arg != 0; 5755 synchronized(mWindowMap) { 5756 // Ignoring requests to enable the red border from clients 5757 // which aren't on screen. (e.g. Broadcast Receivers in 5758 // the background..) 5759 if (on) { 5760 boolean isVisible = false; 5761 final int numDisplays = mDisplayContents.size(); 5762 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5763 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5764 final int numWindows = windows.size(); 5765 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5766 final WindowState ws = windows.get(winNdx); 5767 if (ws.mSession.mPid == pid && ws.isVisibleLw()) { 5768 isVisible = true; 5769 break; 5770 } 5771 } 5772 } 5773 if (!isVisible) { 5774 return; 5775 } 5776 } 5777 5778 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5779 ">>> OPEN TRANSACTION showStrictModeViolation"); 5780 SurfaceControl.openTransaction(); 5781 try { 5782 // TODO(multi-display): support multiple displays 5783 if (mStrictModeFlash == null) { 5784 mStrictModeFlash = new StrictModeFlash( 5785 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 5786 } 5787 mStrictModeFlash.setVisibility(on); 5788 } finally { 5789 SurfaceControl.closeTransaction(); 5790 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5791 "<<< CLOSE TRANSACTION showStrictModeViolation"); 5792 } 5793 } 5794 } 5795 5796 @Override 5797 public void setStrictModeVisualIndicatorPreference(String value) { 5798 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 5799 } 5800 5801 /** 5802 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 5803 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 5804 * of the target image. 5805 * 5806 * @param displayId the Display to take a screenshot of. 5807 * @param width the width of the target bitmap 5808 * @param height the height of the target bitmap 5809 * @param force565 if true the returned bitmap will be RGB_565, otherwise it 5810 * will be the same config as the surface 5811 */ 5812 @Override 5813 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, 5814 int height, boolean force565) { 5815 if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, 5816 "screenshotApplications()")) { 5817 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 5818 } 5819 5820 final DisplayContent displayContent = getDisplayContentLocked(displayId); 5821 if (displayContent == null) { 5822 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 5823 + ": returning null. No Display for displayId=" + displayId); 5824 return null; 5825 } 5826 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 5827 int dw = displayInfo.logicalWidth; 5828 int dh = displayInfo.logicalHeight; 5829 if (dw == 0 || dh == 0) { 5830 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 5831 + ": returning null. logical widthxheight=" + dw + "x" + dh); 5832 return null; 5833 } 5834 5835 Bitmap rawss = null; 5836 5837 int maxLayer = 0; 5838 final Rect frame = new Rect(); 5839 final Rect stackBounds = new Rect(); 5840 5841 float scale = 0; 5842 int rot = Surface.ROTATION_0; 5843 5844 boolean screenshotReady; 5845 int minLayer; 5846 if (appToken == null) { 5847 screenshotReady = true; 5848 minLayer = 0; 5849 } else { 5850 screenshotReady = false; 5851 minLayer = Integer.MAX_VALUE; 5852 } 5853 5854 int retryCount = 0; 5855 WindowState appWin = null; 5856 5857 final boolean appIsImTarget = mInputMethodTarget != null 5858 && mInputMethodTarget.mAppToken != null 5859 && mInputMethodTarget.mAppToken.appToken != null 5860 && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken; 5861 5862 final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1) 5863 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 5864 5865 while (true) { 5866 if (retryCount++ > 0) { 5867 try { 5868 Thread.sleep(100); 5869 } catch (InterruptedException e) { 5870 } 5871 } 5872 synchronized(mWindowMap) { 5873 // Figure out the part of the screen that is actually the app. 5874 appWin = null; 5875 final WindowList windows = displayContent.getWindowList(); 5876 for (int i = windows.size() - 1; i >= 0; i--) { 5877 WindowState ws = windows.get(i); 5878 if (!ws.mHasSurface) { 5879 continue; 5880 } 5881 if (ws.mLayer >= aboveAppLayer) { 5882 continue; 5883 } 5884 if (ws.mIsImWindow) { 5885 if (!appIsImTarget) { 5886 continue; 5887 } 5888 } else if (ws.mIsWallpaper) { 5889 // Fall through. 5890 } else if (appToken != null) { 5891 if (ws.mAppToken == null || ws.mAppToken.token != appToken) { 5892 // This app window is of no interest if it is not associated with the 5893 // screenshot app. 5894 continue; 5895 } 5896 appWin = ws; 5897 } 5898 5899 // Include this window. 5900 5901 final WindowStateAnimator winAnim = ws.mWinAnimator; 5902 if (maxLayer < winAnim.mSurfaceLayer) { 5903 maxLayer = winAnim.mSurfaceLayer; 5904 } 5905 if (minLayer > winAnim.mSurfaceLayer) { 5906 minLayer = winAnim.mSurfaceLayer; 5907 } 5908 5909 // Don't include wallpaper in bounds calculation 5910 if (!ws.mIsWallpaper) { 5911 final Rect wf = ws.mFrame; 5912 final Rect cr = ws.mContentInsets; 5913 int left = wf.left + cr.left; 5914 int top = wf.top + cr.top; 5915 int right = wf.right - cr.right; 5916 int bottom = wf.bottom - cr.bottom; 5917 frame.union(left, top, right, bottom); 5918 ws.getStackBounds(stackBounds); 5919 frame.intersect(stackBounds); 5920 } 5921 5922 if (ws.mAppToken != null && ws.mAppToken.token == appToken && 5923 ws.isDisplayedLw()) { 5924 screenshotReady = true; 5925 } 5926 } 5927 5928 if (appToken != null && appWin == null) { 5929 // Can't find a window to snapshot. 5930 if (DEBUG_SCREENSHOT) Slog.i(TAG, 5931 "Screenshot: Couldn't find a surface matching " + appToken); 5932 return null; 5933 } 5934 5935 if (!screenshotReady) { 5936 if (retryCount > MAX_SCREENSHOT_RETRIES) { 5937 Slog.i(TAG, "Screenshot max retries " + retryCount + " of " + appToken + 5938 " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" + 5939 appWin.mWinAnimator.mDrawState))); 5940 return null; 5941 } 5942 5943 // Delay and hope that window gets drawn. 5944 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken 5945 + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState); 5946 continue; 5947 } 5948 5949 // Screenshot is ready to be taken. Everything from here below will continue 5950 // through the bottom of the loop and return a value. We only stay in the loop 5951 // because we don't want to release the mWindowMap lock until the screenshot is 5952 // taken. 5953 5954 if (maxLayer == 0) { 5955 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 5956 + ": returning null maxLayer=" + maxLayer); 5957 return null; 5958 } 5959 5960 // Constrain frame to the screen size. 5961 frame.intersect(0, 0, dw, dh); 5962 // Constrain thumbnail to smaller of screen width or height. Assumes aspect 5963 // of thumbnail is the same as the screen (in landscape) or square. 5964 scale = Math.max(width / (float) frame.width(), height / (float) frame.height()); 5965 dw = (int)(dw * scale); 5966 dh = (int)(dh * scale); 5967 5968 // The screenshot API does not apply the current screen rotation. 5969 rot = getDefaultDisplayContentLocked().getDisplay().getRotation(); 5970 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 5971 final int tmp = dw; 5972 dw = dh; 5973 dh = tmp; 5974 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; 5975 } 5976 5977 if (DEBUG_SCREENSHOT) { 5978 Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 5979 + maxLayer + " appToken=" + appToken); 5980 for (int i = 0; i < windows.size(); i++) { 5981 WindowState win = windows.get(i); 5982 Slog.i(TAG, win + ": " + win.mLayer 5983 + " animLayer=" + win.mWinAnimator.mAnimLayer 5984 + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer); 5985 } 5986 } 5987 5988 ScreenRotationAnimation screenRotationAnimation = 5989 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 5990 final boolean inRotation = screenRotationAnimation != null && 5991 screenRotationAnimation.isAnimating(); 5992 if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG, 5993 "Taking screenshot while rotating"); 5994 5995 rawss = SurfaceControl.screenshot(new Rect(), dw, dh, minLayer, maxLayer, 5996 inRotation); 5997 if (rawss == null) { 5998 Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh 5999 + ") to layer " + maxLayer); 6000 return null; 6001 } 6002 } 6003 6004 break; 6005 } 6006 6007 Bitmap bm = Bitmap.createBitmap(width, height, force565 ? 6008 Config.RGB_565 : rawss.getConfig()); 6009 if (DEBUG_SCREENSHOT) { 6010 bm.eraseColor(0xFF000000); 6011 } 6012 frame.scale(scale); 6013 Matrix matrix = new Matrix(); 6014 ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix); 6015 // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left 6016 matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top)); 6017 Canvas canvas = new Canvas(bm); 6018 canvas.drawBitmap(rawss, matrix, null); 6019 canvas.setBitmap(null); 6020 6021 if (DEBUG_SCREENSHOT) { 6022 // TEST IF IT's ALL BLACK 6023 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 6024 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 6025 boolean allBlack = true; 6026 final int firstColor = buffer[0]; 6027 for (int i = 0; i < buffer.length; i++) { 6028 if (buffer[i] != firstColor) { 6029 allBlack = false; 6030 break; 6031 } 6032 } 6033 if (allBlack) { 6034 Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" + 6035 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 6036 (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") + 6037 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 6038 } 6039 } 6040 6041 rawss.recycle(); 6042 return bm; 6043 } 6044 6045 /** 6046 * Freeze rotation changes. (Enable "rotation lock".) 6047 * Persists across reboots. 6048 * @param rotation The desired rotation to freeze to, or -1 to use the 6049 * current rotation. 6050 */ 6051 @Override 6052 public void freezeRotation(int rotation) { 6053 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 6054 "freezeRotation()")) { 6055 throw new SecurityException("Requires SET_ORIENTATION permission"); 6056 } 6057 if (rotation < -1 || rotation > Surface.ROTATION_270) { 6058 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 6059 + "rotation constant."); 6060 } 6061 6062 if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); 6063 6064 long origId = Binder.clearCallingIdentity(); 6065 try { 6066 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, 6067 rotation == -1 ? mRotation : rotation); 6068 } finally { 6069 Binder.restoreCallingIdentity(origId); 6070 } 6071 6072 updateRotationUnchecked(false, false); 6073 } 6074 6075 /** 6076 * Thaw rotation changes. (Disable "rotation lock".) 6077 * Persists across reboots. 6078 */ 6079 @Override 6080 public void thawRotation() { 6081 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 6082 "thawRotation()")) { 6083 throw new SecurityException("Requires SET_ORIENTATION permission"); 6084 } 6085 6086 if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); 6087 6088 long origId = Binder.clearCallingIdentity(); 6089 try { 6090 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 6091 777); // rot not used 6092 } finally { 6093 Binder.restoreCallingIdentity(origId); 6094 } 6095 6096 updateRotationUnchecked(false, false); 6097 } 6098 6099 /** 6100 * Recalculate the current rotation. 6101 * 6102 * Called by the window manager policy whenever the state of the system changes 6103 * such that the current rotation might need to be updated, such as when the 6104 * device is docked or rotated into a new posture. 6105 */ 6106 @Override 6107 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 6108 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 6109 } 6110 6111 /** 6112 * Temporarily pauses rotation changes until resumed. 6113 * 6114 * This can be used to prevent rotation changes from occurring while the user is 6115 * performing certain operations, such as drag and drop. 6116 * 6117 * This call nests and must be matched by an equal number of calls to 6118 * {@link #resumeRotationLocked}. 6119 */ 6120 void pauseRotationLocked() { 6121 mDeferredRotationPauseCount += 1; 6122 } 6123 6124 /** 6125 * Resumes normal rotation changes after being paused. 6126 */ 6127 void resumeRotationLocked() { 6128 if (mDeferredRotationPauseCount > 0) { 6129 mDeferredRotationPauseCount -= 1; 6130 if (mDeferredRotationPauseCount == 0) { 6131 boolean changed = updateRotationUncheckedLocked(false); 6132 if (changed) { 6133 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6134 } 6135 } 6136 } 6137 } 6138 6139 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 6140 if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" 6141 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); 6142 6143 long origId = Binder.clearCallingIdentity(); 6144 boolean changed; 6145 synchronized(mWindowMap) { 6146 changed = updateRotationUncheckedLocked(false); 6147 if (!changed || forceRelayout) { 6148 getDefaultDisplayContentLocked().layoutNeeded = true; 6149 performLayoutAndPlaceSurfacesLocked(); 6150 } 6151 } 6152 6153 if (changed || alwaysSendConfiguration) { 6154 sendNewConfiguration(); 6155 } 6156 6157 Binder.restoreCallingIdentity(origId); 6158 } 6159 6160 // TODO(multidisplay): Rotate any display? 6161 /** 6162 * Updates the current rotation. 6163 * 6164 * Returns true if the rotation has been changed. In this case YOU 6165 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. 6166 */ 6167 public boolean updateRotationUncheckedLocked(boolean inTransaction) { 6168 if (mDeferredRotationPauseCount > 0) { 6169 // Rotation updates have been paused temporarily. Defer the update until 6170 // updates have been resumed. 6171 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused."); 6172 return false; 6173 } 6174 6175 ScreenRotationAnimation screenRotationAnimation = 6176 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6177 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 6178 // Rotation updates cannot be performed while the previous rotation change 6179 // animation is still in progress. Skip this update. We will try updating 6180 // again after the animation is finished and the display is unfrozen. 6181 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress."); 6182 return false; 6183 } 6184 6185 if (!mDisplayEnabled) { 6186 // No point choosing a rotation if the display is not enabled. 6187 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled."); 6188 return false; 6189 } 6190 6191 // TODO: Implement forced rotation changes. 6192 // Set mAltOrientation to indicate that the application is receiving 6193 // an orientation that has different metrics than it expected. 6194 // eg. Portrait instead of Landscape. 6195 6196 int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation); 6197 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 6198 mForcedAppOrientation, rotation); 6199 6200 if (DEBUG_ORIENTATION) { 6201 Slog.v(TAG, "Application requested orientation " 6202 + mForcedAppOrientation + ", got rotation " + rotation 6203 + " which has " + (altOrientation ? "incompatible" : "compatible") 6204 + " metrics"); 6205 } 6206 6207 if (mRotation == rotation && mAltOrientation == altOrientation) { 6208 // No change. 6209 return false; 6210 } 6211 6212 if (DEBUG_ORIENTATION) { 6213 Slog.v(TAG, 6214 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") 6215 + " from " + mRotation + (mAltOrientation ? " (alt)" : "") 6216 + ", forceApp=" + mForcedAppOrientation); 6217 } 6218 6219 mRotation = rotation; 6220 mAltOrientation = altOrientation; 6221 mPolicy.setRotationLw(mRotation); 6222 6223 mWindowsFreezingScreen = true; 6224 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 6225 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION); 6226 mWaitingForConfig = true; 6227 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6228 displayContent.layoutNeeded = true; 6229 final int[] anim = new int[2]; 6230 if (displayContent.isDimming()) { 6231 anim[0] = anim[1] = 0; 6232 } else { 6233 mPolicy.selectRotationAnimationLw(anim); 6234 } 6235 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]); 6236 // startFreezingDisplayLocked can reset the ScreenRotationAnimation. 6237 screenRotationAnimation = 6238 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6239 6240 // We need to update our screen size information to match the new 6241 // rotation. Note that this is redundant with the later call to 6242 // sendNewConfiguration() that must be called after this function 6243 // returns... however we need to do the screen size part of that 6244 // before then so we have the correct size to use when initializing 6245 // the rotation animation for the new rotation. 6246 computeScreenConfigurationLocked(null); 6247 6248 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6249 if (!inTransaction) { 6250 if (SHOW_TRANSACTIONS) { 6251 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked"); 6252 } 6253 SurfaceControl.openTransaction(); 6254 } 6255 try { 6256 // NOTE: We disable the rotation in the emulator because 6257 // it doesn't support hardware OpenGL emulation yet. 6258 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 6259 && screenRotationAnimation.hasScreenshot()) { 6260 if (screenRotationAnimation.setRotationInTransaction( 6261 rotation, mFxSession, 6262 MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(), 6263 displayInfo.logicalWidth, displayInfo.logicalHeight)) { 6264 scheduleAnimationLocked(); 6265 } 6266 } 6267 6268 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 6269 } finally { 6270 if (!inTransaction) { 6271 SurfaceControl.closeTransaction(); 6272 if (SHOW_LIGHT_TRANSACTIONS) { 6273 Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked"); 6274 } 6275 } 6276 } 6277 6278 final WindowList windows = displayContent.getWindowList(); 6279 for (int i = windows.size() - 1; i >= 0; i--) { 6280 WindowState w = windows.get(i); 6281 if (w.mHasSurface) { 6282 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w); 6283 w.mOrientationChanging = true; 6284 mInnerFields.mOrientationChangeComplete = false; 6285 } 6286 w.mLastFreezeDuration = 0; 6287 } 6288 6289 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 6290 try { 6291 mRotationWatchers.get(i).watcher.onRotationChanged(rotation); 6292 } catch (RemoteException e) { 6293 } 6294 } 6295 6296 //TODO (multidisplay): Magnification is supported only for the default display. 6297 if (mAccessibilityController != null 6298 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 6299 mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation); 6300 } 6301 6302 return true; 6303 } 6304 6305 @Override 6306 public int getRotation() { 6307 return mRotation; 6308 } 6309 6310 @Override 6311 public boolean isRotationFrozen() { 6312 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED; 6313 } 6314 6315 @Override 6316 public int watchRotation(IRotationWatcher watcher) { 6317 final IBinder watcherBinder = watcher.asBinder(); 6318 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 6319 @Override 6320 public void binderDied() { 6321 synchronized (mWindowMap) { 6322 for (int i=0; i<mRotationWatchers.size(); i++) { 6323 if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) { 6324 RotationWatcher removed = mRotationWatchers.remove(i); 6325 IBinder binder = removed.watcher.asBinder(); 6326 if (binder != null) { 6327 binder.unlinkToDeath(this, 0); 6328 } 6329 i--; 6330 } 6331 } 6332 } 6333 } 6334 }; 6335 6336 synchronized (mWindowMap) { 6337 try { 6338 watcher.asBinder().linkToDeath(dr, 0); 6339 mRotationWatchers.add(new RotationWatcher(watcher, dr)); 6340 } catch (RemoteException e) { 6341 // Client died, no cleanup needed. 6342 } 6343 6344 return mRotation; 6345 } 6346 } 6347 6348 @Override 6349 public void removeRotationWatcher(IRotationWatcher watcher) { 6350 final IBinder watcherBinder = watcher.asBinder(); 6351 synchronized (mWindowMap) { 6352 for (int i=0; i<mRotationWatchers.size(); i++) { 6353 RotationWatcher rotationWatcher = mRotationWatchers.get(i); 6354 if (watcherBinder == rotationWatcher.watcher.asBinder()) { 6355 RotationWatcher removed = mRotationWatchers.remove(i); 6356 IBinder binder = removed.watcher.asBinder(); 6357 if (binder != null) { 6358 binder.unlinkToDeath(removed.deathRecipient, 0); 6359 } 6360 i--; 6361 } 6362 } 6363 } 6364 } 6365 6366 /** 6367 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 6368 * theme attribute) on devices that feature a physical options menu key attempt to position 6369 * their menu panel window along the edge of the screen nearest the physical menu key. 6370 * This lowers the travel distance between invoking the menu panel and selecting 6371 * a menu option. 6372 * 6373 * This method helps control where that menu is placed. Its current implementation makes 6374 * assumptions about the menu key and its relationship to the screen based on whether 6375 * the device's natural orientation is portrait (width < height) or landscape. 6376 * 6377 * The menu key is assumed to be located along the bottom edge of natural-portrait 6378 * devices and along the right edge of natural-landscape devices. If these assumptions 6379 * do not hold for the target device, this method should be changed to reflect that. 6380 * 6381 * @return A {@link Gravity} value for placing the options menu window 6382 */ 6383 @Override 6384 public int getPreferredOptionsPanelGravity() { 6385 synchronized (mWindowMap) { 6386 final int rotation = getRotation(); 6387 6388 // TODO(multidisplay): Assume that such devices physical keys are on the main screen. 6389 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6390 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) { 6391 // On devices with a natural orientation of portrait 6392 switch (rotation) { 6393 default: 6394 case Surface.ROTATION_0: 6395 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6396 case Surface.ROTATION_90: 6397 return Gravity.RIGHT | Gravity.BOTTOM; 6398 case Surface.ROTATION_180: 6399 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6400 case Surface.ROTATION_270: 6401 return Gravity.START | Gravity.BOTTOM; 6402 } 6403 } 6404 6405 // On devices with a natural orientation of landscape 6406 switch (rotation) { 6407 default: 6408 case Surface.ROTATION_0: 6409 return Gravity.RIGHT | Gravity.BOTTOM; 6410 case Surface.ROTATION_90: 6411 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6412 case Surface.ROTATION_180: 6413 return Gravity.START | Gravity.BOTTOM; 6414 case Surface.ROTATION_270: 6415 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6416 } 6417 } 6418 } 6419 6420 /** 6421 * Starts the view server on the specified port. 6422 * 6423 * @param port The port to listener to. 6424 * 6425 * @return True if the server was successfully started, false otherwise. 6426 * 6427 * @see com.android.server.wm.ViewServer 6428 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 6429 */ 6430 @Override 6431 public boolean startViewServer(int port) { 6432 if (isSystemSecure()) { 6433 return false; 6434 } 6435 6436 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 6437 return false; 6438 } 6439 6440 if (port < 1024) { 6441 return false; 6442 } 6443 6444 if (mViewServer != null) { 6445 if (!mViewServer.isRunning()) { 6446 try { 6447 return mViewServer.start(); 6448 } catch (IOException e) { 6449 Slog.w(TAG, "View server did not start"); 6450 } 6451 } 6452 return false; 6453 } 6454 6455 try { 6456 mViewServer = new ViewServer(this, port); 6457 return mViewServer.start(); 6458 } catch (IOException e) { 6459 Slog.w(TAG, "View server did not start"); 6460 } 6461 return false; 6462 } 6463 6464 private boolean isSystemSecure() { 6465 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 6466 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 6467 } 6468 6469 /** 6470 * Stops the view server if it exists. 6471 * 6472 * @return True if the server stopped, false if it wasn't started or 6473 * couldn't be stopped. 6474 * 6475 * @see com.android.server.wm.ViewServer 6476 */ 6477 @Override 6478 public boolean stopViewServer() { 6479 if (isSystemSecure()) { 6480 return false; 6481 } 6482 6483 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 6484 return false; 6485 } 6486 6487 if (mViewServer != null) { 6488 return mViewServer.stop(); 6489 } 6490 return false; 6491 } 6492 6493 /** 6494 * Indicates whether the view server is running. 6495 * 6496 * @return True if the server is running, false otherwise. 6497 * 6498 * @see com.android.server.wm.ViewServer 6499 */ 6500 @Override 6501 public boolean isViewServerRunning() { 6502 if (isSystemSecure()) { 6503 return false; 6504 } 6505 6506 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 6507 return false; 6508 } 6509 6510 return mViewServer != null && mViewServer.isRunning(); 6511 } 6512 6513 /** 6514 * Lists all availble windows in the system. The listing is written in the 6515 * specified Socket's output stream with the following syntax: 6516 * windowHashCodeInHexadecimal windowName 6517 * Each line of the ouput represents a different window. 6518 * 6519 * @param client The remote client to send the listing to. 6520 * @return False if an error occured, true otherwise. 6521 */ 6522 boolean viewServerListWindows(Socket client) { 6523 if (isSystemSecure()) { 6524 return false; 6525 } 6526 6527 boolean result = true; 6528 6529 WindowList windows = new WindowList(); 6530 synchronized (mWindowMap) { 6531 //noinspection unchecked 6532 final int numDisplays = mDisplayContents.size(); 6533 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6534 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 6535 windows.addAll(displayContent.getWindowList()); 6536 } 6537 } 6538 6539 BufferedWriter out = null; 6540 6541 // Any uncaught exception will crash the system process 6542 try { 6543 OutputStream clientStream = client.getOutputStream(); 6544 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6545 6546 final int count = windows.size(); 6547 for (int i = 0; i < count; i++) { 6548 final WindowState w = windows.get(i); 6549 out.write(Integer.toHexString(System.identityHashCode(w))); 6550 out.write(' '); 6551 out.append(w.mAttrs.getTitle()); 6552 out.write('\n'); 6553 } 6554 6555 out.write("DONE.\n"); 6556 out.flush(); 6557 } catch (Exception e) { 6558 result = false; 6559 } finally { 6560 if (out != null) { 6561 try { 6562 out.close(); 6563 } catch (IOException e) { 6564 result = false; 6565 } 6566 } 6567 } 6568 6569 return result; 6570 } 6571 6572 // TODO(multidisplay): Extend to multiple displays. 6573 /** 6574 * Returns the focused window in the following format: 6575 * windowHashCodeInHexadecimal windowName 6576 * 6577 * @param client The remote client to send the listing to. 6578 * @return False if an error occurred, true otherwise. 6579 */ 6580 boolean viewServerGetFocusedWindow(Socket client) { 6581 if (isSystemSecure()) { 6582 return false; 6583 } 6584 6585 boolean result = true; 6586 6587 WindowState focusedWindow = getFocusedWindow(); 6588 6589 BufferedWriter out = null; 6590 6591 // Any uncaught exception will crash the system process 6592 try { 6593 OutputStream clientStream = client.getOutputStream(); 6594 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6595 6596 if(focusedWindow != null) { 6597 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 6598 out.write(' '); 6599 out.append(focusedWindow.mAttrs.getTitle()); 6600 } 6601 out.write('\n'); 6602 out.flush(); 6603 } catch (Exception e) { 6604 result = false; 6605 } finally { 6606 if (out != null) { 6607 try { 6608 out.close(); 6609 } catch (IOException e) { 6610 result = false; 6611 } 6612 } 6613 } 6614 6615 return result; 6616 } 6617 6618 /** 6619 * Sends a command to a target window. The result of the command, if any, will be 6620 * written in the output stream of the specified socket. 6621 * 6622 * The parameters must follow this syntax: 6623 * windowHashcode extra 6624 * 6625 * Where XX is the length in characeters of the windowTitle. 6626 * 6627 * The first parameter is the target window. The window with the specified hashcode 6628 * will be the target. If no target can be found, nothing happens. The extra parameters 6629 * will be delivered to the target window and as parameters to the command itself. 6630 * 6631 * @param client The remote client to sent the result, if any, to. 6632 * @param command The command to execute. 6633 * @param parameters The command parameters. 6634 * 6635 * @return True if the command was successfully delivered, false otherwise. This does 6636 * not indicate whether the command itself was successful. 6637 */ 6638 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 6639 if (isSystemSecure()) { 6640 return false; 6641 } 6642 6643 boolean success = true; 6644 Parcel data = null; 6645 Parcel reply = null; 6646 6647 BufferedWriter out = null; 6648 6649 // Any uncaught exception will crash the system process 6650 try { 6651 // Find the hashcode of the window 6652 int index = parameters.indexOf(' '); 6653 if (index == -1) { 6654 index = parameters.length(); 6655 } 6656 final String code = parameters.substring(0, index); 6657 int hashCode = (int) Long.parseLong(code, 16); 6658 6659 // Extract the command's parameter after the window description 6660 if (index < parameters.length()) { 6661 parameters = parameters.substring(index + 1); 6662 } else { 6663 parameters = ""; 6664 } 6665 6666 final WindowState window = findWindow(hashCode); 6667 if (window == null) { 6668 return false; 6669 } 6670 6671 data = Parcel.obtain(); 6672 data.writeInterfaceToken("android.view.IWindow"); 6673 data.writeString(command); 6674 data.writeString(parameters); 6675 data.writeInt(1); 6676 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 6677 6678 reply = Parcel.obtain(); 6679 6680 final IBinder binder = window.mClient.asBinder(); 6681 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 6682 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 6683 6684 reply.readException(); 6685 6686 if (!client.isOutputShutdown()) { 6687 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 6688 out.write("DONE\n"); 6689 out.flush(); 6690 } 6691 6692 } catch (Exception e) { 6693 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); 6694 success = false; 6695 } finally { 6696 if (data != null) { 6697 data.recycle(); 6698 } 6699 if (reply != null) { 6700 reply.recycle(); 6701 } 6702 if (out != null) { 6703 try { 6704 out.close(); 6705 } catch (IOException e) { 6706 6707 } 6708 } 6709 } 6710 6711 return success; 6712 } 6713 6714 public void addWindowChangeListener(WindowChangeListener listener) { 6715 synchronized(mWindowMap) { 6716 mWindowChangeListeners.add(listener); 6717 } 6718 } 6719 6720 public void removeWindowChangeListener(WindowChangeListener listener) { 6721 synchronized(mWindowMap) { 6722 mWindowChangeListeners.remove(listener); 6723 } 6724 } 6725 6726 private void notifyWindowsChanged() { 6727 WindowChangeListener[] windowChangeListeners; 6728 synchronized(mWindowMap) { 6729 if(mWindowChangeListeners.isEmpty()) { 6730 return; 6731 } 6732 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6733 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6734 } 6735 int N = windowChangeListeners.length; 6736 for(int i = 0; i < N; i++) { 6737 windowChangeListeners[i].windowsChanged(); 6738 } 6739 } 6740 6741 private void notifyFocusChanged() { 6742 WindowChangeListener[] windowChangeListeners; 6743 synchronized(mWindowMap) { 6744 if(mWindowChangeListeners.isEmpty()) { 6745 return; 6746 } 6747 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6748 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6749 } 6750 int N = windowChangeListeners.length; 6751 for(int i = 0; i < N; i++) { 6752 windowChangeListeners[i].focusChanged(); 6753 } 6754 } 6755 6756 private WindowState findWindow(int hashCode) { 6757 if (hashCode == -1) { 6758 // TODO(multidisplay): Extend to multiple displays. 6759 return getFocusedWindow(); 6760 } 6761 6762 synchronized (mWindowMap) { 6763 final int numDisplays = mDisplayContents.size(); 6764 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6765 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 6766 final int numWindows = windows.size(); 6767 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 6768 final WindowState w = windows.get(winNdx); 6769 if (System.identityHashCode(w) == hashCode) { 6770 return w; 6771 } 6772 } 6773 } 6774 } 6775 6776 return null; 6777 } 6778 6779 /* 6780 * Instruct the Activity Manager to fetch the current configuration and broadcast 6781 * that to config-changed listeners if appropriate. 6782 */ 6783 void sendNewConfiguration() { 6784 try { 6785 mActivityManager.updateConfiguration(null); 6786 } catch (RemoteException e) { 6787 } 6788 } 6789 6790 public Configuration computeNewConfiguration() { 6791 synchronized (mWindowMap) { 6792 Configuration config = computeNewConfigurationLocked(); 6793 if (config == null && mWaitingForConfig) { 6794 // Nothing changed but we are waiting for something... stop that! 6795 mWaitingForConfig = false; 6796 mLastFinishedFreezeSource = "new-config"; 6797 performLayoutAndPlaceSurfacesLocked(); 6798 } 6799 return config; 6800 } 6801 } 6802 6803 Configuration computeNewConfigurationLocked() { 6804 Configuration config = new Configuration(); 6805 config.fontScale = 0; 6806 if (!computeScreenConfigurationLocked(config)) { 6807 return null; 6808 } 6809 return config; 6810 } 6811 6812 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) { 6813 // TODO: Multidisplay: for now only use with default display. 6814 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation); 6815 if (width < displayInfo.smallestNominalAppWidth) { 6816 displayInfo.smallestNominalAppWidth = width; 6817 } 6818 if (width > displayInfo.largestNominalAppWidth) { 6819 displayInfo.largestNominalAppWidth = width; 6820 } 6821 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation); 6822 if (height < displayInfo.smallestNominalAppHeight) { 6823 displayInfo.smallestNominalAppHeight = height; 6824 } 6825 if (height > displayInfo.largestNominalAppHeight) { 6826 displayInfo.largestNominalAppHeight = height; 6827 } 6828 } 6829 6830 private int reduceConfigLayout(int curLayout, int rotation, float density, 6831 int dw, int dh) { 6832 // TODO: Multidisplay: for now only use with default display. 6833 // Get the app screen size at this rotation. 6834 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6835 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6836 6837 // Compute the screen layout size class for this rotation. 6838 int longSize = w; 6839 int shortSize = h; 6840 if (longSize < shortSize) { 6841 int tmp = longSize; 6842 longSize = shortSize; 6843 shortSize = tmp; 6844 } 6845 longSize = (int)(longSize/density); 6846 shortSize = (int)(shortSize/density); 6847 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 6848 } 6849 6850 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 6851 int dw, int dh, float density, Configuration outConfig) { 6852 // TODO: Multidisplay: for now only use with default display. 6853 6854 // We need to determine the smallest width that will occur under normal 6855 // operation. To this, start with the base screen size and compute the 6856 // width under the different possible rotations. We need to un-rotate 6857 // the current screen dimensions before doing this. 6858 int unrotDw, unrotDh; 6859 if (rotated) { 6860 unrotDw = dh; 6861 unrotDh = dw; 6862 } else { 6863 unrotDw = dw; 6864 unrotDh = dh; 6865 } 6866 displayInfo.smallestNominalAppWidth = 1<<30; 6867 displayInfo.smallestNominalAppHeight = 1<<30; 6868 displayInfo.largestNominalAppWidth = 0; 6869 displayInfo.largestNominalAppHeight = 0; 6870 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh); 6871 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw); 6872 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh); 6873 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw); 6874 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 6875 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh); 6876 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw); 6877 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); 6878 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); 6879 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 6880 outConfig.screenLayout = sl; 6881 } 6882 6883 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, 6884 int dw, int dh) { 6885 // TODO: Multidisplay: for now only use with default display. 6886 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6887 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6888 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 6889 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 6890 if (curSize == 0 || size < curSize) { 6891 curSize = size; 6892 } 6893 return curSize; 6894 } 6895 6896 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) { 6897 // TODO: Multidisplay: for now only use with default display. 6898 mTmpDisplayMetrics.setTo(dm); 6899 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 6900 final int unrotDw, unrotDh; 6901 if (rotated) { 6902 unrotDw = dh; 6903 unrotDh = dw; 6904 } else { 6905 unrotDw = dw; 6906 unrotDh = dh; 6907 } 6908 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh); 6909 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw); 6910 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh); 6911 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw); 6912 return sw; 6913 } 6914 6915 boolean computeScreenConfigurationLocked(Configuration config) { 6916 if (!mDisplayReady) { 6917 return false; 6918 } 6919 6920 // TODO(multidisplay): For now, apply Configuration to main screen only. 6921 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6922 6923 // Use the effective "visual" dimensions based on current rotation 6924 final boolean rotated = (mRotation == Surface.ROTATION_90 6925 || mRotation == Surface.ROTATION_270); 6926 final int realdw = rotated ? 6927 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; 6928 final int realdh = rotated ? 6929 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; 6930 int dw = realdw; 6931 int dh = realdh; 6932 6933 if (mAltOrientation) { 6934 if (realdw > realdh) { 6935 // Turn landscape into portrait. 6936 int maxw = (int)(realdh/1.3f); 6937 if (maxw < realdw) { 6938 dw = maxw; 6939 } 6940 } else { 6941 // Turn portrait into landscape. 6942 int maxh = (int)(realdw/1.3f); 6943 if (maxh < realdh) { 6944 dh = maxh; 6945 } 6946 } 6947 } 6948 6949 if (config != null) { 6950 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : 6951 Configuration.ORIENTATION_LANDSCAPE; 6952 } 6953 6954 // Update application display metrics. 6955 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); 6956 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); 6957 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6958 synchronized(displayContent.mDisplaySizeLock) { 6959 displayInfo.rotation = mRotation; 6960 displayInfo.logicalWidth = dw; 6961 displayInfo.logicalHeight = dh; 6962 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; 6963 displayInfo.appWidth = appWidth; 6964 displayInfo.appHeight = appHeight; 6965 displayInfo.getLogicalMetrics(mRealDisplayMetrics, 6966 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 6967 displayInfo.getAppMetrics(mDisplayMetrics); 6968 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 6969 displayContent.getDisplayId(), displayInfo); 6970 } 6971 if (false) { 6972 Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); 6973 } 6974 6975 final DisplayMetrics dm = mDisplayMetrics; 6976 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, 6977 mCompatDisplayMetrics); 6978 6979 if (config != null) { 6980 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) 6981 / dm.density); 6982 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) 6983 / dm.density); 6984 computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config); 6985 6986 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 6987 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 6988 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); 6989 config.densityDpi = displayContent.mBaseDisplayDensity; 6990 6991 // Update the configuration based on available input devices, lid switch, 6992 // and platform configuration. 6993 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6994 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6995 config.navigation = Configuration.NAVIGATION_NONAV; 6996 6997 int keyboardPresence = 0; 6998 int navigationPresence = 0; 6999 final InputDevice[] devices = mInputManager.getInputDevices(); 7000 final int len = devices.length; 7001 for (int i = 0; i < len; i++) { 7002 InputDevice device = devices[i]; 7003 if (!device.isVirtual()) { 7004 final int sources = device.getSources(); 7005 final int presenceFlag = device.isExternal() ? 7006 WindowManagerPolicy.PRESENCE_EXTERNAL : 7007 WindowManagerPolicy.PRESENCE_INTERNAL; 7008 7009 if (mIsTouchDevice) { 7010 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 7011 InputDevice.SOURCE_TOUCHSCREEN) { 7012 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 7013 } 7014 } else { 7015 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 7016 } 7017 7018 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 7019 config.navigation = Configuration.NAVIGATION_TRACKBALL; 7020 navigationPresence |= presenceFlag; 7021 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 7022 && config.navigation == Configuration.NAVIGATION_NONAV) { 7023 config.navigation = Configuration.NAVIGATION_DPAD; 7024 navigationPresence |= presenceFlag; 7025 } 7026 7027 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 7028 config.keyboard = Configuration.KEYBOARD_QWERTY; 7029 keyboardPresence |= presenceFlag; 7030 } 7031 } 7032 } 7033 7034 // Determine whether a hard keyboard is available and enabled. 7035 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 7036 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 7037 mHardKeyboardAvailable = hardKeyboardAvailable; 7038 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 7039 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 7040 } 7041 if (mShowImeWithHardKeyboard) { 7042 config.keyboard = Configuration.KEYBOARD_NOKEYS; 7043 } 7044 7045 // Let the policy update hidden states. 7046 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 7047 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 7048 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 7049 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 7050 } 7051 7052 return true; 7053 } 7054 7055 public boolean isHardKeyboardAvailable() { 7056 synchronized (mWindowMap) { 7057 return mHardKeyboardAvailable; 7058 } 7059 } 7060 7061 public void updateShowImeWithHardKeyboard() { 7062 boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser( 7063 mContext.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0, 7064 mCurrentUserId) == 1; 7065 synchronized (mWindowMap) { 7066 mShowImeWithHardKeyboard = showImeWithHardKeyboard; 7067 } 7068 } 7069 7070 public void setOnHardKeyboardStatusChangeListener( 7071 OnHardKeyboardStatusChangeListener listener) { 7072 synchronized (mWindowMap) { 7073 mHardKeyboardStatusChangeListener = listener; 7074 } 7075 } 7076 7077 void notifyHardKeyboardStatusChange() { 7078 final boolean available; 7079 final OnHardKeyboardStatusChangeListener listener; 7080 synchronized (mWindowMap) { 7081 listener = mHardKeyboardStatusChangeListener; 7082 available = mHardKeyboardAvailable; 7083 } 7084 if (listener != null) { 7085 listener.onHardKeyboardStatusChange(available); 7086 } 7087 } 7088 7089 // ------------------------------------------------------------- 7090 // Drag and drop 7091 // ------------------------------------------------------------- 7092 7093 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 7094 int flags, int width, int height, Surface outSurface) { 7095 if (DEBUG_DRAG) { 7096 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 7097 + " flags=" + Integer.toHexString(flags) + " win=" + window 7098 + " asbinder=" + window.asBinder()); 7099 } 7100 7101 final int callerPid = Binder.getCallingPid(); 7102 final long origId = Binder.clearCallingIdentity(); 7103 IBinder token = null; 7104 7105 try { 7106 synchronized (mWindowMap) { 7107 try { 7108 if (mDragState == null) { 7109 // TODO(multi-display): support other displays 7110 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7111 final Display display = displayContent.getDisplay(); 7112 SurfaceControl surface = new SurfaceControl(session, "drag surface", 7113 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 7114 surface.setLayerStack(display.getLayerStack()); 7115 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 7116 + surface + ": CREATE"); 7117 outSurface.copyFrom(surface); 7118 final IBinder winBinder = window.asBinder(); 7119 token = new Binder(); 7120 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 7121 token = mDragState.mToken = new Binder(); 7122 7123 // 5 second timeout for this window to actually begin the drag 7124 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 7125 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 7126 mH.sendMessageDelayed(msg, 5000); 7127 } else { 7128 Slog.w(TAG, "Drag already in progress"); 7129 } 7130 } catch (OutOfResourcesException e) { 7131 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 7132 if (mDragState != null) { 7133 mDragState.reset(); 7134 mDragState = null; 7135 } 7136 } 7137 } 7138 } finally { 7139 Binder.restoreCallingIdentity(origId); 7140 } 7141 7142 return token; 7143 } 7144 7145 // ------------------------------------------------------------- 7146 // Input Events and Focus Management 7147 // ------------------------------------------------------------- 7148 7149 final InputMonitor mInputMonitor = new InputMonitor(this); 7150 private boolean mEventDispatchingEnabled; 7151 7152 @Override 7153 public void pauseKeyDispatching(IBinder _token) { 7154 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7155 "pauseKeyDispatching()")) { 7156 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7157 } 7158 7159 synchronized (mWindowMap) { 7160 WindowToken token = mTokenMap.get(_token); 7161 if (token != null) { 7162 mInputMonitor.pauseDispatchingLw(token); 7163 } 7164 } 7165 } 7166 7167 @Override 7168 public void resumeKeyDispatching(IBinder _token) { 7169 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7170 "resumeKeyDispatching()")) { 7171 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7172 } 7173 7174 synchronized (mWindowMap) { 7175 WindowToken token = mTokenMap.get(_token); 7176 if (token != null) { 7177 mInputMonitor.resumeDispatchingLw(token); 7178 } 7179 } 7180 } 7181 7182 @Override 7183 public void setEventDispatching(boolean enabled) { 7184 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7185 "setEventDispatching()")) { 7186 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7187 } 7188 7189 synchronized (mWindowMap) { 7190 mEventDispatchingEnabled = enabled; 7191 if (mDisplayEnabled) { 7192 mInputMonitor.setEventDispatchingLw(enabled); 7193 } 7194 } 7195 } 7196 7197 private WindowState getFocusedWindow() { 7198 synchronized (mWindowMap) { 7199 return getFocusedWindowLocked(); 7200 } 7201 } 7202 7203 private WindowState getFocusedWindowLocked() { 7204 return mCurrentFocus; 7205 } 7206 7207 public boolean detectSafeMode() { 7208 if (!mInputMonitor.waitForInputDevicesReady( 7209 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 7210 Slog.w(TAG, "Devices still not ready after waiting " 7211 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 7212 + " milliseconds before attempting to detect safe mode."); 7213 } 7214 7215 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7216 KeyEvent.KEYCODE_MENU); 7217 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 7218 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 7219 KeyEvent.KEYCODE_DPAD_CENTER); 7220 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 7221 InputManagerService.BTN_MOUSE); 7222 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7223 KeyEvent.KEYCODE_VOLUME_DOWN); 7224 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 7225 || volumeDownState > 0; 7226 try { 7227 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 7228 mSafeMode = true; 7229 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 7230 } 7231 } catch (IllegalArgumentException e) { 7232 } 7233 if (mSafeMode) { 7234 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 7235 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 7236 } else { 7237 Log.i(TAG, "SAFE MODE not enabled"); 7238 } 7239 mPolicy.setSafeMode(mSafeMode); 7240 return mSafeMode; 7241 } 7242 7243 public void displayReady() { 7244 displayReady(Display.DEFAULT_DISPLAY); 7245 7246 synchronized(mWindowMap) { 7247 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7248 readForcedDisplaySizeAndDensityLocked(displayContent); 7249 mDisplayReady = true; 7250 } 7251 7252 try { 7253 mActivityManager.updateConfiguration(null); 7254 } catch (RemoteException e) { 7255 } 7256 7257 synchronized(mWindowMap) { 7258 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 7259 PackageManager.FEATURE_TOUCHSCREEN); 7260 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 7261 } 7262 7263 try { 7264 mActivityManager.updateConfiguration(null); 7265 } catch (RemoteException e) { 7266 } 7267 } 7268 7269 private void displayReady(int displayId) { 7270 synchronized(mWindowMap) { 7271 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7272 if (displayContent != null) { 7273 mAnimator.addDisplayLocked(displayId); 7274 synchronized(displayContent.mDisplaySizeLock) { 7275 // Bootstrap the default logical display from the display manager. 7276 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7277 DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId); 7278 if (newDisplayInfo != null) { 7279 displayInfo.copyFrom(newDisplayInfo); 7280 } 7281 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; 7282 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; 7283 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; 7284 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; 7285 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; 7286 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; 7287 displayContent.mBaseDisplayRect.set(0, 0, 7288 displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight); 7289 } 7290 } 7291 } 7292 } 7293 7294 public void systemReady() { 7295 mPolicy.systemReady(); 7296 } 7297 7298 // ------------------------------------------------------------- 7299 // Async Handler 7300 // ------------------------------------------------------------- 7301 7302 final class H extends Handler { 7303 public static final int REPORT_FOCUS_CHANGE = 2; 7304 public static final int REPORT_LOSING_FOCUS = 3; 7305 public static final int DO_TRAVERSAL = 4; 7306 public static final int ADD_STARTING = 5; 7307 public static final int REMOVE_STARTING = 6; 7308 public static final int FINISHED_STARTING = 7; 7309 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 7310 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 7311 public static final int WINDOW_FREEZE_TIMEOUT = 11; 7312 7313 public static final int APP_TRANSITION_TIMEOUT = 13; 7314 public static final int PERSIST_ANIMATION_SCALE = 14; 7315 public static final int FORCE_GC = 15; 7316 public static final int ENABLE_SCREEN = 16; 7317 public static final int APP_FREEZE_TIMEOUT = 17; 7318 public static final int SEND_NEW_CONFIGURATION = 18; 7319 public static final int REPORT_WINDOWS_CHANGE = 19; 7320 public static final int DRAG_START_TIMEOUT = 20; 7321 public static final int DRAG_END_TIMEOUT = 21; 7322 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 7323 public static final int BOOT_TIMEOUT = 23; 7324 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 7325 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 7326 public static final int DO_ANIMATION_CALLBACK = 26; 7327 7328 public static final int DO_DISPLAY_ADDED = 27; 7329 public static final int DO_DISPLAY_REMOVED = 28; 7330 public static final int DO_DISPLAY_CHANGED = 29; 7331 7332 public static final int CLIENT_FREEZE_TIMEOUT = 30; 7333 public static final int TAP_OUTSIDE_STACK = 31; 7334 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 7335 7336 public static final int ALL_WINDOWS_DRAWN = 33; 7337 7338 public static final int NEW_ANIMATOR_SCALE = 34; 7339 7340 public static final int SHOW_DISPLAY_MASK = 35; 7341 7342 @Override 7343 public void handleMessage(Message msg) { 7344 if (DEBUG_WINDOW_TRACE) { 7345 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 7346 } 7347 switch (msg.what) { 7348 case REPORT_FOCUS_CHANGE: { 7349 WindowState lastFocus; 7350 WindowState newFocus; 7351 7352 synchronized(mWindowMap) { 7353 lastFocus = mLastFocus; 7354 newFocus = mCurrentFocus; 7355 if (lastFocus == newFocus) { 7356 // Focus is not changing, so nothing to do. 7357 return; 7358 } 7359 mLastFocus = newFocus; 7360 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus + 7361 " to " + newFocus); 7362 if (newFocus != null && lastFocus != null 7363 && !newFocus.isDisplayedLw()) { 7364 //Slog.i(TAG, "Delaying loss of focus..."); 7365 mLosingFocus.add(lastFocus); 7366 lastFocus = null; 7367 } 7368 } 7369 7370 //System.out.println("Changing focus from " + lastFocus 7371 // + " to " + newFocus); 7372 if (newFocus != null) { 7373 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus); 7374 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 7375 notifyFocusChanged(); 7376 } 7377 7378 if (lastFocus != null) { 7379 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus); 7380 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 7381 } 7382 } break; 7383 7384 case REPORT_LOSING_FOCUS: { 7385 ArrayList<WindowState> losers; 7386 7387 synchronized(mWindowMap) { 7388 losers = mLosingFocus; 7389 mLosingFocus = new ArrayList<WindowState>(); 7390 } 7391 7392 final int N = losers.size(); 7393 for (int i=0; i<N; i++) { 7394 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " + 7395 losers.get(i)); 7396 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 7397 } 7398 } break; 7399 7400 case DO_TRAVERSAL: { 7401 synchronized(mWindowMap) { 7402 mTraversalScheduled = false; 7403 performLayoutAndPlaceSurfacesLocked(); 7404 } 7405 } break; 7406 7407 case ADD_STARTING: { 7408 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7409 final StartingData sd = wtoken.startingData; 7410 7411 if (sd == null) { 7412 // Animation has been canceled... do nothing. 7413 return; 7414 } 7415 7416 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 7417 + wtoken + ": pkg=" + sd.pkg); 7418 7419 View view = null; 7420 try { 7421 view = mPolicy.addStartingWindow( 7422 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 7423 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags); 7424 } catch (Exception e) { 7425 Slog.w(TAG, "Exception when adding starting window", e); 7426 } 7427 7428 if (view != null) { 7429 boolean abort = false; 7430 7431 synchronized(mWindowMap) { 7432 if (wtoken.removed || wtoken.startingData == null) { 7433 // If the window was successfully added, then 7434 // we need to remove it. 7435 if (wtoken.startingWindow != null) { 7436 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7437 "Aborted starting " + wtoken 7438 + ": removed=" + wtoken.removed 7439 + " startingData=" + wtoken.startingData); 7440 wtoken.startingWindow = null; 7441 wtoken.startingData = null; 7442 abort = true; 7443 } 7444 } else { 7445 wtoken.startingView = view; 7446 } 7447 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7448 "Added starting " + wtoken 7449 + ": startingWindow=" 7450 + wtoken.startingWindow + " startingView=" 7451 + wtoken.startingView); 7452 } 7453 7454 if (abort) { 7455 try { 7456 mPolicy.removeStartingWindow(wtoken.token, view); 7457 } catch (Exception e) { 7458 Slog.w(TAG, "Exception when removing starting window", e); 7459 } 7460 } 7461 } 7462 } break; 7463 7464 case REMOVE_STARTING: { 7465 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7466 IBinder token = null; 7467 View view = null; 7468 synchronized (mWindowMap) { 7469 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7470 + wtoken + ": startingWindow=" 7471 + wtoken.startingWindow + " startingView=" 7472 + wtoken.startingView); 7473 if (wtoken.startingWindow != null) { 7474 view = wtoken.startingView; 7475 token = wtoken.token; 7476 wtoken.startingData = null; 7477 wtoken.startingView = null; 7478 wtoken.startingWindow = null; 7479 wtoken.startingDisplayed = false; 7480 } 7481 } 7482 if (view != null) { 7483 try { 7484 mPolicy.removeStartingWindow(token, view); 7485 } catch (Exception e) { 7486 Slog.w(TAG, "Exception when removing starting window", e); 7487 } 7488 } 7489 } break; 7490 7491 case FINISHED_STARTING: { 7492 IBinder token = null; 7493 View view = null; 7494 while (true) { 7495 synchronized (mWindowMap) { 7496 final int N = mFinishedStarting.size(); 7497 if (N <= 0) { 7498 break; 7499 } 7500 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7501 7502 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7503 "Finished starting " + wtoken 7504 + ": startingWindow=" + wtoken.startingWindow 7505 + " startingView=" + wtoken.startingView); 7506 7507 if (wtoken.startingWindow == null) { 7508 continue; 7509 } 7510 7511 view = wtoken.startingView; 7512 token = wtoken.token; 7513 wtoken.startingData = null; 7514 wtoken.startingView = null; 7515 wtoken.startingWindow = null; 7516 wtoken.startingDisplayed = false; 7517 } 7518 7519 try { 7520 mPolicy.removeStartingWindow(token, view); 7521 } catch (Exception e) { 7522 Slog.w(TAG, "Exception when removing starting window", e); 7523 } 7524 } 7525 } break; 7526 7527 case REPORT_APPLICATION_TOKEN_DRAWN: { 7528 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7529 7530 try { 7531 if (DEBUG_VISIBILITY) Slog.v( 7532 TAG, "Reporting drawn in " + wtoken); 7533 wtoken.appToken.windowsDrawn(); 7534 } catch (RemoteException ex) { 7535 } 7536 } break; 7537 7538 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7539 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7540 7541 boolean nowVisible = msg.arg1 != 0; 7542 boolean nowGone = msg.arg2 != 0; 7543 7544 try { 7545 if (DEBUG_VISIBILITY) Slog.v( 7546 TAG, "Reporting visible in " + wtoken 7547 + " visible=" + nowVisible 7548 + " gone=" + nowGone); 7549 if (nowVisible) { 7550 wtoken.appToken.windowsVisible(); 7551 } else { 7552 wtoken.appToken.windowsGone(); 7553 } 7554 } catch (RemoteException ex) { 7555 } 7556 } break; 7557 7558 case WINDOW_FREEZE_TIMEOUT: { 7559 // TODO(multidisplay): Can non-default displays rotate? 7560 synchronized (mWindowMap) { 7561 Slog.w(TAG, "Window freeze timeout expired."); 7562 final WindowList windows = getDefaultWindowListLocked(); 7563 int i = windows.size(); 7564 while (i > 0) { 7565 i--; 7566 WindowState w = windows.get(i); 7567 if (w.mOrientationChanging) { 7568 w.mOrientationChanging = false; 7569 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 7570 - mDisplayFreezeTime); 7571 Slog.w(TAG, "Force clearing orientation change: " + w); 7572 } 7573 } 7574 performLayoutAndPlaceSurfacesLocked(); 7575 } 7576 break; 7577 } 7578 7579 case APP_TRANSITION_TIMEOUT: { 7580 synchronized (mWindowMap) { 7581 if (mAppTransition.isTransitionSet()) { 7582 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT"); 7583 mAppTransition.setTimeout(); 7584 performLayoutAndPlaceSurfacesLocked(); 7585 } 7586 } 7587 break; 7588 } 7589 7590 case PERSIST_ANIMATION_SCALE: { 7591 Settings.Global.putFloat(mContext.getContentResolver(), 7592 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 7593 Settings.Global.putFloat(mContext.getContentResolver(), 7594 Settings.Global.TRANSITION_ANIMATION_SCALE, 7595 mTransitionAnimationScaleSetting); 7596 Settings.Global.putFloat(mContext.getContentResolver(), 7597 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting); 7598 break; 7599 } 7600 7601 case FORCE_GC: { 7602 synchronized (mWindowMap) { 7603 // Since we're holding both mWindowMap and mAnimator we don't need to 7604 // hold mAnimator.mLayoutToAnim. 7605 if (mAnimator.mAnimating || mAnimationScheduled) { 7606 // If we are animating, don't do the gc now but 7607 // delay a bit so we don't interrupt the animation. 7608 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 7609 return; 7610 } 7611 // If we are currently rotating the display, it will 7612 // schedule a new message when done. 7613 if (mDisplayFrozen) { 7614 return; 7615 } 7616 } 7617 Runtime.getRuntime().gc(); 7618 break; 7619 } 7620 7621 case ENABLE_SCREEN: { 7622 performEnableScreen(); 7623 break; 7624 } 7625 7626 case APP_FREEZE_TIMEOUT: { 7627 synchronized (mWindowMap) { 7628 Slog.w(TAG, "App freeze timeout expired."); 7629 final int numStacks = mStackIdToStack.size(); 7630 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 7631 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 7632 final ArrayList<Task> tasks = stack.getTasks(); 7633 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 7634 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 7635 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 7636 AppWindowToken tok = tokens.get(tokenNdx); 7637 if (tok.mAppAnimator.freezingScreen) { 7638 Slog.w(TAG, "Force clearing freeze: " + tok); 7639 unsetAppFreezingScreenLocked(tok, true, true); 7640 } 7641 } 7642 } 7643 } 7644 } 7645 break; 7646 } 7647 7648 case CLIENT_FREEZE_TIMEOUT: { 7649 synchronized (mWindowMap) { 7650 if (mClientFreezingScreen) { 7651 mClientFreezingScreen = false; 7652 mLastFinishedFreezeSource = "client-timeout"; 7653 stopFreezingDisplayLocked(); 7654 } 7655 } 7656 break; 7657 } 7658 7659 case SEND_NEW_CONFIGURATION: { 7660 removeMessages(SEND_NEW_CONFIGURATION); 7661 sendNewConfiguration(); 7662 break; 7663 } 7664 7665 case REPORT_WINDOWS_CHANGE: { 7666 if (mWindowsChanged) { 7667 synchronized (mWindowMap) { 7668 mWindowsChanged = false; 7669 } 7670 notifyWindowsChanged(); 7671 } 7672 break; 7673 } 7674 7675 case DRAG_START_TIMEOUT: { 7676 IBinder win = (IBinder)msg.obj; 7677 if (DEBUG_DRAG) { 7678 Slog.w(TAG, "Timeout starting drag by win " + win); 7679 } 7680 synchronized (mWindowMap) { 7681 // !!! TODO: ANR the app that has failed to start the drag in time 7682 if (mDragState != null) { 7683 mDragState.unregister(); 7684 mInputMonitor.updateInputWindowsLw(true /*force*/); 7685 mDragState.reset(); 7686 mDragState = null; 7687 } 7688 } 7689 break; 7690 } 7691 7692 case DRAG_END_TIMEOUT: { 7693 IBinder win = (IBinder)msg.obj; 7694 if (DEBUG_DRAG) { 7695 Slog.w(TAG, "Timeout ending drag to win " + win); 7696 } 7697 synchronized (mWindowMap) { 7698 // !!! TODO: ANR the drag-receiving app 7699 if (mDragState != null) { 7700 mDragState.mDragResult = false; 7701 mDragState.endDragLw(); 7702 } 7703 } 7704 break; 7705 } 7706 7707 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7708 notifyHardKeyboardStatusChange(); 7709 break; 7710 } 7711 7712 case BOOT_TIMEOUT: { 7713 performBootTimeout(); 7714 break; 7715 } 7716 7717 case WAITING_FOR_DRAWN_TIMEOUT: { 7718 Runnable callback = null; 7719 synchronized (mWindowMap) { 7720 Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn); 7721 mWaitingForDrawn.clear(); 7722 callback = mWaitingForDrawnCallback; 7723 mWaitingForDrawnCallback = null; 7724 } 7725 if (callback != null) { 7726 callback.run(); 7727 } 7728 break; 7729 } 7730 7731 case SHOW_STRICT_MODE_VIOLATION: { 7732 showStrictModeViolation(msg.arg1, msg.arg2); 7733 break; 7734 } 7735 7736 case SHOW_DISPLAY_MASK: { 7737 showCircularMask(); 7738 break; 7739 } 7740 7741 case DO_ANIMATION_CALLBACK: { 7742 try { 7743 ((IRemoteCallback)msg.obj).sendResult(null); 7744 } catch (RemoteException e) { 7745 } 7746 break; 7747 } 7748 7749 case DO_DISPLAY_ADDED: 7750 handleDisplayAdded(msg.arg1); 7751 break; 7752 7753 case DO_DISPLAY_REMOVED: 7754 synchronized (mWindowMap) { 7755 handleDisplayRemovedLocked(msg.arg1); 7756 } 7757 break; 7758 7759 case DO_DISPLAY_CHANGED: 7760 synchronized (mWindowMap) { 7761 handleDisplayChangedLocked(msg.arg1); 7762 } 7763 break; 7764 7765 case TAP_OUTSIDE_STACK: { 7766 int stackId; 7767 synchronized (mWindowMap) { 7768 stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2); 7769 } 7770 if (stackId >= 0) { 7771 try { 7772 mActivityManager.setFocusedStack(stackId); 7773 } catch (RemoteException e) { 7774 } 7775 } 7776 } 7777 break; 7778 case NOTIFY_ACTIVITY_DRAWN: 7779 try { 7780 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 7781 } catch (RemoteException e) { 7782 } 7783 break; 7784 case ALL_WINDOWS_DRAWN: { 7785 Runnable callback; 7786 synchronized (mWindowMap) { 7787 callback = mWaitingForDrawnCallback; 7788 mWaitingForDrawnCallback = null; 7789 } 7790 if (callback != null) { 7791 callback.run(); 7792 } 7793 } 7794 case NEW_ANIMATOR_SCALE: { 7795 float scale = getCurrentAnimatorScale(); 7796 ValueAnimator.setDurationScale(scale); 7797 Session session = (Session)msg.obj; 7798 if (session != null) { 7799 try { 7800 session.mCallback.onAnimatorScaleChanged(scale); 7801 } catch (RemoteException e) { 7802 } 7803 } else { 7804 ArrayList<IWindowSessionCallback> callbacks 7805 = new ArrayList<IWindowSessionCallback>(); 7806 synchronized (mWindowMap) { 7807 for (int i=0; i<mSessions.size(); i++) { 7808 callbacks.add(mSessions.valueAt(i).mCallback); 7809 } 7810 7811 } 7812 for (int i=0; i<callbacks.size(); i++) { 7813 try { 7814 callbacks.get(i).onAnimatorScaleChanged(scale); 7815 } catch (RemoteException e) { 7816 } 7817 } 7818 } 7819 } 7820 break; 7821 } 7822 if (DEBUG_WINDOW_TRACE) { 7823 Slog.v(TAG, "handleMessage: exit"); 7824 } 7825 } 7826 } 7827 7828 // ------------------------------------------------------------- 7829 // IWindowManager API 7830 // ------------------------------------------------------------- 7831 7832 @Override 7833 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, 7834 IInputContext inputContext) { 7835 if (client == null) throw new IllegalArgumentException("null client"); 7836 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7837 Session session = new Session(this, callback, client, inputContext); 7838 return session; 7839 } 7840 7841 @Override 7842 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7843 synchronized (mWindowMap) { 7844 // The focus for the client is the window immediately below 7845 // where we would place the input method window. 7846 int idx = findDesiredInputMethodWindowIndexLocked(false); 7847 if (idx > 0) { 7848 // TODO(multidisplay): IMEs are only supported on the default display. 7849 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 7850 if (DEBUG_INPUT_METHOD) { 7851 Slog.i(TAG, "Desired input method target: " + imFocus); 7852 Slog.i(TAG, "Current focus: " + mCurrentFocus); 7853 Slog.i(TAG, "Last focus: " + mLastFocus); 7854 } 7855 if (imFocus != null) { 7856 // This may be a starting window, in which case we still want 7857 // to count it as okay. 7858 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7859 && imFocus.mAppToken != null) { 7860 // The client has definitely started, so it really should 7861 // have a window in this app token. Let's look for it. 7862 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7863 WindowState w = imFocus.mAppToken.windows.get(i); 7864 if (w != imFocus) { 7865 Log.i(TAG, "Switching to real app window: " + w); 7866 imFocus = w; 7867 break; 7868 } 7869 } 7870 } 7871 if (DEBUG_INPUT_METHOD) { 7872 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7873 if (imFocus.mSession.mClient != null) { 7874 Slog.i(TAG, "IM target client binder: " 7875 + imFocus.mSession.mClient.asBinder()); 7876 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 7877 } 7878 } 7879 if (imFocus.mSession.mClient != null && 7880 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7881 return true; 7882 } 7883 } 7884 } 7885 7886 // Okay, how about this... what is the current focus? 7887 // It seems in some cases we may not have moved the IM 7888 // target window, such as when it was in a pop-up window, 7889 // so let's also look at the current focus. (An example: 7890 // go to Gmail, start searching so the keyboard goes up, 7891 // press home. Sometimes the IME won't go down.) 7892 // Would be nice to fix this more correctly, but it's 7893 // way at the end of a release, and this should be good enough. 7894 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 7895 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7896 return true; 7897 } 7898 } 7899 return false; 7900 } 7901 7902 @Override 7903 public void getInitialDisplaySize(int displayId, Point size) { 7904 synchronized (mWindowMap) { 7905 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7906 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7907 synchronized(displayContent.mDisplaySizeLock) { 7908 size.x = displayContent.mInitialDisplayWidth; 7909 size.y = displayContent.mInitialDisplayHeight; 7910 } 7911 } 7912 } 7913 } 7914 7915 @Override 7916 public void getBaseDisplaySize(int displayId, Point size) { 7917 synchronized (mWindowMap) { 7918 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7919 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7920 synchronized(displayContent.mDisplaySizeLock) { 7921 size.x = displayContent.mBaseDisplayWidth; 7922 size.y = displayContent.mBaseDisplayHeight; 7923 } 7924 } 7925 } 7926 } 7927 7928 @Override 7929 public void setForcedDisplaySize(int displayId, int width, int height) { 7930 if (mContext.checkCallingOrSelfPermission( 7931 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7932 PackageManager.PERMISSION_GRANTED) { 7933 throw new SecurityException("Must hold permission " + 7934 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7935 } 7936 if (displayId != Display.DEFAULT_DISPLAY) { 7937 throw new IllegalArgumentException("Can only set the default display"); 7938 } 7939 final long ident = Binder.clearCallingIdentity(); 7940 try { 7941 synchronized(mWindowMap) { 7942 // Set some sort of reasonable bounds on the size of the display that we 7943 // will try to emulate. 7944 final int MIN_WIDTH = 200; 7945 final int MIN_HEIGHT = 200; 7946 final int MAX_SCALE = 2; 7947 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7948 if (displayContent != null) { 7949 width = Math.min(Math.max(width, MIN_WIDTH), 7950 displayContent.mInitialDisplayWidth * MAX_SCALE); 7951 height = Math.min(Math.max(height, MIN_HEIGHT), 7952 displayContent.mInitialDisplayHeight * MAX_SCALE); 7953 setForcedDisplaySizeLocked(displayContent, width, height); 7954 Settings.Global.putString(mContext.getContentResolver(), 7955 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 7956 } 7957 } 7958 } finally { 7959 Binder.restoreCallingIdentity(ident); 7960 } 7961 } 7962 7963 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 7964 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 7965 Settings.Global.DISPLAY_SIZE_FORCED); 7966 if (sizeStr == null || sizeStr.length() == 0) { 7967 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 7968 } 7969 if (sizeStr != null && sizeStr.length() > 0) { 7970 final int pos = sizeStr.indexOf(','); 7971 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 7972 int width, height; 7973 try { 7974 width = Integer.parseInt(sizeStr.substring(0, pos)); 7975 height = Integer.parseInt(sizeStr.substring(pos+1)); 7976 synchronized(displayContent.mDisplaySizeLock) { 7977 if (displayContent.mBaseDisplayWidth != width 7978 || displayContent.mBaseDisplayHeight != height) { 7979 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 7980 displayContent.mBaseDisplayWidth = width; 7981 displayContent.mBaseDisplayHeight = height; 7982 } 7983 } 7984 } catch (NumberFormatException ex) { 7985 } 7986 } 7987 } 7988 String densityStr = Settings.Global.getString(mContext.getContentResolver(), 7989 Settings.Global.DISPLAY_DENSITY_FORCED); 7990 if (densityStr == null || densityStr.length() == 0) { 7991 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 7992 } 7993 if (densityStr != null && densityStr.length() > 0) { 7994 int density; 7995 try { 7996 density = Integer.parseInt(densityStr); 7997 synchronized(displayContent.mDisplaySizeLock) { 7998 if (displayContent.mBaseDisplayDensity != density) { 7999 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 8000 displayContent.mBaseDisplayDensity = density; 8001 } 8002 } 8003 } catch (NumberFormatException ex) { 8004 } 8005 } 8006 } 8007 8008 // displayContent must not be null 8009 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 8010 Slog.i(TAG, "Using new display size: " + width + "x" + height); 8011 8012 synchronized(displayContent.mDisplaySizeLock) { 8013 displayContent.mBaseDisplayWidth = width; 8014 displayContent.mBaseDisplayHeight = height; 8015 } 8016 reconfigureDisplayLocked(displayContent); 8017 } 8018 8019 @Override 8020 public void clearForcedDisplaySize(int displayId) { 8021 if (mContext.checkCallingOrSelfPermission( 8022 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8023 PackageManager.PERMISSION_GRANTED) { 8024 throw new SecurityException("Must hold permission " + 8025 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8026 } 8027 if (displayId != Display.DEFAULT_DISPLAY) { 8028 throw new IllegalArgumentException("Can only set the default display"); 8029 } 8030 final long ident = Binder.clearCallingIdentity(); 8031 try { 8032 synchronized(mWindowMap) { 8033 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8034 if (displayContent != null) { 8035 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 8036 displayContent.mInitialDisplayHeight); 8037 Settings.Global.putString(mContext.getContentResolver(), 8038 Settings.Global.DISPLAY_SIZE_FORCED, ""); 8039 } 8040 } 8041 } finally { 8042 Binder.restoreCallingIdentity(ident); 8043 } 8044 } 8045 8046 @Override 8047 public int getInitialDisplayDensity(int displayId) { 8048 synchronized (mWindowMap) { 8049 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8050 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8051 synchronized(displayContent.mDisplaySizeLock) { 8052 return displayContent.mInitialDisplayDensity; 8053 } 8054 } 8055 } 8056 return -1; 8057 } 8058 8059 @Override 8060 public int getBaseDisplayDensity(int displayId) { 8061 synchronized (mWindowMap) { 8062 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8063 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8064 synchronized(displayContent.mDisplaySizeLock) { 8065 return displayContent.mBaseDisplayDensity; 8066 } 8067 } 8068 } 8069 return -1; 8070 } 8071 8072 @Override 8073 public void setForcedDisplayDensity(int displayId, int density) { 8074 if (mContext.checkCallingOrSelfPermission( 8075 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8076 PackageManager.PERMISSION_GRANTED) { 8077 throw new SecurityException("Must hold permission " + 8078 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8079 } 8080 if (displayId != Display.DEFAULT_DISPLAY) { 8081 throw new IllegalArgumentException("Can only set the default display"); 8082 } 8083 final long ident = Binder.clearCallingIdentity(); 8084 try { 8085 synchronized(mWindowMap) { 8086 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8087 if (displayContent != null) { 8088 setForcedDisplayDensityLocked(displayContent, density); 8089 Settings.Global.putString(mContext.getContentResolver(), 8090 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 8091 } 8092 } 8093 } finally { 8094 Binder.restoreCallingIdentity(ident); 8095 } 8096 } 8097 8098 // displayContent must not be null 8099 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 8100 Slog.i(TAG, "Using new display density: " + density); 8101 8102 synchronized(displayContent.mDisplaySizeLock) { 8103 displayContent.mBaseDisplayDensity = density; 8104 } 8105 reconfigureDisplayLocked(displayContent); 8106 } 8107 8108 @Override 8109 public void clearForcedDisplayDensity(int displayId) { 8110 if (mContext.checkCallingOrSelfPermission( 8111 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8112 PackageManager.PERMISSION_GRANTED) { 8113 throw new SecurityException("Must hold permission " + 8114 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8115 } 8116 if (displayId != Display.DEFAULT_DISPLAY) { 8117 throw new IllegalArgumentException("Can only set the default display"); 8118 } 8119 final long ident = Binder.clearCallingIdentity(); 8120 try { 8121 synchronized(mWindowMap) { 8122 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8123 if (displayContent != null) { 8124 setForcedDisplayDensityLocked(displayContent, 8125 displayContent.mInitialDisplayDensity); 8126 Settings.Global.putString(mContext.getContentResolver(), 8127 Settings.Global.DISPLAY_DENSITY_FORCED, ""); 8128 } 8129 } 8130 } finally { 8131 Binder.restoreCallingIdentity(ident); 8132 } 8133 } 8134 8135 // displayContent must not be null 8136 private void reconfigureDisplayLocked(DisplayContent displayContent) { 8137 // TODO: Multidisplay: for now only use with default display. 8138 configureDisplayPolicyLocked(displayContent); 8139 displayContent.layoutNeeded = true; 8140 8141 boolean configChanged = updateOrientationFromAppTokensLocked(false); 8142 mTempConfiguration.setToDefaults(); 8143 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 8144 if (computeScreenConfigurationLocked(mTempConfiguration)) { 8145 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 8146 configChanged = true; 8147 } 8148 } 8149 8150 if (configChanged) { 8151 mWaitingForConfig = true; 8152 startFreezingDisplayLocked(false, 0, 0); 8153 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8154 } 8155 8156 performLayoutAndPlaceSurfacesLocked(); 8157 } 8158 8159 private void configureDisplayPolicyLocked(DisplayContent displayContent) { 8160 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 8161 displayContent.mBaseDisplayWidth, 8162 displayContent.mBaseDisplayHeight, 8163 displayContent.mBaseDisplayDensity); 8164 8165 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8166 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 8167 displayInfo.overscanLeft, displayInfo.overscanTop, 8168 displayInfo.overscanRight, displayInfo.overscanBottom); 8169 } 8170 8171 @Override 8172 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 8173 if (mContext.checkCallingOrSelfPermission( 8174 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8175 PackageManager.PERMISSION_GRANTED) { 8176 throw new SecurityException("Must hold permission " + 8177 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8178 } 8179 final long ident = Binder.clearCallingIdentity(); 8180 try { 8181 synchronized(mWindowMap) { 8182 DisplayContent displayContent = getDisplayContentLocked(displayId); 8183 if (displayContent != null) { 8184 setOverscanLocked(displayContent, left, top, right, bottom); 8185 } 8186 } 8187 } finally { 8188 Binder.restoreCallingIdentity(ident); 8189 } 8190 } 8191 8192 private void setOverscanLocked(DisplayContent displayContent, 8193 int left, int top, int right, int bottom) { 8194 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8195 synchronized (displayContent.mDisplaySizeLock) { 8196 displayInfo.overscanLeft = left; 8197 displayInfo.overscanTop = top; 8198 displayInfo.overscanRight = right; 8199 displayInfo.overscanBottom = bottom; 8200 } 8201 8202 mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom); 8203 mDisplaySettings.writeSettingsLocked(); 8204 8205 reconfigureDisplayLocked(displayContent); 8206 } 8207 8208 // ------------------------------------------------------------- 8209 // Internals 8210 // ------------------------------------------------------------- 8211 8212 final WindowState windowForClientLocked(Session session, IWindow client, 8213 boolean throwOnError) { 8214 return windowForClientLocked(session, client.asBinder(), throwOnError); 8215 } 8216 8217 final WindowState windowForClientLocked(Session session, IBinder client, 8218 boolean throwOnError) { 8219 WindowState win = mWindowMap.get(client); 8220 if (localLOGV) Slog.v( 8221 TAG, "Looking up client " + client + ": " + win); 8222 if (win == null) { 8223 RuntimeException ex = new IllegalArgumentException( 8224 "Requested window " + client + " does not exist"); 8225 if (throwOnError) { 8226 throw ex; 8227 } 8228 Slog.w(TAG, "Failed looking up window", ex); 8229 return null; 8230 } 8231 if (session != null && win.mSession != session) { 8232 RuntimeException ex = new IllegalArgumentException( 8233 "Requested window " + client + " is in session " + 8234 win.mSession + ", not " + session); 8235 if (throwOnError) { 8236 throw ex; 8237 } 8238 Slog.w(TAG, "Failed looking up window", ex); 8239 return null; 8240 } 8241 8242 return win; 8243 } 8244 8245 final void rebuildAppWindowListLocked() { 8246 rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); 8247 } 8248 8249 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 8250 final WindowList windows = displayContent.getWindowList(); 8251 int NW = windows.size(); 8252 int i; 8253 int lastBelow = -1; 8254 int numRemoved = 0; 8255 8256 if (mRebuildTmp.length < NW) { 8257 mRebuildTmp = new WindowState[NW+10]; 8258 } 8259 8260 // First remove all existing app windows. 8261 i=0; 8262 while (i < NW) { 8263 WindowState w = windows.get(i); 8264 if (w.mAppToken != null) { 8265 WindowState win = windows.remove(i); 8266 win.mRebuilding = true; 8267 mRebuildTmp[numRemoved] = win; 8268 mWindowsChanged = true; 8269 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win); 8270 NW--; 8271 numRemoved++; 8272 continue; 8273 } else if (lastBelow == i-1) { 8274 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8275 lastBelow = i; 8276 } 8277 } 8278 i++; 8279 } 8280 8281 // Keep whatever windows were below the app windows still below, 8282 // by skipping them. 8283 lastBelow++; 8284 i = lastBelow; 8285 8286 // First add all of the exiting app tokens... these are no longer 8287 // in the main app list, but still have windows shown. We put them 8288 // in the back because now that the animation is over we no longer 8289 // will care about them. 8290 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 8291 final int numStacks = stacks.size(); 8292 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8293 AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens; 8294 int NT = exitingAppTokens.size(); 8295 for (int j = 0; j < NT; j++) { 8296 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 8297 } 8298 } 8299 8300 // And add in the still active app tokens in Z order. 8301 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8302 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8303 final int numTasks = tasks.size(); 8304 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 8305 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8306 final int numTokens = tokens.size(); 8307 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 8308 final AppWindowToken wtoken = tokens.get(tokenNdx); 8309 if (wtoken.mDeferRemoval) { 8310 continue; 8311 } 8312 i = reAddAppWindowsLocked(displayContent, i, wtoken); 8313 } 8314 } 8315 } 8316 8317 i -= lastBelow; 8318 if (i != numRemoved) { 8319 Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " + 8320 numRemoved + " windows but added " + i, 8321 new RuntimeException("here").fillInStackTrace()); 8322 for (i=0; i<numRemoved; i++) { 8323 WindowState ws = mRebuildTmp[i]; 8324 if (ws.mRebuilding) { 8325 StringWriter sw = new StringWriter(); 8326 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 8327 ws.dump(pw, "", true); 8328 pw.flush(); 8329 Slog.w(TAG, "This window was lost: " + ws); 8330 Slog.w(TAG, sw.toString()); 8331 ws.mWinAnimator.destroySurfaceLocked(); 8332 } 8333 } 8334 Slog.w(TAG, "Current app token list:"); 8335 dumpAppTokensLocked(); 8336 Slog.w(TAG, "Final window list:"); 8337 dumpWindowsLocked(); 8338 } 8339 } 8340 8341 private final void assignLayersLocked(WindowList windows) { 8342 int N = windows.size(); 8343 int curBaseLayer = 0; 8344 int curLayer = 0; 8345 int i; 8346 8347 if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows, 8348 new RuntimeException("here").fillInStackTrace()); 8349 8350 boolean anyLayerChanged = false; 8351 8352 for (i=0; i<N; i++) { 8353 final WindowState w = windows.get(i); 8354 final WindowStateAnimator winAnimator = w.mWinAnimator; 8355 boolean layerChanged = false; 8356 int oldLayer = w.mLayer; 8357 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 8358 || (i > 0 && w.mIsWallpaper)) { 8359 curLayer += WINDOW_LAYER_MULTIPLIER; 8360 w.mLayer = curLayer; 8361 } else { 8362 curBaseLayer = curLayer = w.mBaseLayer; 8363 w.mLayer = curLayer; 8364 } 8365 if (w.mLayer != oldLayer) { 8366 layerChanged = true; 8367 anyLayerChanged = true; 8368 } 8369 final AppWindowToken wtoken = w.mAppToken; 8370 oldLayer = winAnimator.mAnimLayer; 8371 if (w.mTargetAppToken != null) { 8372 winAnimator.mAnimLayer = 8373 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 8374 } else if (wtoken != null) { 8375 winAnimator.mAnimLayer = 8376 w.mLayer + wtoken.mAppAnimator.animLayerAdjustment; 8377 } else { 8378 winAnimator.mAnimLayer = w.mLayer; 8379 } 8380 if (w.mIsImWindow) { 8381 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 8382 } else if (w.mIsWallpaper) { 8383 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 8384 } 8385 if (winAnimator.mAnimLayer != oldLayer) { 8386 layerChanged = true; 8387 anyLayerChanged = true; 8388 } 8389 if (layerChanged && w.getStack().isDimming(winAnimator)) { 8390 // Force an animation pass just to update the mDimLayer layer. 8391 scheduleAnimationLocked(); 8392 } 8393 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 8394 + "mBase=" + w.mBaseLayer 8395 + " mLayer=" + w.mLayer 8396 + (wtoken == null ? 8397 "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment) 8398 + " =mAnimLayer=" + winAnimator.mAnimLayer); 8399 //System.out.println( 8400 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 8401 } 8402 8403 //TODO (multidisplay): Magnification is supported only for the default display. 8404 if (mAccessibilityController != null && anyLayerChanged 8405 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) { 8406 mAccessibilityController.onWindowLayersChangedLocked(); 8407 } 8408 } 8409 8410 private final void performLayoutAndPlaceSurfacesLocked() { 8411 int loopCount = 6; 8412 do { 8413 mTraversalScheduled = false; 8414 performLayoutAndPlaceSurfacesLockedLoop(); 8415 mH.removeMessages(H.DO_TRAVERSAL); 8416 loopCount--; 8417 } while (mTraversalScheduled && loopCount > 0); 8418 mInnerFields.mWallpaperActionPending = false; 8419 } 8420 8421 private boolean mInLayout = false; 8422 private final void performLayoutAndPlaceSurfacesLockedLoop() { 8423 if (mInLayout) { 8424 if (DEBUG) { 8425 throw new RuntimeException("Recursive call!"); 8426 } 8427 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 8428 + Debug.getCallers(3)); 8429 return; 8430 } 8431 8432 if (mWaitingForConfig) { 8433 // Our configuration has changed (most likely rotation), but we 8434 // don't yet have the complete configuration to report to 8435 // applications. Don't do any window layout until we have it. 8436 return; 8437 } 8438 8439 if (!mDisplayReady) { 8440 // Not yet initialized, nothing to do. 8441 return; 8442 } 8443 8444 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 8445 mInLayout = true; 8446 boolean recoveringMemory = false; 8447 8448 try { 8449 if (mForceRemoves != null) { 8450 recoveringMemory = true; 8451 // Wait a little bit for things to settle down, and off we go. 8452 for (int i=0; i<mForceRemoves.size(); i++) { 8453 WindowState ws = mForceRemoves.get(i); 8454 Slog.i(TAG, "Force removing: " + ws); 8455 removeWindowInnerLocked(ws.mSession, ws); 8456 } 8457 mForceRemoves = null; 8458 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 8459 Object tmp = new Object(); 8460 synchronized (tmp) { 8461 try { 8462 tmp.wait(250); 8463 } catch (InterruptedException e) { 8464 } 8465 } 8466 } 8467 } catch (RuntimeException e) { 8468 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 8469 } 8470 8471 try { 8472 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 8473 8474 mInLayout = false; 8475 8476 if (needsLayout()) { 8477 if (++mLayoutRepeatCount < 6) { 8478 requestTraversalLocked(); 8479 } else { 8480 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 8481 mLayoutRepeatCount = 0; 8482 } 8483 } else { 8484 mLayoutRepeatCount = 0; 8485 } 8486 8487 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 8488 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 8489 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE); 8490 } 8491 } catch (RuntimeException e) { 8492 mInLayout = false; 8493 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 8494 } 8495 8496 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 8497 } 8498 8499 private final void performLayoutLockedInner(final DisplayContent displayContent, 8500 boolean initial, boolean updateInputWindows) { 8501 if (!displayContent.layoutNeeded) { 8502 return; 8503 } 8504 displayContent.layoutNeeded = false; 8505 WindowList windows = displayContent.getWindowList(); 8506 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 8507 8508 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8509 final int dw = displayInfo.logicalWidth; 8510 final int dh = displayInfo.logicalHeight; 8511 8512 final int NFW = mFakeWindows.size(); 8513 for (int i=0; i<NFW; i++) { 8514 mFakeWindows.get(i).layout(dw, dh); 8515 } 8516 8517 final int N = windows.size(); 8518 int i; 8519 8520 if (DEBUG_LAYOUT) { 8521 Slog.v(TAG, "-------------------------------------"); 8522 Slog.v(TAG, "performLayout: needed=" 8523 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 8524 } 8525 8526 WindowStateAnimator universeBackground = null; 8527 8528 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); 8529 if (isDefaultDisplay) { 8530 // Not needed on non-default displays. 8531 mSystemDecorLayer = mPolicy.getSystemDecorLayerLw(); 8532 mScreenRect.set(0, 0, dw, dh); 8533 } 8534 8535 mPolicy.getContentRectLw(mTmpContentRect); 8536 displayContent.resize(mTmpContentRect); 8537 8538 int seq = mLayoutSeq+1; 8539 if (seq < 0) seq = 0; 8540 mLayoutSeq = seq; 8541 8542 boolean behindDream = false; 8543 8544 // First perform layout of any root windows (not attached 8545 // to another window). 8546 int topAttached = -1; 8547 for (i = N-1; i >= 0; i--) { 8548 final WindowState win = windows.get(i); 8549 8550 // Don't do layout of a window if it is not visible, or 8551 // soon won't be visible, to avoid wasting time and funky 8552 // changes while a window is animating away. 8553 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) 8554 || win.isGoneForLayoutLw(); 8555 8556 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 8557 Slog.v(TAG, "1ST PASS " + win 8558 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 8559 + " mLayoutAttached=" + win.mLayoutAttached 8560 + " screen changed=" + win.isConfigChanged()); 8561 final AppWindowToken atoken = win.mAppToken; 8562 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 8563 + win.mViewVisibility + " mRelayoutCalled=" 8564 + win.mRelayoutCalled + " hidden=" 8565 + win.mRootToken.hidden + " hiddenRequested=" 8566 + (atoken != null && atoken.hiddenRequested) 8567 + " mAttachedHidden=" + win.mAttachedHidden); 8568 else Slog.v(TAG, " VIS: mViewVisibility=" 8569 + win.mViewVisibility + " mRelayoutCalled=" 8570 + win.mRelayoutCalled + " hidden=" 8571 + win.mRootToken.hidden + " hiddenRequested=" 8572 + (atoken != null && atoken.hiddenRequested) 8573 + " mAttachedHidden=" + win.mAttachedHidden); 8574 } 8575 8576 // If this view is GONE, then skip it -- keep the current 8577 // frame, and let the caller know so they can ignore it 8578 // if they want. (We do the normal layout for INVISIBLE 8579 // windows, since that means "perform layout as normal, 8580 // just don't display"). 8581 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 8582 || ((win.isConfigChanged() || win.setInsetsChanged()) && 8583 ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || 8584 win.mAppToken != null && win.mAppToken.layoutConfigChanges)) 8585 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8586 if (!win.mLayoutAttached) { 8587 if (initial) { 8588 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8589 win.mContentChanged = false; 8590 } 8591 if (win.mAttrs.type == TYPE_DREAM) { 8592 // Don't layout windows behind a dream, so that if it 8593 // does stuff like hide the status bar we won't get a 8594 // bad transition when it goes away. 8595 behindDream = true; 8596 } 8597 win.mLayoutNeeded = false; 8598 win.prelayout(); 8599 mPolicy.layoutWindowLw(win, null); 8600 win.mLayoutSeq = seq; 8601 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8602 + win.mFrame + " mContainingFrame=" 8603 + win.mContainingFrame + " mDisplayFrame=" 8604 + win.mDisplayFrame); 8605 } else { 8606 if (topAttached < 0) topAttached = i; 8607 } 8608 } 8609 if (win.mViewVisibility == View.VISIBLE 8610 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 8611 && universeBackground == null) { 8612 universeBackground = win.mWinAnimator; 8613 } 8614 } 8615 8616 if (mAnimator.mUniverseBackground != universeBackground) { 8617 mFocusMayChange = true; 8618 mAnimator.mUniverseBackground = universeBackground; 8619 } 8620 8621 boolean attachedBehindDream = false; 8622 8623 // Now perform layout of attached windows, which usually 8624 // depend on the position of the window they are attached to. 8625 // XXX does not deal with windows that are attached to windows 8626 // that are themselves attached. 8627 for (i = topAttached; i >= 0; i--) { 8628 final WindowState win = windows.get(i); 8629 8630 if (win.mLayoutAttached) { 8631 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 8632 + " mHaveFrame=" + win.mHaveFrame 8633 + " mViewVisibility=" + win.mViewVisibility 8634 + " mRelayoutCalled=" + win.mRelayoutCalled); 8635 // If this view is GONE, then skip it -- keep the current 8636 // frame, and let the caller know so they can ignore it 8637 // if they want. (We do the normal layout for INVISIBLE 8638 // windows, since that means "perform layout as normal, 8639 // just don't display"). 8640 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) { 8641 continue; 8642 } 8643 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8644 || !win.mHaveFrame || win.mLayoutNeeded) { 8645 if (initial) { 8646 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8647 win.mContentChanged = false; 8648 } 8649 win.mLayoutNeeded = false; 8650 win.prelayout(); 8651 mPolicy.layoutWindowLw(win, win.mAttachedWindow); 8652 win.mLayoutSeq = seq; 8653 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8654 + win.mFrame + " mContainingFrame=" 8655 + win.mContainingFrame + " mDisplayFrame=" 8656 + win.mDisplayFrame); 8657 } 8658 } else if (win.mAttrs.type == TYPE_DREAM) { 8659 // Don't layout windows behind a dream, so that if it 8660 // does stuff like hide the status bar we won't get a 8661 // bad transition when it goes away. 8662 attachedBehindDream = behindDream; 8663 } 8664 } 8665 8666 // Window frames may have changed. Tell the input dispatcher about it. 8667 mInputMonitor.setUpdateInputWindowsNeededLw(); 8668 if (updateInputWindows) { 8669 mInputMonitor.updateInputWindowsLw(false /*force*/); 8670 } 8671 8672 mPolicy.finishLayoutLw(); 8673 } 8674 8675 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8676 // If the screen is currently frozen or off, then keep 8677 // it frozen/off until this window draws at its new 8678 // orientation. 8679 if (!okToDisplay()) { 8680 if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w); 8681 w.mOrientationChanging = true; 8682 w.mLastFreezeDuration = 0; 8683 mInnerFields.mOrientationChangeComplete = false; 8684 if (!mWindowsFreezingScreen) { 8685 mWindowsFreezingScreen = true; 8686 // XXX should probably keep timeout from 8687 // when we first froze the display. 8688 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8689 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 8690 WINDOW_FREEZE_TIMEOUT_DURATION); 8691 } 8692 } 8693 } 8694 8695 /** 8696 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8697 * @param windows List of windows on default display. 8698 * @return bitmap indicating if another pass through layout must be made. 8699 */ 8700 public int handleAppTransitionReadyLocked(WindowList windows) { 8701 int changes = 0; 8702 int i; 8703 int NN = mOpeningApps.size(); 8704 boolean goodToGo = true; 8705 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8706 "Checking " + NN + " opening apps (frozen=" 8707 + mDisplayFrozen + " timeout=" 8708 + mAppTransition.isTimeout() + ")..."); 8709 if (!mDisplayFrozen && !mAppTransition.isTimeout()) { 8710 // If the display isn't frozen, wait to do anything until 8711 // all of the apps are ready. Otherwise just go because 8712 // we'll unfreeze the display when everyone is ready. 8713 for (i=0; i<NN && goodToGo; i++) { 8714 AppWindowToken wtoken = mOpeningApps.valueAt(i); 8715 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8716 "Check opening app=" + wtoken + ": allDrawn=" 8717 + wtoken.allDrawn + " startingDisplayed=" 8718 + wtoken.startingDisplayed + " startingMoved=" 8719 + wtoken.startingMoved); 8720 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8721 && !wtoken.startingMoved) { 8722 goodToGo = false; 8723 } 8724 } 8725 } 8726 if (goodToGo) { 8727 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8728 int transit = mAppTransition.getAppTransition(); 8729 if (mSkipAppTransitionAnimation) { 8730 transit = AppTransition.TRANSIT_UNSET; 8731 } 8732 mAppTransition.goodToGo(); 8733 mStartingIconInTransition = false; 8734 mSkipAppTransitionAnimation = false; 8735 8736 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8737 8738 rebuildAppWindowListLocked(); 8739 8740 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8741 WindowState oldWallpaper = 8742 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8743 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8744 ? null : mWallpaperTarget; 8745 8746 mInnerFields.mWallpaperMayChange = false; 8747 8748 // The top-most window will supply the layout params, 8749 // and we will determine it below. 8750 LayoutParams animLp = null; 8751 int bestAnimLayer = -1; 8752 boolean fullscreenAnim = false; 8753 boolean voiceInteraction = false; 8754 8755 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8756 "New wallpaper target=" + mWallpaperTarget 8757 + ", oldWallpaper=" + oldWallpaper 8758 + ", lower target=" + mLowerWallpaperTarget 8759 + ", upper target=" + mUpperWallpaperTarget); 8760 8761 boolean openingAppHasWallpaper = false; 8762 boolean closingAppHasWallpaper = false; 8763 final AppWindowToken lowerWallpaperAppToken; 8764 final AppWindowToken upperWallpaperAppToken; 8765 if (mLowerWallpaperTarget == null) { 8766 lowerWallpaperAppToken = upperWallpaperAppToken = null; 8767 } else { 8768 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken; 8769 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken; 8770 } 8771 8772 // Do a first pass through the tokens for two 8773 // things: 8774 // (1) Determine if both the closing and opening 8775 // app token sets are wallpaper targets, in which 8776 // case special animations are needed 8777 // (since the wallpaper needs to stay static 8778 // behind them). 8779 // (2) Find the layout params of the top-most 8780 // application window in the tokens, which is 8781 // what will control the animation theme. 8782 final int NC = mClosingApps.size(); 8783 NN = NC + mOpeningApps.size(); 8784 for (i=0; i<NN; i++) { 8785 final AppWindowToken wtoken; 8786 if (i < NC) { 8787 wtoken = mClosingApps.valueAt(i); 8788 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8789 closingAppHasWallpaper = true; 8790 } 8791 } else { 8792 wtoken = mOpeningApps.valueAt(i - NC); 8793 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8794 openingAppHasWallpaper = true; 8795 } 8796 } 8797 8798 voiceInteraction |= wtoken.voiceInteraction; 8799 8800 if (wtoken.appFullscreen) { 8801 WindowState ws = wtoken.findMainWindow(); 8802 if (ws != null) { 8803 animLp = ws.mAttrs; 8804 bestAnimLayer = ws.mLayer; 8805 fullscreenAnim = true; 8806 } 8807 } else if (!fullscreenAnim) { 8808 WindowState ws = wtoken.findMainWindow(); 8809 if (ws != null) { 8810 if (ws.mLayer > bestAnimLayer) { 8811 animLp = ws.mAttrs; 8812 bestAnimLayer = ws.mLayer; 8813 } 8814 } 8815 } 8816 } 8817 8818 mAnimateWallpaperWithTarget = false; 8819 if (closingAppHasWallpaper && openingAppHasWallpaper) { 8820 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!"); 8821 switch (transit) { 8822 case AppTransition.TRANSIT_ACTIVITY_OPEN: 8823 case AppTransition.TRANSIT_TASK_OPEN: 8824 case AppTransition.TRANSIT_TASK_TO_FRONT: 8825 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN; 8826 break; 8827 case AppTransition.TRANSIT_ACTIVITY_CLOSE: 8828 case AppTransition.TRANSIT_TASK_CLOSE: 8829 case AppTransition.TRANSIT_TASK_TO_BACK: 8830 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; 8831 break; 8832 } 8833 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); 8834 } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty() 8835 && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 8836 // We are transitioning from an activity with 8837 // a wallpaper to one without. 8838 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; 8839 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8840 "New transit away from wallpaper: " + transit); 8841 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) { 8842 // We are transitioning from an activity without 8843 // a wallpaper to now showing the wallpaper 8844 transit = AppTransition.TRANSIT_WALLPAPER_OPEN; 8845 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8846 "New transit into wallpaper: " + transit); 8847 } else { 8848 mAnimateWallpaperWithTarget = true; 8849 } 8850 8851 // If all closing windows are obscured, then there is 8852 // no need to do an animation. This is the case, for 8853 // example, when this transition is being done behind 8854 // the lock screen. 8855 if (!mPolicy.allowAppAnimationsLw()) { 8856 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8857 "Animations disallowed by keyguard or dream."); 8858 animLp = null; 8859 } 8860 8861 AppWindowToken topOpeningApp = null; 8862 int topOpeningLayer = 0; 8863 8864 NN = mOpeningApps.size(); 8865 for (i=0; i<NN; i++) { 8866 AppWindowToken wtoken = mOpeningApps.valueAt(i); 8867 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 8868 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 8869 appAnimator.clearThumbnail(); 8870 wtoken.inPendingTransaction = false; 8871 appAnimator.animation = null; 8872 setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction); 8873 wtoken.updateReportedVisibilityLocked(); 8874 wtoken.waitingToShow = false; 8875 8876 appAnimator.mAllAppWinAnimators.clear(); 8877 final int N = wtoken.allAppWindows.size(); 8878 for (int j = 0; j < N; j++) { 8879 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 8880 } 8881 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 8882 8883 if (animLp != null) { 8884 int layer = -1; 8885 for (int j=0; j<wtoken.windows.size(); j++) { 8886 WindowState win = wtoken.windows.get(j); 8887 if (win.mWinAnimator.mAnimLayer > layer) { 8888 layer = win.mWinAnimator.mAnimLayer; 8889 } 8890 } 8891 if (topOpeningApp == null || layer > topOpeningLayer) { 8892 topOpeningApp = wtoken; 8893 topOpeningLayer = layer; 8894 } 8895 } 8896 } 8897 NN = mClosingApps.size(); 8898 for (i=0; i<NN; i++) { 8899 AppWindowToken wtoken = mClosingApps.valueAt(i); 8900 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken); 8901 wtoken.mAppAnimator.clearThumbnail(); 8902 wtoken.inPendingTransaction = false; 8903 wtoken.mAppAnimator.animation = null; 8904 setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction); 8905 wtoken.updateReportedVisibilityLocked(); 8906 wtoken.waitingToHide = false; 8907 // Force the allDrawn flag, because we want to start 8908 // this guy's animations regardless of whether it's 8909 // gotten drawn. 8910 wtoken.allDrawn = true; 8911 wtoken.deferClearAllDrawn = false; 8912 } 8913 8914 boolean useAlternateThumbnailAnimation = true; 8915 AppWindowAnimator appAnimator = 8916 topOpeningApp == null ? null : topOpeningApp.mAppAnimator; 8917 Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail(); 8918 if (!useAlternateThumbnailAnimation && nextAppTransitionThumbnail != null 8919 && appAnimator != null && appAnimator.animation != null) { 8920 // This thumbnail animation is very special, we need to have 8921 // an extra surface with the thumbnail included with the animation. 8922 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(), 8923 nextAppTransitionThumbnail.getHeight()); 8924 try { 8925 // TODO(multi-display): support other displays 8926 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8927 final Display display = displayContent.getDisplay(); 8928 SurfaceControl surfaceControl = new SurfaceControl(mFxSession, 8929 "thumbnail anim", 8930 dirty.width(), dirty.height(), 8931 PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 8932 surfaceControl.setLayerStack(display.getLayerStack()); 8933 appAnimator.thumbnail = surfaceControl; 8934 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE"); 8935 Surface drawSurface = new Surface(); 8936 drawSurface.copyFrom(surfaceControl); 8937 Canvas c = drawSurface.lockCanvas(dirty); 8938 c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null); 8939 drawSurface.unlockCanvasAndPost(c); 8940 drawSurface.release(); 8941 appAnimator.thumbnailLayer = topOpeningLayer; 8942 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 8943 Animation anim = mAppTransition.createThumbnailScaleAnimationLocked( 8944 displayInfo.appWidth, displayInfo.appHeight, transit); 8945 appAnimator.thumbnailAnimation = anim; 8946 anim.restrictDuration(MAX_ANIMATION_DURATION); 8947 anim.scaleCurrentDuration(getTransitionAnimationScaleLocked()); 8948 Point p = new Point(); 8949 mAppTransition.getStartingPoint(p); 8950 appAnimator.thumbnailX = p.x; 8951 appAnimator.thumbnailY = p.y; 8952 } catch (OutOfResourcesException e) { 8953 Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width() 8954 + " h=" + dirty.height(), e); 8955 appAnimator.clearThumbnail(); 8956 } 8957 } 8958 8959 mAppTransition.postAnimationCallback(); 8960 mAppTransition.clear(); 8961 8962 mOpeningApps.clear(); 8963 mClosingApps.clear(); 8964 8965 // This has changed the visibility of windows, so perform 8966 // a new layout to get them all up-to-date. 8967 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT 8968 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 8969 getDefaultDisplayContentLocked().layoutNeeded = true; 8970 8971 // TODO(multidisplay): IMEs are only supported on the default display. 8972 if (windows == getDefaultWindowListLocked() 8973 && !moveInputMethodWindowsIfNeededLocked(true)) { 8974 assignLayersLocked(windows); 8975 } 8976 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, true /*updateInputWindows*/); 8977 mFocusMayChange = false; 8978 } 8979 8980 return changes; 8981 } 8982 8983 /** 8984 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8985 * @return bitmap indicating if another pass through layout must be made. 8986 */ 8987 private int handleAnimatingStoppedAndTransitionLocked() { 8988 int changes = 0; 8989 8990 mAppTransition.setIdle(); 8991 // Restore window app tokens to the ActivityManager views 8992 ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks(); 8993 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 8994 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8995 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 8996 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8997 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 8998 tokens.get(tokenNdx).sendingToBottom = false; 8999 } 9000 } 9001 } 9002 rebuildAppWindowListLocked(); 9003 9004 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 9005 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 9006 "Wallpaper layer changed: assigning layers + relayout"); 9007 moveInputMethodWindowsIfNeededLocked(true); 9008 mInnerFields.mWallpaperMayChange = true; 9009 // Since the window list has been rebuilt, focus might 9010 // have to be recomputed since the actual order of windows 9011 // might have changed again. 9012 mFocusMayChange = true; 9013 9014 return changes; 9015 } 9016 9017 private void updateResizingWindows(final WindowState w) { 9018 final WindowStateAnimator winAnimator = w.mWinAnimator; 9019 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { 9020 w.setInsetsChanged(); 9021 boolean configChanged = w.isConfigChanged(); 9022 if (DEBUG_CONFIGURATION && configChanged) { 9023 Slog.v(TAG, "Win " + w + " config changed: " 9024 + mCurConfiguration); 9025 } 9026 if (localLOGV) Slog.v(TAG, "Resizing " + w 9027 + ": configChanged=" + configChanged 9028 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 9029 w.mLastFrame.set(w.mFrame); 9030 if (w.mContentInsetsChanged 9031 || w.mVisibleInsetsChanged 9032 || winAnimator.mSurfaceResized 9033 || configChanged) { 9034 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 9035 Slog.v(TAG, "Resize reasons for w=" + w + ": " 9036 + " contentInsetsChanged=" + w.mContentInsetsChanged 9037 + " " + w.mContentInsets.toShortString() 9038 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 9039 + " " + w.mVisibleInsets.toShortString() 9040 + " stableInsetsChanged=" + w.mStableInsetsChanged 9041 + " " + w.mStableInsets.toShortString() 9042 + " surfaceResized=" + winAnimator.mSurfaceResized 9043 + " configChanged=" + configChanged); 9044 } 9045 9046 w.mLastOverscanInsets.set(w.mOverscanInsets); 9047 w.mLastContentInsets.set(w.mContentInsets); 9048 w.mLastVisibleInsets.set(w.mVisibleInsets); 9049 w.mLastStableInsets.set(w.mStableInsets); 9050 makeWindowFreezingScreenIfNeededLocked(w); 9051 // If the orientation is changing, then we need to 9052 // hold off on unfreezing the display until this 9053 // window has been redrawn; to do that, we need 9054 // to go through the process of getting informed 9055 // by the application when it has finished drawing. 9056 if (w.mOrientationChanging) { 9057 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 9058 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 9059 + w + ", surface " + winAnimator.mSurfaceControl); 9060 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 9061 if (w.mAppToken != null) { 9062 w.mAppToken.allDrawn = false; 9063 w.mAppToken.deferClearAllDrawn = false; 9064 } 9065 } 9066 if (!mResizingWindows.contains(w)) { 9067 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 9068 "Resizing window " + w + " to " + winAnimator.mSurfaceW 9069 + "x" + winAnimator.mSurfaceH); 9070 mResizingWindows.add(w); 9071 } 9072 } else if (w.mOrientationChanging) { 9073 if (w.isDrawnLw()) { 9074 if (DEBUG_ORIENTATION) Slog.v(TAG, 9075 "Orientation not waiting for draw in " 9076 + w + ", surface " + winAnimator.mSurfaceControl); 9077 w.mOrientationChanging = false; 9078 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 9079 - mDisplayFreezeTime); 9080 } 9081 } 9082 } 9083 } 9084 9085 /** 9086 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 9087 * 9088 * @param w WindowState this method is applied to. 9089 * @param currentTime The time which animations use for calculating transitions. 9090 * @param innerDw Width of app window. 9091 * @param innerDh Height of app window. 9092 */ 9093 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 9094 final int innerDw, final int innerDh) { 9095 final WindowManager.LayoutParams attrs = w.mAttrs; 9096 final int attrFlags = attrs.flags; 9097 final boolean canBeSeen = w.isDisplayedLw(); 9098 final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 9099 9100 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 9101 // This window completely covers everything behind it, 9102 // so we want to leave all of them as undimmed (for 9103 // performance reasons). 9104 mInnerFields.mObscured = true; 9105 } 9106 9107 if (w.mHasSurface) { 9108 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 9109 mInnerFields.mHoldScreen = w.mSession; 9110 } 9111 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 9112 && mInnerFields.mScreenBrightness < 0) { 9113 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 9114 } 9115 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 9116 && mInnerFields.mButtonBrightness < 0) { 9117 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 9118 } 9119 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0 9120 && mInnerFields.mUserActivityTimeout < 0) { 9121 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout; 9122 } 9123 9124 final int type = attrs.type; 9125 if (canBeSeen 9126 && (type == TYPE_SYSTEM_DIALOG 9127 || type == TYPE_RECENTS_OVERLAY 9128 || type == TYPE_SYSTEM_ERROR 9129 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) { 9130 mInnerFields.mSyswin = true; 9131 } 9132 9133 if (canBeSeen) { 9134 // This function assumes that the contents of the default display are 9135 // processed first before secondary displays. 9136 final DisplayContent displayContent = w.getDisplayContent(); 9137 if (displayContent != null && displayContent.isDefaultDisplay) { 9138 // While a dream or keyguard is showing, obscure ordinary application 9139 // content on secondary displays (by forcibly enabling mirroring unless 9140 // there is other content we want to show) but still allow opaque 9141 // keyguard dialogs to be shown. 9142 if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 9143 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true; 9144 } 9145 mInnerFields.mDisplayHasContent = true; 9146 } else if (displayContent != null && 9147 (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays 9148 || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) { 9149 // Allow full screen keyguard presentation dialogs to be seen. 9150 mInnerFields.mDisplayHasContent = true; 9151 } 9152 if (mInnerFields.mPreferredRefreshRate == 0 9153 && w.mAttrs.preferredRefreshRate != 0) { 9154 mInnerFields.mPreferredRefreshRate = w.mAttrs.preferredRefreshRate; 9155 } 9156 } 9157 } 9158 } 9159 9160 private void handleFlagDimBehind(WindowState w) { 9161 final WindowManager.LayoutParams attrs = w.mAttrs; 9162 if ((attrs.flags & FLAG_DIM_BEHIND) != 0 9163 && w.isDisplayedLw() 9164 && !w.mExiting) { 9165 final WindowStateAnimator winAnimator = w.mWinAnimator; 9166 final TaskStack stack = w.getStack(); 9167 stack.setDimmingTag(); 9168 if (!stack.isDimming(winAnimator)) { 9169 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming."); 9170 stack.startDimmingIfNeeded(winAnimator); 9171 } 9172 } 9173 } 9174 9175 private void updateAllDrawnLocked(DisplayContent displayContent) { 9176 // See if any windows have been drawn, so they (and others 9177 // associated with them) can now be shown. 9178 ArrayList<TaskStack> stacks = displayContent.getStacks(); 9179 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 9180 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9181 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9182 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9183 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9184 final AppWindowToken wtoken = tokens.get(tokenNdx); 9185 if (!wtoken.allDrawn) { 9186 int numInteresting = wtoken.numInterestingWindows; 9187 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 9188 if (DEBUG_VISIBILITY) Slog.v(TAG, 9189 "allDrawn: " + wtoken 9190 + " interesting=" + numInteresting 9191 + " drawn=" + wtoken.numDrawnWindows); 9192 wtoken.allDrawn = true; 9193 mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget(); 9194 } 9195 } 9196 } 9197 } 9198 } 9199 } 9200 9201 // "Something has changed! Let's make it correct now." 9202 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 9203 if (DEBUG_WINDOW_TRACE) { 9204 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 9205 + Debug.getCallers(3)); 9206 } 9207 9208 final long currentTime = SystemClock.uptimeMillis(); 9209 9210 int i; 9211 boolean updateInputWindowsNeeded = false; 9212 9213 if (mFocusMayChange) { 9214 mFocusMayChange = false; 9215 updateInputWindowsNeeded = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 9216 false /*updateInputWindows*/); 9217 } 9218 9219 // Initialize state of exiting tokens. 9220 final int numDisplays = mDisplayContents.size(); 9221 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9222 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9223 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) { 9224 displayContent.mExitingTokens.get(i).hasVisible = false; 9225 } 9226 } 9227 9228 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9229 // Initialize state of exiting applications. 9230 final AppTokenList exitingAppTokens = 9231 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9232 for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9233 exitingAppTokens.get(tokenNdx).hasVisible = false; 9234 } 9235 } 9236 9237 mInnerFields.mHoldScreen = null; 9238 mInnerFields.mScreenBrightness = -1; 9239 mInnerFields.mButtonBrightness = -1; 9240 mInnerFields.mUserActivityTimeout = -1; 9241 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false; 9242 9243 mTransactionSequence++; 9244 9245 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked(); 9246 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 9247 final int defaultDw = defaultInfo.logicalWidth; 9248 final int defaultDh = defaultInfo.logicalHeight; 9249 9250 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9251 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 9252 SurfaceControl.openTransaction(); 9253 try { 9254 9255 if (mWatermark != null) { 9256 mWatermark.positionSurface(defaultDw, defaultDh); 9257 } 9258 if (mStrictModeFlash != null) { 9259 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 9260 } 9261 if (mCircularDisplayMask != null) { 9262 mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation); 9263 } 9264 9265 boolean focusDisplayed = false; 9266 9267 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9268 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9269 boolean updateAllDrawn = false; 9270 WindowList windows = displayContent.getWindowList(); 9271 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9272 final int displayId = displayContent.getDisplayId(); 9273 final int dw = displayInfo.logicalWidth; 9274 final int dh = displayInfo.logicalHeight; 9275 final int innerDw = displayInfo.appWidth; 9276 final int innerDh = displayInfo.appHeight; 9277 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 9278 9279 // Reset for each display. 9280 mInnerFields.mDisplayHasContent = false; 9281 mInnerFields.mPreferredRefreshRate = 0; 9282 9283 int repeats = 0; 9284 do { 9285 repeats++; 9286 if (repeats > 6) { 9287 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 9288 displayContent.layoutNeeded = false; 9289 break; 9290 } 9291 9292 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 9293 displayContent.pendingLayoutChanges); 9294 9295 if ((displayContent.pendingLayoutChanges & 9296 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 && 9297 (adjustWallpaperWindowsLocked() & 9298 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 9299 assignLayersLocked(windows); 9300 displayContent.layoutNeeded = true; 9301 } 9302 9303 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 9304 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 9305 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 9306 if (updateOrientationFromAppTokensLocked(true)) { 9307 displayContent.layoutNeeded = true; 9308 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9309 } 9310 } 9311 9312 if ((displayContent.pendingLayoutChanges 9313 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9314 displayContent.layoutNeeded = true; 9315 } 9316 9317 // FIRST LOOP: Perform a layout, if needed. 9318 if (repeats < 4) { 9319 performLayoutLockedInner(displayContent, repeats == 1, 9320 false /*updateInputWindows*/); 9321 } else { 9322 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 9323 } 9324 9325 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 9326 // it is animating. 9327 displayContent.pendingLayoutChanges = 0; 9328 9329 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 9330 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 9331 9332 if (isDefaultDisplay) { 9333 mPolicy.beginPostLayoutPolicyLw(dw, dh); 9334 for (i = windows.size() - 1; i >= 0; i--) { 9335 WindowState w = windows.get(i); 9336 if (w.mHasSurface) { 9337 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); 9338 } 9339 } 9340 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 9341 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 9342 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges); 9343 } 9344 } while (displayContent.pendingLayoutChanges != 0); 9345 9346 mInnerFields.mObscured = false; 9347 mInnerFields.mSyswin = false; 9348 displayContent.resetDimming(); 9349 9350 // Only used if default window 9351 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 9352 9353 final int N = windows.size(); 9354 for (i=N-1; i>=0; i--) { 9355 WindowState w = windows.get(i); 9356 final TaskStack stack = w.getStack(); 9357 if (stack == null) { 9358 continue; 9359 } 9360 9361 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 9362 9363 // Update effect. 9364 w.mObscured = mInnerFields.mObscured; 9365 if (!mInnerFields.mObscured) { 9366 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 9367 } 9368 9369 if (!stack.testDimmingTag()) { 9370 handleFlagDimBehind(w); 9371 } 9372 9373 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 9374 && w.isVisibleLw()) { 9375 // This is the wallpaper target and its obscured state 9376 // changed... make sure the current wallaper's visibility 9377 // has been updated accordingly. 9378 updateWallpaperVisibilityLocked(); 9379 } 9380 9381 final WindowStateAnimator winAnimator = w.mWinAnimator; 9382 9383 // If the window has moved due to its containing 9384 // content frame changing, then we'd like to animate 9385 // it. 9386 if (w.mHasSurface && w.shouldAnimateMove()) { 9387 // Frame has moved, containing content frame 9388 // has also moved, and we're not currently animating... 9389 // let's do something. 9390 Animation a = AnimationUtils.loadAnimation(mContext, 9391 com.android.internal.R.anim.window_move_from_decor); 9392 winAnimator.setAnimation(a); 9393 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 9394 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 9395 9396 //TODO (multidisplay): Accessibility supported only for the default display. 9397 if (mAccessibilityController != null 9398 && displayId == Display.DEFAULT_DISPLAY) { 9399 mAccessibilityController.onSomeWindowResizedOrMovedLocked(); 9400 } 9401 9402 try { 9403 w.mClient.moved(w.mFrame.left, w.mFrame.top); 9404 } catch (RemoteException e) { 9405 } 9406 } 9407 9408 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 9409 w.mContentChanged = false; 9410 9411 // Moved from updateWindowsAndWallpaperLocked(). 9412 if (w.mHasSurface) { 9413 // Take care of the window being ready to display. 9414 final boolean committed = 9415 winAnimator.commitFinishDrawingLocked(currentTime); 9416 if (isDefaultDisplay && committed) { 9417 if (w.mAttrs.type == TYPE_DREAM) { 9418 // HACK: When a dream is shown, it may at that 9419 // point hide the lock screen. So we need to 9420 // redo the layout to let the phone window manager 9421 // make this happen. 9422 displayContent.pendingLayoutChanges |= 9423 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9424 if (DEBUG_LAYOUT_REPEATS) { 9425 debugLayoutRepeats( 9426 "dream and commitFinishDrawingLocked true", 9427 displayContent.pendingLayoutChanges); 9428 } 9429 } 9430 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 9431 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 9432 "First draw done in potential wallpaper target " + w); 9433 mInnerFields.mWallpaperMayChange = true; 9434 displayContent.pendingLayoutChanges |= 9435 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9436 if (DEBUG_LAYOUT_REPEATS) { 9437 debugLayoutRepeats( 9438 "wallpaper and commitFinishDrawingLocked true", 9439 displayContent.pendingLayoutChanges); 9440 } 9441 } 9442 } 9443 9444 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 9445 9446 final AppWindowToken atoken = w.mAppToken; 9447 if (DEBUG_STARTING_WINDOW && atoken != null 9448 && w == atoken.startingWindow) { 9449 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 9450 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 9451 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 9452 } 9453 if (atoken != null 9454 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 9455 if (atoken.lastTransactionSequence != mTransactionSequence) { 9456 atoken.lastTransactionSequence = mTransactionSequence; 9457 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 9458 atoken.startingDisplayed = false; 9459 } 9460 if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 9461 && !w.mExiting && !w.mDestroying) { 9462 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 9463 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 9464 + ", isAnimating=" + winAnimator.isAnimating()); 9465 if (!w.isDrawnLw()) { 9466 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl 9467 + " pv=" + w.mPolicyVisibility 9468 + " mDrawState=" + winAnimator.mDrawState 9469 + " ah=" + w.mAttachedHidden 9470 + " th=" + atoken.hiddenRequested 9471 + " a=" + winAnimator.mAnimating); 9472 } 9473 } 9474 if (w != atoken.startingWindow) { 9475 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 9476 atoken.numInterestingWindows++; 9477 if (w.isDrawnLw()) { 9478 atoken.numDrawnWindows++; 9479 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 9480 "tokenMayBeDrawn: " + atoken 9481 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 9482 + " mAppFreezing=" + w.mAppFreezing); 9483 updateAllDrawn = true; 9484 } 9485 } 9486 } else if (w.isDrawnLw()) { 9487 atoken.startingDisplayed = true; 9488 } 9489 } 9490 } 9491 } 9492 9493 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 9494 && w.isDisplayedLw()) { 9495 focusDisplayed = true; 9496 } 9497 9498 updateResizingWindows(w); 9499 } 9500 9501 mDisplayManagerInternal.setDisplayProperties(displayId, 9502 mInnerFields.mDisplayHasContent, mInnerFields.mPreferredRefreshRate, 9503 true /* inTraversal, must call performTraversalInTrans... below */); 9504 9505 getDisplayContentLocked(displayId).stopDimmingIfNeeded(); 9506 9507 if (updateAllDrawn) { 9508 updateAllDrawnLocked(displayContent); 9509 } 9510 } 9511 9512 if (focusDisplayed) { 9513 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 9514 } 9515 9516 // Give the display manager a chance to adjust properties 9517 // like display rotation if it needs to. 9518 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 9519 9520 } catch (RuntimeException e) { 9521 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 9522 } finally { 9523 SurfaceControl.closeTransaction(); 9524 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9525 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 9526 } 9527 9528 final WindowList defaultWindows = defaultDisplay.getWindowList(); 9529 9530 // If we are ready to perform an app transition, check through 9531 // all of the app tokens to be shown and see if they are ready 9532 // to go. 9533 if (mAppTransition.isReady()) { 9534 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 9535 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 9536 defaultDisplay.pendingLayoutChanges); 9537 } 9538 9539 if (!mAnimator.mAnimating && mAppTransition.isRunning()) { 9540 // We have finished the animation of an app transition. To do 9541 // this, we have delayed a lot of operations like showing and 9542 // hiding apps, moving apps in Z-order, etc. The app token list 9543 // reflects the correct Z-order, but the window list may now 9544 // be out of sync with it. So here we will just rebuild the 9545 // entire app window list. Fun! 9546 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 9547 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 9548 defaultDisplay.pendingLayoutChanges); 9549 } 9550 9551 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 9552 && !mAppTransition.isReady()) { 9553 // At this point, there was a window with a wallpaper that 9554 // was force hiding other windows behind it, but now it 9555 // is going away. This may be simple -- just animate 9556 // away the wallpaper and its window -- or it may be 9557 // hard -- the wallpaper now needs to be shown behind 9558 // something that was hidden. 9559 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9560 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 9561 defaultDisplay.pendingLayoutChanges); 9562 } 9563 mInnerFields.mWallpaperForceHidingChanged = false; 9564 9565 if (mInnerFields.mWallpaperMayChange) { 9566 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting"); 9567 defaultDisplay.pendingLayoutChanges |= 9568 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9569 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange", 9570 defaultDisplay.pendingLayoutChanges); 9571 } 9572 9573 if (mFocusMayChange) { 9574 mFocusMayChange = false; 9575 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 9576 false /*updateInputWindows*/)) { 9577 updateInputWindowsNeeded = true; 9578 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 9579 } 9580 } 9581 9582 if (needsLayout()) { 9583 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9584 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 9585 defaultDisplay.pendingLayoutChanges); 9586 } 9587 9588 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 9589 WindowState win = mResizingWindows.get(i); 9590 if (win.mAppFreezing) { 9591 // Don't remove this window until rotation has completed. 9592 continue; 9593 } 9594 win.reportResized(); 9595 mResizingWindows.remove(i); 9596 } 9597 9598 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 9599 "With display frozen, orientationChangeComplete=" 9600 + mInnerFields.mOrientationChangeComplete); 9601 if (mInnerFields.mOrientationChangeComplete) { 9602 if (mWindowsFreezingScreen) { 9603 mWindowsFreezingScreen = false; 9604 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource; 9605 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9606 } 9607 stopFreezingDisplayLocked(); 9608 } 9609 9610 // Destroy the surface of any windows that are no longer visible. 9611 boolean wallpaperDestroyed = false; 9612 i = mDestroySurface.size(); 9613 if (i > 0) { 9614 do { 9615 i--; 9616 WindowState win = mDestroySurface.get(i); 9617 win.mDestroying = false; 9618 if (mInputMethodWindow == win) { 9619 mInputMethodWindow = null; 9620 } 9621 if (win == mWallpaperTarget) { 9622 wallpaperDestroyed = true; 9623 } 9624 win.mWinAnimator.destroySurfaceLocked(); 9625 } while (i > 0); 9626 mDestroySurface.clear(); 9627 } 9628 9629 // Time to remove any exiting tokens? 9630 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9631 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9632 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens; 9633 for (i = exitingTokens.size() - 1; i >= 0; i--) { 9634 WindowToken token = exitingTokens.get(i); 9635 if (!token.hasVisible) { 9636 exitingTokens.remove(i); 9637 if (token.windowType == TYPE_WALLPAPER) { 9638 mWallpaperTokens.remove(token); 9639 } 9640 } 9641 } 9642 } 9643 9644 // Time to remove any exiting applications? 9645 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9646 // Initialize state of exiting applications. 9647 final AppTokenList exitingAppTokens = 9648 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9649 for (i = exitingAppTokens.size() - 1; i >= 0; i--) { 9650 AppWindowToken token = exitingAppTokens.get(i); 9651 if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) { 9652 // Make sure there is no animation running on this token, 9653 // so any windows associated with it will be removed as 9654 // soon as their animations are complete 9655 token.mAppAnimator.clearAnimation(); 9656 token.mAppAnimator.animating = false; 9657 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 9658 "performLayout: App token exiting now removed" + token); 9659 removeAppFromTaskLocked(token); 9660 exitingAppTokens.remove(i); 9661 } 9662 } 9663 } 9664 9665 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 9666 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 9667 try { 9668 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 9669 } catch (RemoteException e) { 9670 } 9671 } 9672 mRelayoutWhileAnimating.clear(); 9673 } 9674 9675 if (wallpaperDestroyed) { 9676 defaultDisplay.pendingLayoutChanges |= 9677 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9678 defaultDisplay.layoutNeeded = true; 9679 } 9680 9681 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9682 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9683 if (displayContent.pendingLayoutChanges != 0) { 9684 displayContent.layoutNeeded = true; 9685 } 9686 } 9687 9688 // Finally update all input windows now that the window changes have stabilized. 9689 mInputMonitor.updateInputWindowsLw(true /*force*/); 9690 9691 setHoldScreenLocked(mInnerFields.mHoldScreen); 9692 if (!mDisplayFrozen) { 9693 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 9694 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1); 9695 } else { 9696 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager( 9697 toBrightnessOverride(mInnerFields.mScreenBrightness)); 9698 } 9699 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 9700 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1); 9701 } else { 9702 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager( 9703 toBrightnessOverride(mInnerFields.mButtonBrightness)); 9704 } 9705 mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager( 9706 mInnerFields.mUserActivityTimeout); 9707 } 9708 9709 if (mTurnOnScreen) { 9710 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 9711 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 9712 mTurnOnScreen = false; 9713 } 9714 9715 if (mInnerFields.mUpdateRotation) { 9716 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9717 if (updateRotationUncheckedLocked(false)) { 9718 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9719 } else { 9720 mInnerFields.mUpdateRotation = false; 9721 } 9722 } 9723 9724 if (mWaitingForDrawnCallback != null || 9725 (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded && 9726 !mInnerFields.mUpdateRotation)) { 9727 checkDrawnWindowsLocked(); 9728 } 9729 9730 final int N = mPendingRemove.size(); 9731 if (N > 0) { 9732 if (mPendingRemoveTmp.length < N) { 9733 mPendingRemoveTmp = new WindowState[N+10]; 9734 } 9735 mPendingRemove.toArray(mPendingRemoveTmp); 9736 mPendingRemove.clear(); 9737 DisplayContentList displayList = new DisplayContentList(); 9738 for (i = 0; i < N; i++) { 9739 WindowState w = mPendingRemoveTmp[i]; 9740 removeWindowInnerLocked(w.mSession, w); 9741 final DisplayContent displayContent = w.getDisplayContent(); 9742 if (displayContent != null && !displayList.contains(displayContent)) { 9743 displayList.add(displayContent); 9744 } 9745 } 9746 9747 for (DisplayContent displayContent : displayList) { 9748 assignLayersLocked(displayContent.getWindowList()); 9749 displayContent.layoutNeeded = true; 9750 } 9751 } 9752 9753 // Remove all deferred displays stacks, tasks, and activities. 9754 for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) { 9755 mDisplayContents.valueAt(displayNdx).checkForDeferredActions(); 9756 } 9757 9758 if (updateInputWindowsNeeded) { 9759 mInputMonitor.updateInputWindowsLw(false /*force*/); 9760 } 9761 setFocusedStackFrame(); 9762 9763 // Check to see if we are now in a state where the screen should 9764 // be enabled, because the window obscured flags have changed. 9765 enableScreenIfNeededLocked(); 9766 9767 scheduleAnimationLocked(); 9768 9769 if (DEBUG_WINDOW_TRACE) { 9770 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" 9771 + mAnimator.mAnimating); 9772 } 9773 } 9774 9775 private int toBrightnessOverride(float value) { 9776 return (int)(value * PowerManager.BRIGHTNESS_ON); 9777 } 9778 9779 void checkDrawnWindowsLocked() { 9780 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { 9781 return; 9782 } 9783 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { 9784 WindowState win = mWaitingForDrawn.get(j); 9785 if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win + 9786 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() + 9787 " mHasSurface=" + win.mHasSurface + 9788 " drawState=" + win.mWinAnimator.mDrawState); 9789 if (win.mRemoved || !win.mHasSurface) { 9790 // Window has been removed; no draw will now happen, so stop waiting. 9791 if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win); 9792 mWaitingForDrawn.remove(win); 9793 } else if (win.hasDrawnLw()) { 9794 // Window is now drawn (and shown). 9795 if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win); 9796 mWaitingForDrawn.remove(win); 9797 } 9798 } 9799 if (mWaitingForDrawn.isEmpty()) { 9800 if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!"); 9801 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 9802 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); 9803 } 9804 } 9805 9806 void setHoldScreenLocked(final Session newHoldScreen) { 9807 final boolean hold = newHoldScreen != null; 9808 9809 if (hold && mHoldingScreenOn != newHoldScreen) { 9810 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 9811 } 9812 mHoldingScreenOn = newHoldScreen; 9813 9814 final boolean state = mHoldingScreenWakeLock.isHeld(); 9815 if (hold != state) { 9816 if (hold) { 9817 mHoldingScreenWakeLock.acquire(); 9818 mPolicy.keepScreenOnStartedLw(); 9819 } else { 9820 mPolicy.keepScreenOnStoppedLw(); 9821 mHoldingScreenWakeLock.release(); 9822 } 9823 } 9824 } 9825 9826 void requestTraversal() { 9827 synchronized (mWindowMap) { 9828 requestTraversalLocked(); 9829 } 9830 } 9831 9832 void requestTraversalLocked() { 9833 if (!mTraversalScheduled) { 9834 mTraversalScheduled = true; 9835 mH.sendEmptyMessage(H.DO_TRAVERSAL); 9836 } 9837 } 9838 9839 /** Note that Locked in this case is on mLayoutToAnim */ 9840 void scheduleAnimationLocked() { 9841 if (!mAnimationScheduled) { 9842 mAnimationScheduled = true; 9843 mChoreographer.postCallback( 9844 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 9845 } 9846 } 9847 9848 private boolean needsLayout() { 9849 final int numDisplays = mDisplayContents.size(); 9850 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9851 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9852 if (displayContent.layoutNeeded) { 9853 return true; 9854 } 9855 } 9856 return false; 9857 } 9858 9859 boolean copyAnimToLayoutParamsLocked() { 9860 boolean doRequest = false; 9861 9862 final int bulkUpdateParams = mAnimator.mBulkUpdateParams; 9863 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 9864 mInnerFields.mUpdateRotation = true; 9865 doRequest = true; 9866 } 9867 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 9868 mInnerFields.mWallpaperMayChange = true; 9869 doRequest = true; 9870 } 9871 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 9872 mInnerFields.mWallpaperForceHidingChanged = true; 9873 doRequest = true; 9874 } 9875 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 9876 mInnerFields.mOrientationChangeComplete = false; 9877 } else { 9878 mInnerFields.mOrientationChangeComplete = true; 9879 mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource; 9880 if (mWindowsFreezingScreen) { 9881 doRequest = true; 9882 } 9883 } 9884 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 9885 mTurnOnScreen = true; 9886 } 9887 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) { 9888 mInnerFields.mWallpaperActionPending = true; 9889 } 9890 9891 return doRequest; 9892 } 9893 9894 /** If a window that has an animation specifying a colored background and the current wallpaper 9895 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 9896 * suddenly disappear. */ 9897 int adjustAnimationBackground(WindowStateAnimator winAnimator) { 9898 WindowList windows = winAnimator.mWin.getWindowList(); 9899 for (int i = windows.size() - 1; i >= 0; --i) { 9900 WindowState testWin = windows.get(i); 9901 if (testWin.mIsWallpaper && testWin.isVisibleNow()) { 9902 return testWin.mWinAnimator.mAnimLayer; 9903 } 9904 } 9905 return winAnimator.mAnimLayer; 9906 } 9907 9908 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9909 boolean secure) { 9910 final SurfaceControl surface = winAnimator.mSurfaceControl; 9911 boolean leakedSurface = false; 9912 boolean killedApps = false; 9913 9914 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9915 winAnimator.mSession.mPid, operation); 9916 9917 if (mForceRemoves == null) { 9918 mForceRemoves = new ArrayList<WindowState>(); 9919 } 9920 9921 long callingIdentity = Binder.clearCallingIdentity(); 9922 try { 9923 // There was some problem... first, do a sanity check of the 9924 // window list to make sure we haven't left any dangling surfaces 9925 // around. 9926 9927 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 9928 final int numDisplays = mDisplayContents.size(); 9929 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9930 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9931 final int numWindows = windows.size(); 9932 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9933 final WindowState ws = windows.get(winNdx); 9934 WindowStateAnimator wsa = ws.mWinAnimator; 9935 if (wsa.mSurfaceControl != null) { 9936 if (!mSessions.contains(wsa.mSession)) { 9937 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 9938 + ws + " surface=" + wsa.mSurfaceControl 9939 + " token=" + ws.mToken 9940 + " pid=" + ws.mSession.mPid 9941 + " uid=" + ws.mSession.mUid); 9942 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9943 wsa.mSurfaceControl.destroy(); 9944 wsa.mSurfaceShown = false; 9945 wsa.mSurfaceControl = null; 9946 ws.mHasSurface = false; 9947 mForceRemoves.add(ws); 9948 leakedSurface = true; 9949 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9950 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 9951 + ws + " surface=" + wsa.mSurfaceControl 9952 + " token=" + ws.mAppToken); 9953 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9954 wsa.mSurfaceControl.destroy(); 9955 wsa.mSurfaceShown = false; 9956 wsa.mSurfaceControl = null; 9957 ws.mHasSurface = false; 9958 leakedSurface = true; 9959 } 9960 } 9961 } 9962 } 9963 9964 if (!leakedSurface) { 9965 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 9966 SparseIntArray pidCandidates = new SparseIntArray(); 9967 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9968 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9969 final int numWindows = windows.size(); 9970 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9971 final WindowState ws = windows.get(winNdx); 9972 if (mForceRemoves.contains(ws)) { 9973 continue; 9974 } 9975 WindowStateAnimator wsa = ws.mWinAnimator; 9976 if (wsa.mSurfaceControl != null) { 9977 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9978 } 9979 } 9980 if (pidCandidates.size() > 0) { 9981 int[] pids = new int[pidCandidates.size()]; 9982 for (int i=0; i<pids.length; i++) { 9983 pids[i] = pidCandidates.keyAt(i); 9984 } 9985 try { 9986 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9987 killedApps = true; 9988 } 9989 } catch (RemoteException e) { 9990 } 9991 } 9992 } 9993 } 9994 9995 if (leakedSurface || killedApps) { 9996 // We managed to reclaim some memory, so get rid of the trouble 9997 // surface and ask the app to request another one. 9998 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 9999 if (surface != null) { 10000 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 10001 "RECOVER DESTROY", null); 10002 surface.destroy(); 10003 winAnimator.mSurfaceShown = false; 10004 winAnimator.mSurfaceControl = null; 10005 winAnimator.mWin.mHasSurface = false; 10006 scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken); 10007 } 10008 10009 try { 10010 winAnimator.mWin.mClient.dispatchGetNewSurface(); 10011 } catch (RemoteException e) { 10012 } 10013 } 10014 } finally { 10015 Binder.restoreCallingIdentity(callingIdentity); 10016 } 10017 10018 return leakedSurface || killedApps; 10019 } 10020 10021 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 10022 WindowState newFocus = computeFocusedWindowLocked(); 10023 if (mCurrentFocus != newFocus) { 10024 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 10025 // This check makes sure that we don't already have the focus 10026 // change message pending. 10027 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 10028 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 10029 // TODO(multidisplay): Focused windows on default display only. 10030 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10031 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked( 10032 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 10033 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES); 10034 if (imWindowChanged) { 10035 displayContent.layoutNeeded = true; 10036 newFocus = computeFocusedWindowLocked(); 10037 } 10038 10039 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " + 10040 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 10041 final WindowState oldFocus = mCurrentFocus; 10042 mCurrentFocus = newFocus; 10043 mLosingFocus.remove(newFocus); 10044 10045 // TODO(multidisplay): Accessibilty supported only of default desiplay. 10046 if (mAccessibilityController != null 10047 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 10048 mAccessibilityController.onWindowFocusChangedLocked(); 10049 } 10050 10051 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 10052 10053 if (imWindowChanged && oldFocus != mInputMethodWindow) { 10054 // Focus of the input method window changed. Perform layout if needed. 10055 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 10056 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 10057 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 10058 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 10059 // Client will do the layout, but we need to assign layers 10060 // for handleNewWindowLocked() below. 10061 assignLayersLocked(displayContent.getWindowList()); 10062 } 10063 } 10064 10065 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 10066 // The change in focus caused us to need to do a layout. Okay. 10067 displayContent.layoutNeeded = true; 10068 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 10069 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 10070 } 10071 } 10072 10073 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 10074 // If we defer assigning layers, then the caller is responsible for 10075 // doing this part. 10076 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 10077 } 10078 10079 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 10080 return true; 10081 } 10082 return false; 10083 } 10084 10085 private WindowState computeFocusedWindowLocked() { 10086 if (mAnimator.mUniverseBackground != null 10087 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 10088 return mAnimator.mUniverseBackground.mWin; 10089 } 10090 10091 final int displayCount = mDisplayContents.size(); 10092 for (int i = 0; i < displayCount; i++) { 10093 final DisplayContent displayContent = mDisplayContents.valueAt(i); 10094 WindowState win = findFocusedWindowLocked(displayContent); 10095 if (win != null) { 10096 return win; 10097 } 10098 } 10099 return null; 10100 } 10101 10102 private WindowState findFocusedWindowLocked(DisplayContent displayContent) { 10103 final WindowList windows = displayContent.getWindowList(); 10104 for (int i = windows.size() - 1; i >= 0; i--) { 10105 final WindowState win = windows.get(i); 10106 10107 if (localLOGV || DEBUG_FOCUS) Slog.v( 10108 TAG, "Looking for focus: " + i 10109 + " = " + win 10110 + ", flags=" + win.mAttrs.flags 10111 + ", canReceive=" + win.canReceiveKeys()); 10112 10113 AppWindowToken wtoken = win.mAppToken; 10114 10115 // If this window's application has been removed, just skip it. 10116 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 10117 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because " 10118 + (wtoken.removed ? "removed" : "sendingToBottom")); 10119 continue; 10120 } 10121 10122 if (!win.canReceiveKeys()) { 10123 continue; 10124 } 10125 10126 // Descend through all of the app tokens and find the first that either matches 10127 // win.mAppToken (return win) or mFocusedApp (return null). 10128 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && 10129 mFocusedApp != null) { 10130 ArrayList<Task> tasks = displayContent.getTasks(); 10131 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 10132 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 10133 int tokenNdx = tokens.size() - 1; 10134 for ( ; tokenNdx >= 0; --tokenNdx) { 10135 final AppWindowToken token = tokens.get(tokenNdx); 10136 if (wtoken == token) { 10137 break; 10138 } 10139 if (mFocusedApp == token) { 10140 // Whoops, we are below the focused app... no focus for you! 10141 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG, 10142 "findFocusedWindow: Reached focused app=" + mFocusedApp); 10143 return null; 10144 } 10145 } 10146 if (tokenNdx >= 0) { 10147 // Early exit from loop, must have found the matching token. 10148 break; 10149 } 10150 } 10151 } 10152 10153 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i + 10154 " = " + win); 10155 return win; 10156 } 10157 10158 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows."); 10159 return null; 10160 } 10161 10162 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 10163 if (mDisplayFrozen) { 10164 return; 10165 } 10166 10167 if (!mDisplayReady || !mPolicy.isScreenOnFully()) { 10168 // No need to freeze the screen before the system is ready or if 10169 // the screen is off. 10170 return; 10171 } 10172 10173 mScreenFrozenLock.acquire(); 10174 10175 mDisplayFrozen = true; 10176 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 10177 mLastFinishedFreezeSource = null; 10178 10179 mInputMonitor.freezeInputDispatchingLw(); 10180 10181 // Clear the last input window -- that is just used for 10182 // clean transitions between IMEs, and if we are freezing 10183 // the screen then the whole world is changing behind the scenes. 10184 mPolicy.setLastInputMethodWindowLw(null, null); 10185 10186 if (mAppTransition.isTransitionSet()) { 10187 mAppTransition.freeze(); 10188 } 10189 10190 if (PROFILE_ORIENTATION) { 10191 File file = new File("/data/system/frozen"); 10192 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 10193 } 10194 10195 if (CUSTOM_SCREEN_ROTATION) { 10196 mExitAnimId = exitAnim; 10197 mEnterAnimId = enterAnim; 10198 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10199 final int displayId = displayContent.getDisplayId(); 10200 ScreenRotationAnimation screenRotationAnimation = 10201 mAnimator.getScreenRotationAnimationLocked(displayId); 10202 if (screenRotationAnimation != null) { 10203 screenRotationAnimation.kill(); 10204 } 10205 10206 // Check whether the current screen contains any secure content. 10207 boolean isSecure = false; 10208 final WindowList windows = getDefaultWindowListLocked(); 10209 final int N = windows.size(); 10210 for (int i = 0; i < N; i++) { 10211 WindowState ws = windows.get(i); 10212 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) { 10213 isSecure = true; 10214 break; 10215 } 10216 } 10217 10218 // TODO(multidisplay): rotation on main screen only. 10219 displayContent.updateDisplayInfo(); 10220 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 10221 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure); 10222 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10223 } 10224 } 10225 10226 private void stopFreezingDisplayLocked() { 10227 if (!mDisplayFrozen) { 10228 return; 10229 } 10230 10231 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen 10232 || mClientFreezingScreen) { 10233 if (DEBUG_ORIENTATION) Slog.d(TAG, 10234 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 10235 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 10236 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 10237 + ", mClientFreezingScreen=" + mClientFreezingScreen); 10238 return; 10239 } 10240 10241 mDisplayFrozen = false; 10242 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 10243 StringBuilder sb = new StringBuilder(128); 10244 sb.append("Screen frozen for "); 10245 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 10246 if (mLastFinishedFreezeSource != null) { 10247 sb.append(" due to "); 10248 sb.append(mLastFinishedFreezeSource); 10249 } 10250 Slog.i(TAG, sb.toString()); 10251 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 10252 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 10253 if (PROFILE_ORIENTATION) { 10254 Debug.stopMethodTracing(); 10255 } 10256 10257 boolean updateRotation = false; 10258 10259 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10260 final int displayId = displayContent.getDisplayId(); 10261 ScreenRotationAnimation screenRotationAnimation = 10262 mAnimator.getScreenRotationAnimationLocked(displayId); 10263 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 10264 && screenRotationAnimation.hasScreenshot()) { 10265 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 10266 // TODO(multidisplay): rotation on main screen only. 10267 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10268 // Get rotation animation again, with new top window 10269 boolean isDimming = displayContent.isDimming(); 10270 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 10271 mExitAnimId = mEnterAnimId = 0; 10272 } 10273 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 10274 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, 10275 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 10276 scheduleAnimationLocked(); 10277 } else { 10278 screenRotationAnimation.kill(); 10279 screenRotationAnimation = null; 10280 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10281 updateRotation = true; 10282 } 10283 } else { 10284 if (screenRotationAnimation != null) { 10285 screenRotationAnimation.kill(); 10286 screenRotationAnimation = null; 10287 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10288 } 10289 updateRotation = true; 10290 } 10291 10292 mInputMonitor.thawInputDispatchingLw(); 10293 10294 boolean configChanged; 10295 10296 // While the display is frozen we don't re-compute the orientation 10297 // to avoid inconsistent states. However, something interesting 10298 // could have actually changed during that time so re-evaluate it 10299 // now to catch that. 10300 configChanged = updateOrientationFromAppTokensLocked(false); 10301 10302 // A little kludge: a lot could have happened while the 10303 // display was frozen, so now that we are coming back we 10304 // do a gc so that any remote references the system 10305 // processes holds on others can be released if they are 10306 // no longer needed. 10307 mH.removeMessages(H.FORCE_GC); 10308 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 10309 10310 mScreenFrozenLock.release(); 10311 10312 if (updateRotation) { 10313 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 10314 configChanged |= updateRotationUncheckedLocked(false); 10315 } 10316 10317 if (configChanged) { 10318 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10319 } 10320 } 10321 10322 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 10323 DisplayMetrics dm) { 10324 if (index < tokens.length) { 10325 String str = tokens[index]; 10326 if (str != null && str.length() > 0) { 10327 try { 10328 int val = Integer.parseInt(str); 10329 return val; 10330 } catch (Exception e) { 10331 } 10332 } 10333 } 10334 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 10335 return defDps; 10336 } 10337 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 10338 return val; 10339 } 10340 10341 void createWatermarkInTransaction() { 10342 if (mWatermark != null) { 10343 return; 10344 } 10345 10346 File file = new File("/system/etc/setup.conf"); 10347 FileInputStream in = null; 10348 DataInputStream ind = null; 10349 try { 10350 in = new FileInputStream(file); 10351 ind = new DataInputStream(in); 10352 String line = ind.readLine(); 10353 if (line != null) { 10354 String[] toks = line.split("%"); 10355 if (toks != null && toks.length > 0) { 10356 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 10357 mRealDisplayMetrics, mFxSession, toks); 10358 } 10359 } 10360 } catch (FileNotFoundException e) { 10361 } catch (IOException e) { 10362 } finally { 10363 if (ind != null) { 10364 try { 10365 ind.close(); 10366 } catch (IOException e) { 10367 } 10368 } else if (in != null) { 10369 try { 10370 in.close(); 10371 } catch (IOException e) { 10372 } 10373 } 10374 } 10375 } 10376 10377 @Override 10378 public void statusBarVisibilityChanged(int visibility) { 10379 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10380 != PackageManager.PERMISSION_GRANTED) { 10381 throw new SecurityException("Caller does not hold permission " 10382 + android.Manifest.permission.STATUS_BAR); 10383 } 10384 10385 synchronized (mWindowMap) { 10386 mLastStatusBarVisibility = visibility; 10387 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 10388 updateStatusBarVisibilityLocked(visibility); 10389 } 10390 } 10391 10392 // TOOD(multidisplay): StatusBar on multiple screens? 10393 void updateStatusBarVisibilityLocked(int visibility) { 10394 mInputManager.setSystemUiVisibility(visibility); 10395 final WindowList windows = getDefaultWindowListLocked(); 10396 final int N = windows.size(); 10397 for (int i = 0; i < N; i++) { 10398 WindowState ws = windows.get(i); 10399 try { 10400 int curValue = ws.mSystemUiVisibility; 10401 int diff = curValue ^ visibility; 10402 // We are only interested in differences of one of the 10403 // clearable flags... 10404 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 10405 // ...if it has actually been cleared. 10406 diff &= ~visibility; 10407 int newValue = (curValue&~diff) | (visibility&diff); 10408 if (newValue != curValue) { 10409 ws.mSeq++; 10410 ws.mSystemUiVisibility = newValue; 10411 } 10412 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 10413 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 10414 visibility, newValue, diff); 10415 } 10416 } catch (RemoteException e) { 10417 // so sorry 10418 } 10419 } 10420 } 10421 10422 @Override 10423 public void reevaluateStatusBarVisibility() { 10424 synchronized (mWindowMap) { 10425 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 10426 updateStatusBarVisibilityLocked(visibility); 10427 performLayoutAndPlaceSurfacesLocked(); 10428 } 10429 } 10430 10431 @Override 10432 public FakeWindow addFakeWindow(Looper looper, 10433 InputEventReceiver.Factory inputEventReceiverFactory, 10434 String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags, 10435 boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) { 10436 synchronized (mWindowMap) { 10437 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 10438 name, windowType, 10439 layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys, 10440 hasFocus, touchFullscreen); 10441 int i=0; 10442 while (i<mFakeWindows.size()) { 10443 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 10444 break; 10445 } 10446 } 10447 mFakeWindows.add(i, fw); 10448 mInputMonitor.updateInputWindowsLw(true); 10449 return fw; 10450 } 10451 } 10452 10453 boolean removeFakeWindowLocked(FakeWindow window) { 10454 synchronized (mWindowMap) { 10455 if (mFakeWindows.remove(window)) { 10456 mInputMonitor.updateInputWindowsLw(true); 10457 return true; 10458 } 10459 return false; 10460 } 10461 } 10462 10463 // It is assumed that this method is called only by InputMethodManagerService. 10464 public void saveLastInputMethodWindowForTransition() { 10465 synchronized (mWindowMap) { 10466 // TODO(multidisplay): Pass in the displayID. 10467 DisplayContent displayContent = getDefaultDisplayContentLocked(); 10468 if (mInputMethodWindow != null) { 10469 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 10470 } 10471 } 10472 } 10473 10474 public int getInputMethodWindowVisibleHeight() { 10475 synchronized (mWindowMap) { 10476 return mPolicy.getInputMethodWindowVisibleHeightLw(); 10477 } 10478 } 10479 10480 @Override 10481 public boolean hasNavigationBar() { 10482 return mPolicy.hasNavigationBar(); 10483 } 10484 10485 @Override 10486 public void lockNow(Bundle options) { 10487 mPolicy.lockNow(options); 10488 } 10489 10490 public void showRecentApps() { 10491 mPolicy.showRecentApps(); 10492 } 10493 10494 @Override 10495 public boolean isSafeModeEnabled() { 10496 return mSafeMode; 10497 } 10498 10499 @Override 10500 public boolean clearWindowContentFrameStats(IBinder token) { 10501 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10502 "clearWindowContentFrameStats()")) { 10503 throw new SecurityException("Requires FRAME_STATS permission"); 10504 } 10505 synchronized (mWindowMap) { 10506 WindowState windowState = mWindowMap.get(token); 10507 if (windowState == null) { 10508 return false; 10509 } 10510 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10511 if (surfaceControl == null) { 10512 return false; 10513 } 10514 return surfaceControl.clearContentFrameStats(); 10515 } 10516 } 10517 10518 @Override 10519 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) { 10520 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10521 "getWindowContentFrameStats()")) { 10522 throw new SecurityException("Requires FRAME_STATS permission"); 10523 } 10524 synchronized (mWindowMap) { 10525 WindowState windowState = mWindowMap.get(token); 10526 if (windowState == null) { 10527 return null; 10528 } 10529 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10530 if (surfaceControl == null) { 10531 return null; 10532 } 10533 if (mTempWindowRenderStats == null) { 10534 mTempWindowRenderStats = new WindowContentFrameStats(); 10535 } 10536 WindowContentFrameStats stats = mTempWindowRenderStats; 10537 if (!surfaceControl.getContentFrameStats(stats)) { 10538 return null; 10539 } 10540 return stats; 10541 } 10542 } 10543 10544 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10545 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 10546 mPolicy.dump(" ", pw, args); 10547 } 10548 10549 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10550 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 10551 mAnimator.dumpLocked(pw, " ", dumpAll); 10552 } 10553 10554 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 10555 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 10556 if (mTokenMap.size() > 0) { 10557 pw.println(" All tokens:"); 10558 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10559 while (it.hasNext()) { 10560 WindowToken token = it.next(); 10561 pw.print(" "); pw.print(token); 10562 if (dumpAll) { 10563 pw.println(':'); 10564 token.dump(pw, " "); 10565 } else { 10566 pw.println(); 10567 } 10568 } 10569 } 10570 if (mWallpaperTokens.size() > 0) { 10571 pw.println(); 10572 pw.println(" Wallpaper tokens:"); 10573 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 10574 WindowToken token = mWallpaperTokens.get(i); 10575 pw.print(" Wallpaper #"); pw.print(i); 10576 pw.print(' '); pw.print(token); 10577 if (dumpAll) { 10578 pw.println(':'); 10579 token.dump(pw, " "); 10580 } else { 10581 pw.println(); 10582 } 10583 } 10584 } 10585 if (mFinishedStarting.size() > 0) { 10586 pw.println(); 10587 pw.println(" Finishing start of application tokens:"); 10588 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10589 WindowToken token = mFinishedStarting.get(i); 10590 pw.print(" Finished Starting #"); pw.print(i); 10591 pw.print(' '); pw.print(token); 10592 if (dumpAll) { 10593 pw.println(':'); 10594 token.dump(pw, " "); 10595 } else { 10596 pw.println(); 10597 } 10598 } 10599 } 10600 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 10601 pw.println(); 10602 if (mOpeningApps.size() > 0) { 10603 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10604 } 10605 if (mClosingApps.size() > 0) { 10606 pw.print(" mClosingApps="); pw.println(mClosingApps); 10607 } 10608 } 10609 } 10610 10611 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 10612 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 10613 for (int i=0; i<mSessions.size(); i++) { 10614 Session s = mSessions.valueAt(i); 10615 pw.print(" Session "); pw.print(s); pw.println(':'); 10616 s.dump(pw, " "); 10617 } 10618 } 10619 10620 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 10621 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 10622 if (mDisplayReady) { 10623 final int numDisplays = mDisplayContents.size(); 10624 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10625 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10626 displayContent.dump(" ", pw); 10627 } 10628 } else { 10629 pw.println(" NO DISPLAY"); 10630 } 10631 } 10632 10633 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 10634 ArrayList<WindowState> windows) { 10635 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 10636 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 10637 } 10638 10639 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 10640 ArrayList<WindowState> windows) { 10641 final int numDisplays = mDisplayContents.size(); 10642 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10643 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); 10644 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10645 final WindowState w = windowList.get(winNdx); 10646 if (windows == null || windows.contains(w)) { 10647 pw.print(" Window #"); pw.print(winNdx); pw.print(' '); 10648 pw.print(w); pw.println(":"); 10649 w.dump(pw, " ", dumpAll || windows != null); 10650 } 10651 } 10652 } 10653 if (mInputMethodDialogs.size() > 0) { 10654 pw.println(); 10655 pw.println(" Input method dialogs:"); 10656 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 10657 WindowState w = mInputMethodDialogs.get(i); 10658 if (windows == null || windows.contains(w)) { 10659 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 10660 } 10661 } 10662 } 10663 if (mPendingRemove.size() > 0) { 10664 pw.println(); 10665 pw.println(" Remove pending for:"); 10666 for (int i=mPendingRemove.size()-1; i>=0; i--) { 10667 WindowState w = mPendingRemove.get(i); 10668 if (windows == null || windows.contains(w)) { 10669 pw.print(" Remove #"); pw.print(i); pw.print(' '); 10670 pw.print(w); 10671 if (dumpAll) { 10672 pw.println(":"); 10673 w.dump(pw, " ", true); 10674 } else { 10675 pw.println(); 10676 } 10677 } 10678 } 10679 } 10680 if (mForceRemoves != null && mForceRemoves.size() > 0) { 10681 pw.println(); 10682 pw.println(" Windows force removing:"); 10683 for (int i=mForceRemoves.size()-1; i>=0; i--) { 10684 WindowState w = mForceRemoves.get(i); 10685 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10686 pw.print(w); 10687 if (dumpAll) { 10688 pw.println(":"); 10689 w.dump(pw, " ", true); 10690 } else { 10691 pw.println(); 10692 } 10693 } 10694 } 10695 if (mDestroySurface.size() > 0) { 10696 pw.println(); 10697 pw.println(" Windows waiting to destroy their surface:"); 10698 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10699 WindowState w = mDestroySurface.get(i); 10700 if (windows == null || windows.contains(w)) { 10701 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10702 pw.print(w); 10703 if (dumpAll) { 10704 pw.println(":"); 10705 w.dump(pw, " ", true); 10706 } else { 10707 pw.println(); 10708 } 10709 } 10710 } 10711 } 10712 if (mLosingFocus.size() > 0) { 10713 pw.println(); 10714 pw.println(" Windows losing focus:"); 10715 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10716 WindowState w = mLosingFocus.get(i); 10717 if (windows == null || windows.contains(w)) { 10718 pw.print(" Losing #"); pw.print(i); pw.print(' '); 10719 pw.print(w); 10720 if (dumpAll) { 10721 pw.println(":"); 10722 w.dump(pw, " ", true); 10723 } else { 10724 pw.println(); 10725 } 10726 } 10727 } 10728 } 10729 if (mResizingWindows.size() > 0) { 10730 pw.println(); 10731 pw.println(" Windows waiting to resize:"); 10732 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10733 WindowState w = mResizingWindows.get(i); 10734 if (windows == null || windows.contains(w)) { 10735 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 10736 pw.print(w); 10737 if (dumpAll) { 10738 pw.println(":"); 10739 w.dump(pw, " ", true); 10740 } else { 10741 pw.println(); 10742 } 10743 } 10744 } 10745 } 10746 if (mWaitingForDrawn.size() > 0) { 10747 pw.println(); 10748 pw.println(" Clients waiting for these windows to be drawn:"); 10749 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10750 WindowState win = mWaitingForDrawn.get(i); 10751 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); 10752 } 10753 } 10754 pw.println(); 10755 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10756 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10757 if (mLastFocus != mCurrentFocus) { 10758 pw.print(" mLastFocus="); pw.println(mLastFocus); 10759 } 10760 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10761 if (mInputMethodTarget != null) { 10762 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10763 } 10764 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10765 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10766 pw.print(" mLastDisplayFreezeDuration="); 10767 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 10768 if ( mLastFinishedFreezeSource != null) { 10769 pw.print(" due to "); 10770 pw.print(mLastFinishedFreezeSource); 10771 } 10772 pw.println(); 10773 if (dumpAll) { 10774 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 10775 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 10776 if (mLastStatusBarVisibility != 0) { 10777 pw.print(" mLastStatusBarVisibility=0x"); 10778 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 10779 } 10780 if (mInputMethodWindow != null) { 10781 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10782 } 10783 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 10784 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) { 10785 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 10786 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 10787 } 10788 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 10789 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 10790 if (mInputMethodAnimLayerAdjustment != 0 || 10791 mWallpaperAnimLayerAdjustment != 0) { 10792 pw.print(" mInputMethodAnimLayerAdjustment="); 10793 pw.print(mInputMethodAnimLayerAdjustment); 10794 pw.print(" mWallpaperAnimLayerAdjustment="); 10795 pw.println(mWallpaperAnimLayerAdjustment); 10796 } 10797 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10798 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10799 if (needsLayout()) { 10800 pw.print(" layoutNeeded on displays="); 10801 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10802 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10803 if (displayContent.layoutNeeded) { 10804 pw.print(displayContent.getDisplayId()); 10805 } 10806 } 10807 pw.println(); 10808 } 10809 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 10810 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10811 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 10812 pw.print(" client="); pw.print(mClientFreezingScreen); 10813 pw.print(" apps="); pw.print(mAppsFreezingScreen); 10814 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 10815 pw.print(" mRotation="); pw.print(mRotation); 10816 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 10817 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 10818 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 10819 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 10820 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled); 10821 pw.print(" window="); pw.print(mWindowAnimationScaleSetting); 10822 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); 10823 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); 10824 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); 10825 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 10826 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 10827 pw.println(" mLayoutToAnim:"); 10828 mAppTransition.dump(pw); 10829 } 10830 } 10831 10832 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10833 int opti, boolean dumpAll) { 10834 WindowList windows = new WindowList(); 10835 if ("visible".equals(name)) { 10836 synchronized(mWindowMap) { 10837 final int numDisplays = mDisplayContents.size(); 10838 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10839 final WindowList windowList = 10840 mDisplayContents.valueAt(displayNdx).getWindowList(); 10841 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10842 final WindowState w = windowList.get(winNdx); 10843 if (w.mWinAnimator.mSurfaceShown) { 10844 windows.add(w); 10845 } 10846 } 10847 } 10848 } 10849 } else { 10850 int objectId = 0; 10851 // See if this is an object ID. 10852 try { 10853 objectId = Integer.parseInt(name, 16); 10854 name = null; 10855 } catch (RuntimeException e) { 10856 } 10857 synchronized(mWindowMap) { 10858 final int numDisplays = mDisplayContents.size(); 10859 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10860 final WindowList windowList = 10861 mDisplayContents.valueAt(displayNdx).getWindowList(); 10862 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10863 final WindowState w = windowList.get(winNdx); 10864 if (name != null) { 10865 if (w.mAttrs.getTitle().toString().contains(name)) { 10866 windows.add(w); 10867 } 10868 } else if (System.identityHashCode(w) == objectId) { 10869 windows.add(w); 10870 } 10871 } 10872 } 10873 } 10874 } 10875 10876 if (windows.size() <= 0) { 10877 return false; 10878 } 10879 10880 synchronized(mWindowMap) { 10881 dumpWindowsLocked(pw, dumpAll, windows); 10882 } 10883 return true; 10884 } 10885 10886 void dumpLastANRLocked(PrintWriter pw) { 10887 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10888 if (mLastANRState == null) { 10889 pw.println(" <no ANR has occurred since boot>"); 10890 } else { 10891 pw.println(mLastANRState); 10892 } 10893 } 10894 10895 /** 10896 * Saves information about the state of the window manager at 10897 * the time an ANR occurred before anything else in the system changes 10898 * in response. 10899 * 10900 * @param appWindowToken The application that ANR'd, may be null. 10901 * @param windowState The window that ANR'd, may be null. 10902 * @param reason The reason for the ANR, may be null. 10903 */ 10904 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, 10905 String reason) { 10906 StringWriter sw = new StringWriter(); 10907 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 10908 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10909 if (appWindowToken != null) { 10910 pw.println(" Application at fault: " + appWindowToken.stringName); 10911 } 10912 if (windowState != null) { 10913 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10914 } 10915 if (reason != null) { 10916 pw.println(" Reason: " + reason); 10917 } 10918 pw.println(); 10919 dumpWindowsNoHeaderLocked(pw, true, null); 10920 pw.close(); 10921 mLastANRState = sw.toString(); 10922 } 10923 10924 @Override 10925 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10926 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10927 != PackageManager.PERMISSION_GRANTED) { 10928 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10929 + Binder.getCallingPid() 10930 + ", uid=" + Binder.getCallingUid()); 10931 return; 10932 } 10933 10934 boolean dumpAll = false; 10935 10936 int opti = 0; 10937 while (opti < args.length) { 10938 String opt = args[opti]; 10939 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10940 break; 10941 } 10942 opti++; 10943 if ("-a".equals(opt)) { 10944 dumpAll = true; 10945 } else if ("-h".equals(opt)) { 10946 pw.println("Window manager dump options:"); 10947 pw.println(" [-a] [-h] [cmd] ..."); 10948 pw.println(" cmd may be one of:"); 10949 pw.println(" l[astanr]: last ANR information"); 10950 pw.println(" p[policy]: policy state"); 10951 pw.println(" a[animator]: animator state"); 10952 pw.println(" s[essions]: active sessions"); 10953 pw.println(" d[isplays]: active display contents"); 10954 pw.println(" t[okens]: token list"); 10955 pw.println(" w[indows]: window list"); 10956 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10957 pw.println(" be a partial substring in a window name, a"); 10958 pw.println(" Window hex object identifier, or"); 10959 pw.println(" \"all\" for all windows, or"); 10960 pw.println(" \"visible\" for the visible windows."); 10961 pw.println(" -a: include all available server state."); 10962 return; 10963 } else { 10964 pw.println("Unknown argument: " + opt + "; use -h for help"); 10965 } 10966 } 10967 10968 // Is the caller requesting to dump a particular piece of data? 10969 if (opti < args.length) { 10970 String cmd = args[opti]; 10971 opti++; 10972 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10973 synchronized(mWindowMap) { 10974 dumpLastANRLocked(pw); 10975 } 10976 return; 10977 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10978 synchronized(mWindowMap) { 10979 dumpPolicyLocked(pw, args, true); 10980 } 10981 return; 10982 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 10983 synchronized(mWindowMap) { 10984 dumpAnimatorLocked(pw, args, true); 10985 } 10986 return; 10987 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10988 synchronized(mWindowMap) { 10989 dumpSessionsLocked(pw, true); 10990 } 10991 return; 10992 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 10993 synchronized(mWindowMap) { 10994 dumpDisplayContentsLocked(pw, true); 10995 } 10996 return; 10997 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10998 synchronized(mWindowMap) { 10999 dumpTokensLocked(pw, true); 11000 } 11001 return; 11002 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 11003 synchronized(mWindowMap) { 11004 dumpWindowsLocked(pw, true, null); 11005 } 11006 return; 11007 } else if ("all".equals(cmd) || "a".equals(cmd)) { 11008 synchronized(mWindowMap) { 11009 dumpWindowsLocked(pw, true, null); 11010 } 11011 return; 11012 } else { 11013 // Dumping a single name? 11014 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 11015 pw.println("Bad window command, or no windows match: " + cmd); 11016 pw.println("Use -h for help."); 11017 } 11018 return; 11019 } 11020 } 11021 11022 synchronized(mWindowMap) { 11023 pw.println(); 11024 if (dumpAll) { 11025 pw.println("-------------------------------------------------------------------------------"); 11026 } 11027 dumpLastANRLocked(pw); 11028 pw.println(); 11029 if (dumpAll) { 11030 pw.println("-------------------------------------------------------------------------------"); 11031 } 11032 dumpPolicyLocked(pw, args, dumpAll); 11033 pw.println(); 11034 if (dumpAll) { 11035 pw.println("-------------------------------------------------------------------------------"); 11036 } 11037 dumpAnimatorLocked(pw, args, dumpAll); 11038 pw.println(); 11039 if (dumpAll) { 11040 pw.println("-------------------------------------------------------------------------------"); 11041 } 11042 dumpSessionsLocked(pw, dumpAll); 11043 pw.println(); 11044 if (dumpAll) { 11045 pw.println("-------------------------------------------------------------------------------"); 11046 } 11047 dumpDisplayContentsLocked(pw, dumpAll); 11048 pw.println(); 11049 if (dumpAll) { 11050 pw.println("-------------------------------------------------------------------------------"); 11051 } 11052 dumpTokensLocked(pw, dumpAll); 11053 pw.println(); 11054 if (dumpAll) { 11055 pw.println("-------------------------------------------------------------------------------"); 11056 } 11057 dumpWindowsLocked(pw, dumpAll, null); 11058 } 11059 } 11060 11061 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 11062 @Override 11063 public void monitor() { 11064 synchronized (mWindowMap) { } 11065 } 11066 11067 public interface OnHardKeyboardStatusChangeListener { 11068 public void onHardKeyboardStatusChange(boolean available); 11069 } 11070 11071 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 11072 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 11073 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 11074 Integer.toHexString(pendingLayoutChanges)); 11075 } 11076 } 11077 11078 private DisplayContent newDisplayContentLocked(final Display display) { 11079 DisplayContent displayContent = new DisplayContent(display, this); 11080 final int displayId = display.getDisplayId(); 11081 if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display); 11082 mDisplayContents.put(displayId, displayContent); 11083 11084 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 11085 final Rect rect = new Rect(); 11086 mDisplaySettings.getOverscanLocked(displayInfo.name, rect); 11087 synchronized (displayContent.mDisplaySizeLock) { 11088 displayInfo.overscanLeft = rect.left; 11089 displayInfo.overscanTop = rect.top; 11090 displayInfo.overscanRight = rect.right; 11091 displayInfo.overscanBottom = rect.bottom; 11092 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 11093 displayId, displayInfo); 11094 } 11095 configureDisplayPolicyLocked(displayContent); 11096 11097 // TODO: Create an input channel for each display with touch capability. 11098 if (displayId == Display.DEFAULT_DISPLAY) { 11099 displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent); 11100 registerPointerEventListener(displayContent.mTapDetector); 11101 } 11102 11103 return displayContent; 11104 } 11105 11106 public void createDisplayContentLocked(final Display display) { 11107 if (display == null) { 11108 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 11109 } 11110 getDisplayContentLocked(display.getDisplayId()); 11111 } 11112 11113 /** 11114 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 11115 * there is a Display for the displayId. 11116 * @param displayId The display the caller is interested in. 11117 * @return The DisplayContent associated with displayId or null if there is no Display for it. 11118 */ 11119 public DisplayContent getDisplayContentLocked(final int displayId) { 11120 DisplayContent displayContent = mDisplayContents.get(displayId); 11121 if (displayContent == null) { 11122 final Display display = mDisplayManager.getDisplay(displayId); 11123 if (display != null) { 11124 displayContent = newDisplayContentLocked(display); 11125 } 11126 } 11127 return displayContent; 11128 } 11129 11130 // There is an inherent assumption that this will never return null. 11131 public DisplayContent getDefaultDisplayContentLocked() { 11132 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 11133 } 11134 11135 public WindowList getDefaultWindowListLocked() { 11136 return getDefaultDisplayContentLocked().getWindowList(); 11137 } 11138 11139 public DisplayInfo getDefaultDisplayInfoLocked() { 11140 return getDefaultDisplayContentLocked().getDisplayInfo(); 11141 } 11142 11143 /** 11144 * Return the list of WindowStates associated on the passed display. 11145 * @param display The screen to return windows from. 11146 * @return The list of WindowStates on the screen, or null if the there is no screen. 11147 */ 11148 public WindowList getWindowListLocked(final Display display) { 11149 return getWindowListLocked(display.getDisplayId()); 11150 } 11151 11152 /** 11153 * Return the list of WindowStates associated on the passed display. 11154 * @param displayId The screen to return windows from. 11155 * @return The list of WindowStates on the screen, or null if the there is no screen. 11156 */ 11157 public WindowList getWindowListLocked(final int displayId) { 11158 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11159 return displayContent != null ? displayContent.getWindowList() : null; 11160 } 11161 11162 public void onDisplayAdded(int displayId) { 11163 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 11164 } 11165 11166 public void handleDisplayAdded(int displayId) { 11167 synchronized (mWindowMap) { 11168 final Display display = mDisplayManager.getDisplay(displayId); 11169 if (display != null) { 11170 createDisplayContentLocked(display); 11171 displayReady(displayId); 11172 } 11173 } 11174 } 11175 11176 public void onDisplayRemoved(int displayId) { 11177 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 11178 } 11179 11180 private void handleDisplayRemovedLocked(int displayId) { 11181 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11182 if (displayContent != null) { 11183 if (displayContent.isAnimating()) { 11184 displayContent.mDeferredRemoval = true; 11185 return; 11186 } 11187 if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent); 11188 mDisplayContents.delete(displayId); 11189 displayContent.close(); 11190 if (displayId == Display.DEFAULT_DISPLAY) { 11191 unregisterPointerEventListener(displayContent.mTapDetector); 11192 } 11193 } 11194 mAnimator.removeDisplayLocked(displayId); 11195 } 11196 11197 public void onDisplayChanged(int displayId) { 11198 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 11199 } 11200 11201 private void handleDisplayChangedLocked(int displayId) { 11202 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11203 if (displayContent != null) { 11204 displayContent.updateDisplayInfo(); 11205 } 11206 } 11207 11208 @Override 11209 public Object getWindowManagerLock() { 11210 return mWindowMap; 11211 } 11212 11213 private final class LocalService extends WindowManagerInternal { 11214 @Override 11215 public void requestTraversalFromDisplayManager() { 11216 requestTraversal(); 11217 } 11218 11219 @Override 11220 public void setMagnificationSpec(MagnificationSpec spec) { 11221 synchronized (mWindowMap) { 11222 if (mAccessibilityController != null) { 11223 mAccessibilityController.setMagnificationSpecLocked(spec); 11224 } else { 11225 throw new IllegalStateException("Magnification callbacks not set!"); 11226 } 11227 } 11228 if (Binder.getCallingPid() != android.os.Process.myPid()) { 11229 spec.recycle(); 11230 } 11231 } 11232 11233 @Override 11234 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { 11235 synchronized (mWindowMap) { 11236 WindowState windowState = mWindowMap.get(windowToken); 11237 if (windowState == null) { 11238 return null; 11239 } 11240 MagnificationSpec spec = null; 11241 if (mAccessibilityController != null) { 11242 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState); 11243 } 11244 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) { 11245 return null; 11246 } 11247 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec); 11248 spec.scale *= windowState.mGlobalScale; 11249 return spec; 11250 } 11251 } 11252 11253 @Override 11254 public void setMagnificationCallbacks(MagnificationCallbacks callbacks) { 11255 synchronized (mWindowMap) { 11256 if (mAccessibilityController == null) { 11257 mAccessibilityController = new AccessibilityController( 11258 WindowManagerService.this); 11259 } 11260 mAccessibilityController.setMagnificationCallbacksLocked(callbacks); 11261 if (!mAccessibilityController.hasCallbacksLocked()) { 11262 mAccessibilityController = null; 11263 } 11264 } 11265 } 11266 11267 @Override 11268 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) { 11269 synchronized (mWindowMap) { 11270 if (mAccessibilityController == null) { 11271 mAccessibilityController = new AccessibilityController( 11272 WindowManagerService.this); 11273 } 11274 mAccessibilityController.setWindowsForAccessibilityCallback(callback); 11275 if (!mAccessibilityController.hasCallbacksLocked()) { 11276 mAccessibilityController = null; 11277 } 11278 } 11279 } 11280 11281 @Override 11282 public void setInputFilter(IInputFilter filter) { 11283 mInputManager.setInputFilter(filter); 11284 } 11285 11286 @Override 11287 public IBinder getFocusedWindowToken() { 11288 synchronized (mWindowMap) { 11289 WindowState windowState = getFocusedWindowLocked(); 11290 if (windowState != null) { 11291 return windowState.mClient.asBinder(); 11292 } 11293 return null; 11294 } 11295 } 11296 11297 @Override 11298 public boolean isKeyguardLocked() { 11299 return WindowManagerService.this.isKeyguardLocked(); 11300 } 11301 11302 @Override 11303 public void showGlobalActions() { 11304 WindowManagerService.this.showGlobalActions(); 11305 } 11306 11307 @Override 11308 public void getWindowFrame(IBinder token, Rect outBounds) { 11309 synchronized (mWindowMap) { 11310 WindowState windowState = mWindowMap.get(token); 11311 if (windowState != null) { 11312 outBounds.set(windowState.mFrame); 11313 } else { 11314 outBounds.setEmpty(); 11315 } 11316 } 11317 } 11318 11319 public void waitForAllWindowsDrawn(Runnable callback, long timeout) { 11320 synchronized (mWindowMap) { 11321 mWaitingForDrawnCallback = callback; 11322 final WindowList windows = getDefaultWindowListLocked(); 11323 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 11324 final WindowState win = windows.get(winNdx); 11325 if (win.mHasSurface && win.mAppToken != null) { 11326 win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 11327 // Force add to mResizingWindows. 11328 win.mLastContentInsets.set(-1, -1, -1, -1); 11329 mWaitingForDrawn.add(win); 11330 } 11331 } 11332 requestTraversalLocked(); 11333 } 11334 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 11335 if (mWaitingForDrawn.isEmpty()) { 11336 callback.run(); 11337 } else { 11338 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); 11339 checkDrawnWindowsLocked(); 11340 } 11341 } 11342 } 11343} 11344