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