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