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