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