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.ActivityManager; 25 import android.app.ActivityManagerInternal; 26 import android.app.ActivityManagerNative; 27 import android.app.AppOpsManager; 28 import android.app.IActivityManager; 29 import android.app.Notification; 30 import android.app.NotificationManager; 31 import android.app.PendingIntent; 32 import android.app.admin.DevicePolicyManager; 33 import android.content.BroadcastReceiver; 34 import android.content.ContentResolver; 35 import android.content.Context; 36 import android.content.Intent; 37 import android.content.IntentFilter; 38 import android.content.pm.ActivityInfo; 39 import android.content.pm.ApplicationInfo; 40 import android.content.pm.PackageManager; 41 import android.content.res.CompatibilityInfo; 42 import android.content.res.Configuration; 43 import android.database.ContentObserver; 44 import android.graphics.Bitmap; 45 import android.graphics.PixelFormat; 46 import android.graphics.Matrix; 47 import android.graphics.Point; 48 import android.graphics.Rect; 49 import android.graphics.RectF; 50 import android.graphics.Region; 51 import android.hardware.display.DisplayManager; 52 import android.hardware.display.DisplayManagerInternal; 53 import android.hardware.input.InputManager; 54 import android.net.Uri; 55 import android.os.Binder; 56 import android.os.Build; 57 import android.os.Bundle; 58 import android.os.Debug; 59 import android.os.Handler; 60 import android.os.IBinder; 61 import android.os.IRemoteCallback; 62 import android.os.Looper; 63 import android.os.Message; 64 import android.os.Parcel; 65 import android.os.ParcelFileDescriptor; 66 import android.os.PowerManager; 67 import android.os.PowerManagerInternal; 68 import android.os.Process; 69 import android.os.RemoteException; 70 import android.os.ServiceManager; 71 import android.os.StrictMode; 72 import android.os.SystemClock; 73 import android.os.SystemProperties; 74 import android.os.SystemService; 75 import android.os.Trace; 76 import android.os.UserHandle; 77 import android.os.WorkSource; 78 import android.provider.Settings; 79 import android.util.ArraySet; 80 import android.util.DisplayMetrics; 81 import android.util.EventLog; 82 import android.util.Log; 83 import android.util.Pair; 84 import android.util.Slog; 85 import android.util.SparseArray; 86 import android.util.SparseIntArray; 87 import android.util.TimeUtils; 88 import android.util.TypedValue; 89 import android.view.AppTransitionAnimationSpec; 90 import android.view.Choreographer; 91 import android.view.Display; 92 import android.view.DisplayInfo; 93 import android.view.Gravity; 94 import android.view.PointerIcon; 95 import android.view.IAppTransitionAnimationSpecsFuture; 96 import android.view.IApplicationToken; 97 import android.view.IDockedStackListener; 98 import android.view.IInputFilter; 99 import android.view.IOnKeyguardExitResult; 100 import android.view.IRotationWatcher; 101 import android.view.IWindow; 102 import android.view.IWindowId; 103 import android.view.IWindowManager; 104 import android.view.IWindowSession; 105 import android.view.IWindowSessionCallback; 106 import android.view.InputChannel; 107 import android.view.InputDevice; 108 import android.view.InputEvent; 109 import android.view.InputEventReceiver; 110 import android.view.KeyEvent; 111 import android.view.MagnificationSpec; 112 import android.view.MotionEvent; 113 import android.view.Surface; 114 import android.view.Surface.OutOfResourcesException; 115 import android.view.SurfaceControl; 116 import android.view.SurfaceSession; 117 import android.view.View; 118 import android.view.WindowContentFrameStats; 119 import android.view.WindowManager; 120 import android.view.WindowManager.LayoutParams; 121 import android.view.WindowManagerGlobal; 122 import android.view.WindowManagerInternal; 123 import android.view.WindowManagerPolicy; 124 import android.view.WindowManagerPolicy.PointerEventListener; 125 import android.view.animation.Animation; 126 import android.view.inputmethod.InputMethodManagerInternal; 127 128 import com.android.internal.R; 129 import com.android.internal.app.IAssistScreenshotReceiver; 130 import com.android.internal.os.IResultReceiver; 131 import com.android.internal.policy.IShortcutService; 132 import com.android.internal.util.ArrayUtils; 133 import com.android.internal.util.FastPrintWriter; 134 import com.android.internal.view.IInputContext; 135 import com.android.internal.view.IInputMethodClient; 136 import com.android.internal.view.IInputMethodManager; 137 import com.android.internal.view.WindowManagerPolicyThread; 138 import com.android.server.AttributeCache; 139 import com.android.server.DisplayThread; 140 import com.android.server.EventLogTags; 141 import com.android.server.FgThread; 142 import com.android.server.LocalServices; 143 import com.android.server.UiThread; 144 import com.android.server.Watchdog; 145 import com.android.server.input.InputManagerService; 146 import com.android.server.policy.PhoneWindowManager; 147 import com.android.server.power.ShutdownThread; 148 149 import java.io.BufferedWriter; 150 import java.io.DataInputStream; 151 import java.io.File; 152 import java.io.FileDescriptor; 153 import java.io.FileInputStream; 154 import java.io.FileNotFoundException; 155 import java.io.IOException; 156 import java.io.OutputStream; 157 import java.io.OutputStreamWriter; 158 import java.io.PrintWriter; 159 import java.io.StringWriter; 160 import java.lang.annotation.Retention; 161 import java.lang.annotation.RetentionPolicy; 162 import java.net.Socket; 163 import java.text.DateFormat; 164 import java.util.ArrayList; 165 import java.util.Arrays; 166 import java.util.Date; 167 import java.util.HashMap; 168 import java.util.Iterator; 169 import java.util.List; 170 171 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; 172 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; 173 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; 174 import static android.app.ActivityManager.StackId.PINNED_STACK_ID; 175 import static android.app.StatusBarManager.DISABLE_MASK; 176 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; 177 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 178 import static android.view.WindowManager.DOCKED_BOTTOM; 179 import static android.view.WindowManager.DOCKED_INVALID; 180 import static android.view.WindowManager.DOCKED_TOP; 181 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; 182 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; 183 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 184 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; 185 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 186 import static android.view.WindowManager.LayoutParams.FLAG_SECURE; 187 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 188 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; 189 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 190 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; 191 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; 192 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; 193 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 194 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 195 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 196 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION; 197 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; 198 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; 199 import static android.view.WindowManager.LayoutParams.TYPE_DREAM; 200 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 201 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 202 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; 203 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; 204 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG; 205 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; 206 import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 207 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; 208 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 209 import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY; 210 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED; 211 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 212 import static android.view.WindowManagerPolicy.TRANSIT_EXIT; 213 import static android.view.WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 214 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END; 215 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START; 216 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; 217 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM; 218 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; 219 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 220 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 221 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_ORIENTATION; 222 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS; 223 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT; 224 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION; 225 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; 226 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG; 227 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS; 228 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; 229 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; 230 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD; 231 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON; 232 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; 233 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; 234 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE; 235 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT; 236 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON; 237 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; 238 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW; 239 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE; 240 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; 241 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT; 242 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 243 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; 244 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT; 245 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE; 246 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; 247 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS; 248 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC; 249 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; 250 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSACTIONS; 251 import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON; 252 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 253 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 254 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; 255 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE; 256 257 /** {@hide} */ 258 public class WindowManagerService extends IWindowManager.Stub 259 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs { 260 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowManagerService" : TAG_WM; 261 262 static final int LAYOUT_REPEAT_THRESHOLD = 4; 263 264 static final boolean PROFILE_ORIENTATION = false; 265 static final boolean localLOGV = DEBUG; 266 267 /** How much to multiply the policy's type layer, to reserve room 268 * for multiple windows of the same type and Z-ordering adjustment 269 * with TYPE_LAYER_OFFSET. */ 270 static final int TYPE_LAYER_MULTIPLIER = 10000; 271 272 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above 273 * or below others in the same layer. */ 274 static final int TYPE_LAYER_OFFSET = 1000; 275 276 /** How much to increment the layer for each window, to reserve room 277 * for effect surfaces between them. 278 */ 279 static final int WINDOW_LAYER_MULTIPLIER = 5; 280 281 /** 282 * Dim surface layer is immediately below target window. 283 */ 284 static final int LAYER_OFFSET_DIM = 1; 285 286 /** 287 * Animation thumbnail is as far as possible below the window above 288 * the thumbnail (or in other words as far as possible above the window 289 * below it). 290 */ 291 static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER - 1; 292 293 /** The maximum length we will accept for a loaded animation duration: 294 * this is 10 seconds. 295 */ 296 static final int MAX_ANIMATION_DURATION = 10 * 1000; 297 298 /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */ 299 static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000; 300 301 /** Amount of time (in milliseconds) to delay before declaring a seamless rotation timeout. */ 302 static final int SEAMLESS_ROTATION_TIMEOUT_DURATION = 2000; 303 304 /** Amount of time (in milliseconds) to delay before declaring a window replacement timeout. */ 305 static final int WINDOW_REPLACEMENT_TIMEOUT_DURATION = 2000; 306 307 /** Amount of time to allow a last ANR message to exist before freeing the memory. */ 308 static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours 309 /** 310 * If true, the window manager will do its own custom freezing and general 311 * management of the screen during rotation. 312 */ 313 static final boolean CUSTOM_SCREEN_ROTATION = true; 314 315 // Maximum number of milliseconds to wait for input devices to be enumerated before 316 // proceding with safe mode detection. 317 private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000; 318 319 // Default input dispatching timeout in nanoseconds. 320 static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L; 321 322 // Poll interval in milliseconds for watching boot animation finished. 323 private static final int BOOT_ANIMATION_POLL_INTERVAL = 200; 324 325 // The name of the boot animation service in init.rc. 326 private static final String BOOT_ANIMATION_SERVICE = "bootanim"; 327 328 static final int UPDATE_FOCUS_NORMAL = 0; 329 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1; 330 static final int UPDATE_FOCUS_PLACING_SURFACES = 2; 331 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3; 332 333 private static final String SYSTEM_SECURE = "ro.secure"; 334 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; 335 336 private static final String DENSITY_OVERRIDE = "ro.config.density_override"; 337 private static final String SIZE_OVERRIDE = "ro.config.size_override"; 338 339 private static final int MAX_SCREENSHOT_RETRIES = 3; 340 341 private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular"; 342 343 // Used to indicate that if there is already a transition set, it should be preserved when 344 // trying to apply a new one. 345 private static final boolean ALWAYS_KEEP_CURRENT = true; 346 347 private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f; 348 349 private static final String PROPERTY_BUILD_DATE_UTC = "ro.build.date.utc"; 350 351 // Enums for animation scale update types. 352 @Retention(RetentionPolicy.SOURCE) 353 @IntDef({WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE, ANIMATION_DURATION_SCALE}) 354 private @interface UpdateAnimationScaleMode {}; 355 private static final int WINDOW_ANIMATION_SCALE = 0; 356 private static final int TRANSITION_ANIMATION_SCALE = 1; 357 private static final int ANIMATION_DURATION_SCALE = 2; 358 359 final private KeyguardDisableHandler mKeyguardDisableHandler; 360 361 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 362 @Override 363 public void onReceive(Context context, Intent intent) { 364 final String action = intent.getAction(); 365 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) { 366 mKeyguardDisableHandler.sendEmptyMessage( 367 KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED); 368 } 369 } 370 }; 371 final WindowSurfacePlacer mWindowPlacerLocked; 372 373 /** 374 * Current user when multi-user is enabled. Don't show windows of 375 * non-current user. Also see mCurrentProfileIds. 376 */ 377 int mCurrentUserId; 378 /** 379 * Users that are profiles of the current user. These are also allowed to show windows 380 * on the current user. 381 */ 382 int[] mCurrentProfileIds = new int[] {}; 383 384 final Context mContext; 385 386 final boolean mHaveInputMethods; 387 388 final boolean mHasPermanentDpad; 389 final long mDrawLockTimeoutMillis; 390 final boolean mAllowAnimationsInLowPowerMode; 391 392 final boolean mAllowBootMessages; 393 394 final boolean mLimitedAlphaCompositing; 395 396 final WindowManagerPolicy mPolicy = new PhoneWindowManager(); 397 398 final IActivityManager mActivityManager; 399 final ActivityManagerInternal mAmInternal; 400 401 final AppOpsManager mAppOps; 402 403 final DisplaySettings mDisplaySettings; 404 405 /** 406 * All currently active sessions with clients. 407 */ 408 final ArraySet<Session> mSessions = new ArraySet<>(); 409 410 /** 411 * Mapping from an IWindow IBinder to the server's Window object. 412 * This is also used as the lock for all of our state. 413 * NOTE: Never call into methods that lock ActivityManagerService while holding this object. 414 */ 415 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>(); 416 417 /** 418 * Mapping from a token IBinder to a WindowToken object. 419 */ 420 final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<>(); 421 422 /** 423 * List of window tokens that have finished starting their application, 424 * and now need to have the policy remove their windows. 425 */ 426 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<>(); 427 428 /** 429 * List of window tokens that have finished drawing their own windows and 430 * no longer need to show any saved surfaces. Windows that's still showing 431 * saved surfaces will be cleaned up after next animation pass. 432 */ 433 final ArrayList<AppWindowToken> mFinishedEarlyAnim = new ArrayList<>(); 434 435 /** 436 * List of app window tokens that are waiting for replacing windows. If the 437 * replacement doesn't come in time the stale windows needs to be disposed of. 438 */ 439 final ArrayList<AppWindowToken> mReplacingWindowTimeouts = new ArrayList<>(); 440 441 /** 442 * The input consumer added to the window manager which consumes input events to windows below 443 * it. 444 */ 445 InputConsumerImpl mInputConsumer; 446 447 /** 448 * The input consumer added to the window manager before all wallpaper windows. 449 */ 450 InputConsumerImpl mWallpaperInputConsumer; 451 452 /** 453 * Windows that are being resized. Used so we can tell the client about 454 * the resize after closing the transaction in which we resized the 455 * underlying surface. 456 */ 457 final ArrayList<WindowState> mResizingWindows = new ArrayList<>(); 458 459 /** 460 * Windows whose animations have ended and now must be removed. 461 */ 462 final ArrayList<WindowState> mPendingRemove = new ArrayList<>(); 463 464 /** 465 * Used when processing mPendingRemove to avoid working on the original array. 466 */ 467 WindowState[] mPendingRemoveTmp = new WindowState[20]; 468 469 /** 470 * Windows whose surface should be destroyed. 471 */ 472 final ArrayList<WindowState> mDestroySurface = new ArrayList<>(); 473 474 /** 475 * Windows with a preserved surface waiting to be destroyed. These windows 476 * are going through a surface change. We keep the old surface around until 477 * the first frame on the new surface finishes drawing. 478 */ 479 final ArrayList<WindowState> mDestroyPreservedSurface = new ArrayList<>(); 480 481 /** 482 * Windows that have lost input focus and are waiting for the new 483 * focus window to be displayed before they are told about this. 484 */ 485 ArrayList<WindowState> mLosingFocus = new ArrayList<>(); 486 487 /** 488 * This is set when we have run out of memory, and will either be an empty 489 * list or contain windows that need to be force removed. 490 */ 491 final ArrayList<WindowState> mForceRemoves = new ArrayList<>(); 492 493 /** 494 * Windows that clients are waiting to have drawn. 495 */ 496 ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>(); 497 /** 498 * And the callback to make when they've all been drawn. 499 */ 500 Runnable mWaitingForDrawnCallback; 501 502 /** 503 * Used when rebuilding window list to keep track of windows that have 504 * been removed. 505 */ 506 WindowState[] mRebuildTmp = new WindowState[20]; 507 508 /** 509 * Stores for each user whether screencapture is disabled 510 * This array is essentially a cache for all userId for 511 * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled} 512 */ 513 SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>(); 514 515 IInputMethodManager mInputMethodManager; 516 517 AccessibilityController mAccessibilityController; 518 519 final SurfaceSession mFxSession; 520 Watermark mWatermark; 521 StrictModeFlash mStrictModeFlash; 522 CircularDisplayMask mCircularDisplayMask; 523 EmulatorDisplayOverlay mEmulatorDisplayOverlay; 524 525 final float[] mTmpFloats = new float[9]; 526 final Rect mTmpRect = new Rect(); 527 final Rect mTmpRect2 = new Rect(); 528 final Rect mTmpRect3 = new Rect(); 529 final RectF mTmpRectF = new RectF(); 530 531 final Matrix mTmpTransform = new Matrix(); 532 533 boolean mDisplayReady; 534 boolean mSafeMode; 535 boolean mDisplayEnabled = false; 536 boolean mSystemBooted = false; 537 boolean mForceDisplayEnabled = false; 538 boolean mShowingBootMessages = false; 539 boolean mBootAnimationStopped = false; 540 541 // Following variables are for debugging screen wakelock only. 542 WindowState mLastWakeLockHoldingWindow = null; 543 WindowState mLastWakeLockObscuringWindow = null; 544 545 /** Dump of the windows and app tokens at the time of the last ANR. Cleared after 546 * LAST_ANR_LIFETIME_DURATION_MSECS */ 547 String mLastANRState; 548 549 /** All DisplayContents in the world, kept here */ 550 SparseArray<DisplayContent> mDisplayContents = new SparseArray<>(2); 551 552 int mRotation = 0; 553 int mLastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 554 boolean mAltOrientation = false; 555 556 private boolean mKeyguardWaitingForActivityDrawn; 557 558 int mDockedStackCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; 559 Rect mDockedStackCreateBounds; 560 561 private final SparseIntArray mTmpTaskIds = new SparseIntArray(); 562 563 private final ArrayList<Integer> mChangedStackList = new ArrayList(); 564 565 boolean mForceResizableTasks = false; 566 567 int getDragLayerLocked() { 568 return mPolicy.windowTypeToLayerLw(LayoutParams.TYPE_DRAG) * TYPE_LAYER_MULTIPLIER 569 + TYPE_LAYER_OFFSET; 570 } 571 572 class RotationWatcher { 573 IRotationWatcher watcher; 574 IBinder.DeathRecipient deathRecipient; 575 RotationWatcher(IRotationWatcher w, IBinder.DeathRecipient d) { 576 watcher = w; 577 deathRecipient = d; 578 } 579 } 580 ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<>(); 581 int mDeferredRotationPauseCount; 582 583 int mSystemDecorLayer = 0; 584 final Rect mScreenRect = new Rect(); 585 586 boolean mDisplayFrozen = false; 587 long mDisplayFreezeTime = 0; 588 int mLastDisplayFreezeDuration = 0; 589 Object mLastFinishedFreezeSource = null; 590 boolean mWaitingForConfig = false; 591 592 final static int WINDOWS_FREEZING_SCREENS_NONE = 0; 593 final static int WINDOWS_FREEZING_SCREENS_ACTIVE = 1; 594 final static int WINDOWS_FREEZING_SCREENS_TIMEOUT = 2; 595 int mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE; 596 597 boolean mClientFreezingScreen = false; 598 int mAppsFreezingScreen = 0; 599 int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 600 int mLastKeyguardForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 601 602 int mLayoutSeq = 0; 603 604 // Last systemUiVisibility we received from status bar. 605 int mLastStatusBarVisibility = 0; 606 // Last systemUiVisibility we dispatched to windows. 607 int mLastDispatchedSystemUiVisibility = 0; 608 609 // State while inside of layoutAndPlaceSurfacesLocked(). 610 boolean mFocusMayChange; 611 612 Configuration mCurConfiguration = new Configuration(); 613 614 // This is held as long as we have the screen frozen, to give us time to 615 // perform a rotation animation when turning off shows the lock screen which 616 // changes the orientation. 617 private final PowerManager.WakeLock mScreenFrozenLock; 618 619 final AppTransition mAppTransition; 620 boolean mSkipAppTransitionAnimation = false; 621 622 final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<>(); 623 final ArraySet<AppWindowToken> mClosingApps = new ArraySet<>(); 624 625 boolean mIsTouchDevice; 626 627 final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 628 final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics(); 629 final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics(); 630 final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics(); 631 632 final H mH = new H(); 633 634 final Choreographer mChoreographer = Choreographer.getInstance(); 635 636 WindowState mCurrentFocus = null; 637 WindowState mLastFocus = null; 638 639 /** This just indicates the window the input method is on top of, not 640 * necessarily the window its input is going to. */ 641 WindowState mInputMethodTarget = null; 642 643 /** If true hold off on modifying the animation layer of mInputMethodTarget */ 644 boolean mInputMethodTargetWaitingAnim; 645 646 WindowState mInputMethodWindow = null; 647 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<>(); 648 649 /** Temporary list for comparison. Always clear this after use so we don't end up with 650 * orphaned windows references */ 651 final ArrayList<WindowState> mTmpWindows = new ArrayList<>(); 652 653 boolean mHardKeyboardAvailable; 654 WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; 655 SettingsObserver mSettingsObserver; 656 657 // A count of the windows which are 'seamlessly rotated', e.g. a surface 658 // at an old orientation is being transformed. We freeze orientation updates 659 // while any windows are seamlessly rotated, so we need to track when this 660 // hits zero so we can apply deferred orientation updates. 661 int mSeamlessRotationCount = 0; 662 663 private final class SettingsObserver extends ContentObserver { 664 private final Uri mDisplayInversionEnabledUri = 665 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); 666 private final Uri mWindowAnimationScaleUri = 667 Settings.Global.getUriFor(Settings.Global.WINDOW_ANIMATION_SCALE); 668 private final Uri mTransitionAnimationScaleUri = 669 Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE); 670 private final Uri mAnimationDurationScaleUri = 671 Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE); 672 673 public SettingsObserver() { 674 super(new Handler()); 675 ContentResolver resolver = mContext.getContentResolver(); 676 resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this, 677 UserHandle.USER_ALL); 678 resolver.registerContentObserver(mWindowAnimationScaleUri, false, this, 679 UserHandle.USER_ALL); 680 resolver.registerContentObserver(mTransitionAnimationScaleUri, false, this, 681 UserHandle.USER_ALL); 682 resolver.registerContentObserver(mAnimationDurationScaleUri, false, this, 683 UserHandle.USER_ALL); 684 } 685 686 @Override 687 public void onChange(boolean selfChange, Uri uri) { 688 if (uri == null) { 689 return; 690 } 691 692 if (mDisplayInversionEnabledUri.equals(uri)) { 693 updateCircularDisplayMaskIfNeeded(); 694 } else { 695 @UpdateAnimationScaleMode 696 final int mode; 697 if (mWindowAnimationScaleUri.equals(uri)) { 698 mode = WINDOW_ANIMATION_SCALE; 699 } else if (mTransitionAnimationScaleUri.equals(uri)) { 700 mode = TRANSITION_ANIMATION_SCALE; 701 } else if (mAnimationDurationScaleUri.equals(uri)) { 702 mode = ANIMATION_DURATION_SCALE; 703 } else { 704 // Ignoring unrecognized content changes 705 return; 706 } 707 Message m = mH.obtainMessage(H.UPDATE_ANIMATION_SCALE, mode, 0); 708 mH.sendMessage(m); 709 } 710 } 711 } 712 713 WallpaperController mWallpaperControllerLocked; 714 715 final WindowLayersController mLayersController; 716 717 boolean mAnimateWallpaperWithTarget; 718 719 AppWindowToken mFocusedApp = null; 720 721 PowerManager mPowerManager; 722 PowerManagerInternal mPowerManagerInternal; 723 724 float mWindowAnimationScaleSetting = 1.0f; 725 float mTransitionAnimationScaleSetting = 1.0f; 726 float mAnimatorDurationScaleSetting = 1.0f; 727 boolean mAnimationsDisabled = false; 728 729 final InputManagerService mInputManager; 730 final DisplayManagerInternal mDisplayManagerInternal; 731 final DisplayManager mDisplayManager; 732 final Display[] mDisplays; 733 734 // Who is holding the screen on. 735 Session mHoldingScreenOn; 736 PowerManager.WakeLock mHoldingScreenWakeLock; 737 738 boolean mTurnOnScreen; 739 740 // Whether or not a layout can cause a wake up when theater mode is enabled. 741 boolean mAllowTheaterModeWakeFromLayout; 742 743 TaskPositioner mTaskPositioner; 744 DragState mDragState = null; 745 746 // For frozen screen animations. 747 int mExitAnimId, mEnterAnimId; 748 749 boolean mAnimationScheduled; 750 751 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this 752 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */ 753 int mTransactionSequence; 754 755 final WindowAnimator mAnimator; 756 757 private final BoundsAnimationController mBoundsAnimationController; 758 759 SparseArray<Task> mTaskIdToTask = new SparseArray<>(); 760 761 /** All of the TaskStacks in the window manager, unordered. For an ordered list call 762 * DisplayContent.getStacks(). */ 763 SparseArray<TaskStack> mStackIdToStack = new SparseArray<>(); 764 765 private final PointerEventDispatcher mPointerEventDispatcher; 766 767 private WindowContentFrameStats mTempWindowRenderStats; 768 769 final class DragInputEventReceiver extends InputEventReceiver { 770 // Set, if stylus button was down at the start of the drag. 771 private boolean mStylusButtonDownAtStart; 772 // Indicates the first event to check for button state. 773 private boolean mIsStartEvent = true; 774 775 public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { 776 super(inputChannel, looper); 777 } 778 779 @Override 780 public void onInputEvent(InputEvent event) { 781 boolean handled = false; 782 try { 783 if (event instanceof MotionEvent 784 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0 785 && mDragState != null) { 786 final MotionEvent motionEvent = (MotionEvent)event; 787 boolean endDrag = false; 788 final float newX = motionEvent.getRawX(); 789 final float newY = motionEvent.getRawY(); 790 final boolean isStylusButtonDown = 791 (motionEvent.getButtonState() & MotionEvent.BUTTON_STYLUS_PRIMARY) != 0; 792 793 if (mIsStartEvent) { 794 if (isStylusButtonDown) { 795 // First event and the button was down, check for the button being 796 // lifted in the future, if that happens we'll drop the item. 797 mStylusButtonDownAtStart = true; 798 } 799 mIsStartEvent = false; 800 } 801 802 switch (motionEvent.getAction()) { 803 case MotionEvent.ACTION_DOWN: { 804 if (DEBUG_DRAG) { 805 Slog.w(TAG_WM, "Unexpected ACTION_DOWN in drag layer"); 806 } 807 } break; 808 809 case MotionEvent.ACTION_MOVE: { 810 if (mStylusButtonDownAtStart && !isStylusButtonDown) { 811 if (DEBUG_DRAG) Slog.d(TAG_WM, "Button no longer pressed; dropping at " 812 + newX + "," + newY); 813 synchronized (mWindowMap) { 814 endDrag = mDragState.notifyDropLw(newX, newY); 815 } 816 } else { 817 synchronized (mWindowMap) { 818 // move the surface and tell the involved window(s) where we are 819 mDragState.notifyMoveLw(newX, newY); 820 } 821 } 822 } break; 823 824 case MotionEvent.ACTION_UP: { 825 if (DEBUG_DRAG) Slog.d(TAG_WM, "Got UP on move channel; dropping at " 826 + newX + "," + newY); 827 synchronized (mWindowMap) { 828 endDrag = mDragState.notifyDropLw(newX, newY); 829 } 830 } break; 831 832 case MotionEvent.ACTION_CANCEL: { 833 if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag cancelled!"); 834 endDrag = true; 835 } break; 836 } 837 838 if (endDrag) { 839 if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ended; tearing down state"); 840 // tell all the windows that the drag has ended 841 synchronized (mWindowMap) { 842 mDragState.endDragLw(); 843 } 844 mStylusButtonDownAtStart = false; 845 mIsStartEvent = true; 846 } 847 848 handled = true; 849 } 850 } catch (Exception e) { 851 Slog.e(TAG_WM, "Exception caught by drag handleMotion", e); 852 } finally { 853 finishInputEvent(event, handled); 854 } 855 } 856 } 857 858 /** 859 * Whether the UI is currently running in touch mode (not showing 860 * navigational focus because the user is directly pressing the screen). 861 */ 862 boolean mInTouchMode; 863 864 private ViewServer mViewServer; 865 final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>(); 866 boolean mWindowsChanged = false; 867 868 public interface WindowChangeListener { 869 public void windowsChanged(); 870 public void focusChanged(); 871 } 872 873 final Configuration mTempConfiguration = new Configuration(); 874 875 // The desired scaling factor for compatible apps. 876 float mCompatibleScreenScale; 877 878 // If true, only the core apps and services are being launched because the device 879 // is in a special boot mode, such as being encrypted or waiting for a decryption password. 880 // For example, when this flag is true, there will be no wallpaper service. 881 final boolean mOnlyCore; 882 883 // List of clients without a transtiton animation that we notify once we are done transitioning 884 // since they won't be notified through the app window animator. 885 final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>(); 886 887 // List of displays to reconfigure after configuration changes. 888 // Some of the information reported for a display is dependent on resources to do the right 889 // calculations. For example, {@link DisplayInfo#smallestNominalAppWidth} and company are 890 // dependent on the height and width of the status and nav bar which change depending on the 891 // current configuration. 892 private final DisplayContentList mReconfigureOnConfigurationChanged = new DisplayContentList(); 893 894 /** Listener to notify activity manager about app transitions. */ 895 private final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier 896 = new WindowManagerInternal.AppTransitionListener() { 897 898 @Override 899 public void onAppTransitionCancelledLocked() { 900 mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_CANCELLED); 901 } 902 903 @Override 904 public void onAppTransitionFinishedLocked(IBinder token) { 905 mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_FINISHED); 906 AppWindowToken atoken = findAppWindowToken(token); 907 if (atoken == null) { 908 return; 909 } 910 if (atoken.mLaunchTaskBehind) { 911 try { 912 mActivityManager.notifyLaunchTaskBehindComplete(atoken.token); 913 } catch (RemoteException e) { 914 } 915 atoken.mLaunchTaskBehind = false; 916 } else { 917 atoken.updateReportedVisibilityLocked(); 918 if (atoken.mEnteringAnimation) { 919 atoken.mEnteringAnimation = false; 920 try { 921 mActivityManager.notifyEnterAnimationComplete(atoken.token); 922 } catch (RemoteException e) { 923 } 924 } 925 } 926 } 927 }; 928 929 public static WindowManagerService main(final Context context, 930 final InputManagerService im, 931 final boolean haveInputMethods, final boolean showBootMsgs, 932 final boolean onlyCore) { 933 final WindowManagerService[] holder = new WindowManagerService[1]; 934 DisplayThread.getHandler().runWithScissors(new Runnable() { 935 @Override 936 public void run() { 937 holder[0] = new WindowManagerService(context, im, 938 haveInputMethods, showBootMsgs, onlyCore); 939 } 940 }, 0); 941 return holder[0]; 942 } 943 944 private void initPolicy() { 945 UiThread.getHandler().runWithScissors(new Runnable() { 946 @Override 947 public void run() { 948 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper()); 949 950 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this); 951 } 952 }, 0); 953 } 954 955 private WindowManagerService(Context context, InputManagerService inputManager, 956 boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) { 957 mContext = context; 958 mHaveInputMethods = haveInputMethods; 959 mAllowBootMessages = showBootMsgs; 960 mOnlyCore = onlyCore; 961 mLimitedAlphaCompositing = context.getResources().getBoolean( 962 com.android.internal.R.bool.config_sf_limitedAlpha); 963 mHasPermanentDpad = context.getResources().getBoolean( 964 com.android.internal.R.bool.config_hasPermanentDpad); 965 mInTouchMode = context.getResources().getBoolean( 966 com.android.internal.R.bool.config_defaultInTouchMode); 967 mDrawLockTimeoutMillis = context.getResources().getInteger( 968 com.android.internal.R.integer.config_drawLockTimeoutMillis); 969 mAllowAnimationsInLowPowerMode = context.getResources().getBoolean( 970 com.android.internal.R.bool.config_allowAnimationsInLowPowerMode); 971 mInputManager = inputManager; // Must be before createDisplayContentLocked. 972 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); 973 mDisplaySettings = new DisplaySettings(); 974 mDisplaySettings.readSettingsLocked(); 975 976 mWallpaperControllerLocked = new WallpaperController(this); 977 mWindowPlacerLocked = new WindowSurfacePlacer(this); 978 mLayersController = new WindowLayersController(this); 979 980 LocalServices.addService(WindowManagerPolicy.class, mPolicy); 981 982 mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG_WM)); 983 984 mFxSession = new SurfaceSession(); 985 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); 986 mDisplays = mDisplayManager.getDisplays(); 987 for (Display display : mDisplays) { 988 createDisplayContentLocked(display); 989 } 990 991 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy); 992 993 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 994 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 995 mPowerManagerInternal.registerLowPowerModeObserver( 996 new PowerManagerInternal.LowPowerModeListener() { 997 @Override 998 public void onLowPowerModeChanged(boolean enabled) { 999 synchronized (mWindowMap) { 1000 if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) { 1001 mAnimationsDisabled = enabled; 1002 dispatchNewAnimatorScaleLocked(null); 1003 } 1004 } 1005 } 1006 }); 1007 mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled(); 1008 mScreenFrozenLock = mPowerManager.newWakeLock( 1009 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN"); 1010 mScreenFrozenLock.setReferenceCounted(false); 1011 1012 mAppTransition = new AppTransition(context, this); 1013 mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier); 1014 1015 mBoundsAnimationController = 1016 new BoundsAnimationController(mAppTransition, UiThread.getHandler()); 1017 1018 mActivityManager = ActivityManagerNative.getDefault(); 1019 mAmInternal = LocalServices.getService(ActivityManagerInternal.class); 1020 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 1021 AppOpsManager.OnOpChangedInternalListener opListener = 1022 new AppOpsManager.OnOpChangedInternalListener() { 1023 @Override public void onOpChanged(int op, String packageName) { 1024 updateAppOpsState(); 1025 } 1026 }; 1027 mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null, opListener); 1028 mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener); 1029 1030 // Get persisted window scale setting 1031 mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 1032 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 1033 mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 1034 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting); 1035 setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(), 1036 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting)); 1037 1038 // Track changes to DevicePolicyManager state so we can enable/disable keyguard. 1039 IntentFilter filter = new IntentFilter(); 1040 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 1041 mContext.registerReceiver(mBroadcastReceiver, filter); 1042 1043 mSettingsObserver = new SettingsObserver(); 1044 1045 mHoldingScreenWakeLock = mPowerManager.newWakeLock( 1046 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM); 1047 mHoldingScreenWakeLock.setReferenceCounted(false); 1048 1049 mAnimator = new WindowAnimator(this); 1050 1051 mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean( 1052 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout); 1053 1054 1055 LocalServices.addService(WindowManagerInternal.class, new LocalService()); 1056 initPolicy(); 1057 1058 // Add ourself to the Watchdog monitors. 1059 Watchdog.getInstance().addMonitor(this); 1060 1061 SurfaceControl.openTransaction(); 1062 try { 1063 createWatermarkInTransaction(); 1064 } finally { 1065 SurfaceControl.closeTransaction(); 1066 } 1067 1068 showEmulatorDisplayOverlayIfNeeded(); 1069 } 1070 1071 public InputMonitor getInputMonitor() { 1072 return mInputMonitor; 1073 } 1074 1075 @Override 1076 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 1077 throws RemoteException { 1078 try { 1079 return super.onTransact(code, data, reply, flags); 1080 } catch (RuntimeException e) { 1081 // The window manager only throws security exceptions, so let's 1082 // log all others. 1083 if (!(e instanceof SecurityException)) { 1084 Slog.wtf(TAG_WM, "Window Manager Crash", e); 1085 } 1086 throw e; 1087 } 1088 } 1089 1090 private void placeWindowAfter(WindowState pos, WindowState window) { 1091 final WindowList windows = pos.getWindowList(); 1092 final 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+1) + " of " + windows.size() + " (after " + pos + ")"); 1096 windows.add(i+1, window); 1097 mWindowsChanged = true; 1098 } 1099 1100 private void placeWindowBefore(WindowState pos, WindowState window) { 1101 final WindowList windows = pos.getWindowList(); 1102 int i = windows.indexOf(pos); 1103 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 1104 TAG_WM, "Adding window " + window + " at " 1105 + i + " of " + windows.size() + " (before " + pos + ")"); 1106 if (i < 0) { 1107 Slog.w(TAG_WM, "placeWindowBefore: Unable to find " + pos + " in " + windows); 1108 i = 0; 1109 } 1110 windows.add(i, window); 1111 mWindowsChanged = true; 1112 } 1113 1114 //This method finds out the index of a window that has the same app token as 1115 //win. used for z ordering the windows in mWindows 1116 private int findIdxBasedOnAppTokens(WindowState win) { 1117 WindowList windows = win.getWindowList(); 1118 for(int j = windows.size() - 1; j >= 0; j--) { 1119 WindowState wentry = windows.get(j); 1120 if(wentry.mAppToken == win.mAppToken) { 1121 return j; 1122 } 1123 } 1124 return -1; 1125 } 1126 1127 /** 1128 * Return the list of Windows from the passed token on the given Display. 1129 * @param token The token with all the windows. 1130 * @param displayContent The display we are interested in. 1131 * @return List of windows from token that are on displayContent. 1132 */ 1133 private WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) { 1134 final WindowList windowList = new WindowList(); 1135 final int count = token.windows.size(); 1136 for (int i = 0; i < count; i++) { 1137 final WindowState win = token.windows.get(i); 1138 if (win.getDisplayContent() == displayContent) { 1139 windowList.add(win); 1140 } 1141 } 1142 return windowList; 1143 } 1144 1145 /** 1146 * Recursive search through a WindowList and all of its windows' children. 1147 * @param targetWin The window to search for. 1148 * @param windows The list to search. 1149 * @return The index of win in windows or of the window that is an ancestor of win. 1150 */ 1151 private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) { 1152 for (int i = windows.size() - 1; i >= 0; i--) { 1153 final WindowState w = windows.get(i); 1154 if (w == targetWin) { 1155 return i; 1156 } 1157 if (!w.mChildWindows.isEmpty()) { 1158 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) { 1159 return i; 1160 } 1161 } 1162 } 1163 return -1; 1164 } 1165 1166 private int addAppWindowToListLocked(final WindowState win) { 1167 final DisplayContent displayContent = win.getDisplayContent(); 1168 if (displayContent == null) { 1169 // It doesn't matter this display is going away. 1170 return 0; 1171 } 1172 final IWindow client = win.mClient; 1173 final WindowToken token = win.mToken; 1174 1175 final WindowList windows = displayContent.getWindowList(); 1176 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 1177 int tokenWindowsPos = 0; 1178 if (!tokenWindowList.isEmpty()) { 1179 return addAppWindowToTokenListLocked(win, token, windows, tokenWindowList); 1180 } 1181 1182 // No windows from this token on this display 1183 if (localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window " + client.asBinder() 1184 + " (token=" + token + ")"); 1185 // Figure out where the window should go, based on the 1186 // order of applications. 1187 WindowState pos = null; 1188 1189 final ArrayList<Task> tasks = displayContent.getTasks(); 1190 int taskNdx; 1191 int tokenNdx = -1; 1192 for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 1193 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1194 for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 1195 final AppWindowToken t = tokens.get(tokenNdx); 1196 if (t == token) { 1197 --tokenNdx; 1198 if (tokenNdx < 0) { 1199 --taskNdx; 1200 if (taskNdx >= 0) { 1201 tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1; 1202 } 1203 } 1204 break; 1205 } 1206 1207 // We haven't reached the token yet; if this token 1208 // is not going to the bottom and has windows on this display, we can 1209 // use it as an anchor for when we do reach the token. 1210 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1211 if (!t.sendingToBottom && tokenWindowList.size() > 0) { 1212 pos = tokenWindowList.get(0); 1213 } 1214 } 1215 if (tokenNdx >= 0) { 1216 // early exit 1217 break; 1218 } 1219 } 1220 1221 // We now know the index into the apps. If we found 1222 // an app window above, that gives us the position; else 1223 // we need to look some more. 1224 if (pos != null) { 1225 // Move behind any windows attached to this one. 1226 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1227 if (atoken != null) { 1228 tokenWindowList = 1229 getTokenWindowsOnDisplay(atoken, displayContent); 1230 final int NC = tokenWindowList.size(); 1231 if (NC > 0) { 1232 WindowState bottom = tokenWindowList.get(0); 1233 if (bottom.mSubLayer < 0) { 1234 pos = bottom; 1235 } 1236 } 1237 } 1238 placeWindowBefore(pos, win); 1239 return tokenWindowsPos; 1240 } 1241 1242 // Continue looking down until we find the first 1243 // token that has windows on this display. 1244 for ( ; taskNdx >= 0; --taskNdx) { 1245 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1246 for ( ; tokenNdx >= 0; --tokenNdx) { 1247 final AppWindowToken t = tokens.get(tokenNdx); 1248 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1249 final int NW = tokenWindowList.size(); 1250 if (NW > 0) { 1251 pos = tokenWindowList.get(NW-1); 1252 break; 1253 } 1254 } 1255 if (tokenNdx >= 0) { 1256 // found 1257 break; 1258 } 1259 } 1260 1261 if (pos != null) { 1262 // Move in front of any windows attached to this 1263 // one. 1264 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1265 if (atoken != null) { 1266 final int NC = atoken.windows.size(); 1267 if (NC > 0) { 1268 WindowState top = atoken.windows.get(NC-1); 1269 if (top.mSubLayer >= 0) { 1270 pos = top; 1271 } 1272 } 1273 } 1274 placeWindowAfter(pos, win); 1275 return tokenWindowsPos; 1276 } 1277 1278 // Just search for the start of this layer. 1279 final int myLayer = win.mBaseLayer; 1280 int i; 1281 for (i = windows.size() - 1; i >= 0; --i) { 1282 WindowState w = windows.get(i); 1283 // Dock divider shares the base layer with application windows, but we want to always 1284 // keep it above the application windows. The sharing of the base layer is intended 1285 // for window animations, which need to be above the dock divider for the duration 1286 // of the animation. 1287 if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) { 1288 break; 1289 } 1290 } 1291 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1292 "Based on layer: Adding window " + win + " at " + (i + 1) + " of " 1293 + windows.size()); 1294 windows.add(i + 1, win); 1295 mWindowsChanged = true; 1296 return tokenWindowsPos; 1297 } 1298 1299 private int addAppWindowToTokenListLocked(WindowState win, WindowToken token, 1300 WindowList windows, WindowList tokenWindowList) { 1301 int tokenWindowsPos; 1302 // If this application has existing windows, we 1303 // simply place the new window on top of them... but 1304 // keep the starting window on top. 1305 if (win.mAttrs.type == TYPE_BASE_APPLICATION) { 1306 // Base windows go behind everything else. 1307 WindowState lowestWindow = tokenWindowList.get(0); 1308 placeWindowBefore(lowestWindow, win); 1309 tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows); 1310 } else { 1311 AppWindowToken atoken = win.mAppToken; 1312 final int windowListPos = tokenWindowList.size(); 1313 WindowState lastWindow = tokenWindowList.get(windowListPos - 1); 1314 if (atoken != null && lastWindow == atoken.startingWindow) { 1315 placeWindowBefore(lastWindow, win); 1316 tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows); 1317 } else { 1318 int newIdx = findIdxBasedOnAppTokens(win); 1319 //there is a window above this one associated with the same 1320 //apptoken note that the window could be a floating window 1321 //that was created later or a window at the top of the list of 1322 //windows associated with this token. 1323 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1324 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " 1325 + windows.size()); 1326 windows.add(newIdx + 1, win); 1327 if (newIdx < 0) { 1328 // No window from token found on win's display. 1329 tokenWindowsPos = 0; 1330 } else { 1331 tokenWindowsPos = indexOfWinInWindowList( 1332 windows.get(newIdx), token.windows) + 1; 1333 } 1334 mWindowsChanged = true; 1335 } 1336 } 1337 return tokenWindowsPos; 1338 } 1339 1340 private void addFreeWindowToListLocked(final WindowState win) { 1341 final WindowList windows = win.getWindowList(); 1342 1343 // Figure out where window should go, based on layer. 1344 final int myLayer = win.mBaseLayer; 1345 int i; 1346 for (i = windows.size() - 1; i >= 0; i--) { 1347 final WindowState otherWin = windows.get(i); 1348 if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= myLayer) { 1349 // Wallpaper wanders through the window list, for example to position itself 1350 // directly behind keyguard. Because of this it will break the ordering based on 1351 // WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and 1352 // we don't want the new window to appear above them. An example of this is adding 1353 // of the docked stack divider. Consider a scenario with the following ordering (top 1354 // to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider 1355 // to land below the assist preview, so the dock divider must ignore the wallpaper, 1356 // with which it shares the base layer. 1357 break; 1358 } 1359 } 1360 i++; 1361 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1362 "Free window: Adding window " + win + " at " + i + " of " + windows.size()); 1363 windows.add(i, win); 1364 mWindowsChanged = true; 1365 } 1366 1367 private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) { 1368 final WindowToken token = win.mToken; 1369 final DisplayContent displayContent = win.getDisplayContent(); 1370 if (displayContent == null) { 1371 return; 1372 } 1373 final WindowState attached = win.mAttachedWindow; 1374 1375 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 1376 1377 // Figure out this window's ordering relative to the window 1378 // it is attached to. 1379 final int NA = tokenWindowList.size(); 1380 final int sublayer = win.mSubLayer; 1381 int largestSublayer = Integer.MIN_VALUE; 1382 WindowState windowWithLargestSublayer = null; 1383 int i; 1384 for (i = 0; i < NA; i++) { 1385 WindowState w = tokenWindowList.get(i); 1386 final int wSublayer = w.mSubLayer; 1387 if (wSublayer >= largestSublayer) { 1388 largestSublayer = wSublayer; 1389 windowWithLargestSublayer = w; 1390 } 1391 if (sublayer < 0) { 1392 // For negative sublayers, we go below all windows 1393 // in the same sublayer. 1394 if (wSublayer >= sublayer) { 1395 if (addToToken) { 1396 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + token); 1397 token.windows.add(i, win); 1398 } 1399 placeWindowBefore(wSublayer >= 0 ? attached : w, win); 1400 break; 1401 } 1402 } else { 1403 // For positive sublayers, we go above all windows 1404 // in the same sublayer. 1405 if (wSublayer > sublayer) { 1406 if (addToToken) { 1407 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + token); 1408 token.windows.add(i, win); 1409 } 1410 placeWindowBefore(w, win); 1411 break; 1412 } 1413 } 1414 } 1415 if (i >= NA) { 1416 if (addToToken) { 1417 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + token); 1418 token.windows.add(win); 1419 } 1420 if (sublayer < 0) { 1421 placeWindowBefore(attached, win); 1422 } else { 1423 placeWindowAfter(largestSublayer >= 0 1424 ? windowWithLargestSublayer 1425 : attached, 1426 win); 1427 } 1428 } 1429 } 1430 1431 private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) { 1432 if (DEBUG_FOCUS) Slog.d(TAG_WM, "addWindowToListInOrderLocked: win=" + win + 1433 " Callers=" + Debug.getCallers(4)); 1434 if (win.mAttachedWindow == null) { 1435 final WindowToken token = win.mToken; 1436 int tokenWindowsPos = 0; 1437 if (token.appWindowToken != null) { 1438 tokenWindowsPos = addAppWindowToListLocked(win); 1439 } else { 1440 addFreeWindowToListLocked(win); 1441 } 1442 if (addToToken) { 1443 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + token); 1444 token.windows.add(tokenWindowsPos, win); 1445 } 1446 } else { 1447 addAttachedWindowToListLocked(win, addToToken); 1448 } 1449 1450 final AppWindowToken appToken = win.mAppToken; 1451 if (appToken != null) { 1452 if (addToToken) { 1453 appToken.addWindow(win); 1454 } 1455 } 1456 } 1457 1458 static boolean canBeImeTarget(WindowState w) { 1459 final int fl = w.mAttrs.flags 1460 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); 1461 final int type = w.mAttrs.type; 1462 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM) 1463 || type == TYPE_APPLICATION_STARTING) { 1464 if (DEBUG_INPUT_METHOD) { 1465 Slog.i(TAG_WM, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding()); 1466 if (!w.isVisibleOrAdding()) { 1467 Slog.i(TAG_WM, " mSurfaceController=" + w.mWinAnimator.mSurfaceController 1468 + " relayoutCalled=" + w.mRelayoutCalled 1469 + " viewVis=" + w.mViewVisibility 1470 + " policyVis=" + w.mPolicyVisibility 1471 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim 1472 + " attachHid=" + w.mAttachedHidden 1473 + " exiting=" + w.mAnimatingExit + " destroying=" + w.mDestroying); 1474 if (w.mAppToken != null) { 1475 Slog.i(TAG_WM, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested); 1476 } 1477 } 1478 } 1479 return w.isVisibleOrAdding(); 1480 } 1481 return false; 1482 } 1483 1484 /** 1485 * Dig through the WindowStates and find the one that the Input Method will target. 1486 * @param willMove 1487 * @return The index+1 in mWindows of the discovered target. 1488 */ 1489 int findDesiredInputMethodWindowIndexLocked(boolean willMove) { 1490 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the 1491 // same display. Or even when the current IME/target are not on the same screen as the next 1492 // IME/target. For now only look for input windows on the main screen. 1493 WindowList windows = getDefaultWindowListLocked(); 1494 WindowState w = null; 1495 int i; 1496 for (i = windows.size() - 1; i >= 0; --i) { 1497 WindowState win = windows.get(i); 1498 1499 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG_WM, "Checking window @" + i 1500 + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags)); 1501 if (canBeImeTarget(win)) { 1502 w = win; 1503 //Slog.i(TAG_WM, "Putting input method here!"); 1504 1505 // Yet more tricksyness! If this window is a "starting" 1506 // window, we do actually want to be on top of it, but 1507 // it is not -really- where input will go. So if the caller 1508 // is not actually looking to move the IME, look down below 1509 // for a real window to target... 1510 if (!willMove 1511 && w.mAttrs.type == TYPE_APPLICATION_STARTING 1512 && i > 0) { 1513 WindowState wb = windows.get(i-1); 1514 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) { 1515 i--; 1516 w = wb; 1517 } 1518 } 1519 break; 1520 } 1521 } 1522 1523 // Now w is either mWindows[0] or an IME (or null if mWindows is empty). 1524 1525 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG_WM, "Proposed new IME target: " + w); 1526 1527 // Now, a special case -- if the last target's window is in the 1528 // process of exiting, and is above the new target, keep on the 1529 // last target to avoid flicker. Consider for example a Dialog with 1530 // the IME shown: when the Dialog is dismissed, we want to keep 1531 // the IME above it until it is completely gone so it doesn't drop 1532 // behind the dialog or its full-screen scrim. 1533 final WindowState curTarget = mInputMethodTarget; 1534 if (curTarget != null 1535 && curTarget.isDisplayedLw() 1536 && curTarget.isClosing() 1537 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) { 1538 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing"); 1539 return windows.indexOf(curTarget) + 1; 1540 } 1541 1542 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" 1543 + w + " willMove=" + willMove); 1544 1545 if (willMove && w != null) { 1546 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken; 1547 if (token != null) { 1548 1549 // Now some fun for dealing with window animations that 1550 // modify the Z order. We need to look at all windows below 1551 // the current target that are in this app, finding the highest 1552 // visible one in layering. 1553 WindowState highestTarget = null; 1554 int highestPos = 0; 1555 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) { 1556 WindowList curWindows = curTarget.getWindowList(); 1557 int pos = curWindows.indexOf(curTarget); 1558 while (pos >= 0) { 1559 WindowState win = curWindows.get(pos); 1560 if (win.mAppToken != token) { 1561 break; 1562 } 1563 if (!win.mRemoved) { 1564 if (highestTarget == null || win.mWinAnimator.mAnimLayer > 1565 highestTarget.mWinAnimator.mAnimLayer) { 1566 highestTarget = win; 1567 highestPos = pos; 1568 } 1569 } 1570 pos--; 1571 } 1572 } 1573 1574 if (highestTarget != null) { 1575 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, mAppTransition + " " + highestTarget 1576 + " animating=" + highestTarget.mWinAnimator.isAnimationSet() 1577 + " layer=" + highestTarget.mWinAnimator.mAnimLayer 1578 + " new layer=" + w.mWinAnimator.mAnimLayer); 1579 1580 if (mAppTransition.isTransitionSet()) { 1581 // If we are currently setting up for an animation, 1582 // hold everything until we can find out what will happen. 1583 mInputMethodTargetWaitingAnim = true; 1584 mInputMethodTarget = highestTarget; 1585 return highestPos + 1; 1586 } else if (highestTarget.mWinAnimator.isAnimationSet() && 1587 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) { 1588 // If the window we are currently targeting is involved 1589 // with an animation, and it is on top of the next target 1590 // we will be over, then hold off on moving until 1591 // that is done. 1592 mInputMethodTargetWaitingAnim = true; 1593 mInputMethodTarget = highestTarget; 1594 return highestPos + 1; 1595 } 1596 } 1597 } 1598 } 1599 1600 //Slog.i(TAG_WM, "Placing input method @" + (i+1)); 1601 if (w != null) { 1602 if (willMove) { 1603 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to " 1604 + w + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : "")); 1605 mInputMethodTarget = w; 1606 mInputMethodTargetWaitingAnim = false; 1607 if (w.mAppToken != null) { 1608 mLayersController.setInputMethodAnimLayerAdjustment( 1609 w.mAppToken.mAppAnimator.animLayerAdjustment); 1610 } else { 1611 mLayersController.setInputMethodAnimLayerAdjustment(0); 1612 } 1613 } 1614 1615 // If the docked divider is visible, we still need to go through this whole 1616 // excercise to find the appropriate input method target (used for animations 1617 // and dialog adjustments), but for purposes of Z ordering we simply wish to 1618 // place it above the docked divider. Unless it is already above the divider. 1619 WindowState dockedDivider = w.mDisplayContent.mDividerControllerLocked.getWindow(); 1620 if (dockedDivider != null && dockedDivider.isVisibleLw()) { 1621 int dividerIndex = windows.indexOf(dockedDivider); 1622 if (dividerIndex > 0 && dividerIndex > i) { 1623 return dividerIndex + 1; 1624 } 1625 } 1626 return i+1; 1627 } 1628 if (willMove) { 1629 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to null." 1630 + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : "")); 1631 mInputMethodTarget = null; 1632 mLayersController.setInputMethodAnimLayerAdjustment(0); 1633 } 1634 return -1; 1635 } 1636 1637 void addInputMethodWindowToListLocked(WindowState win) { 1638 int pos = findDesiredInputMethodWindowIndexLocked(true); 1639 if (pos >= 0) { 1640 win.mTargetAppToken = mInputMethodTarget.mAppToken; 1641 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 1642 TAG_WM, "Adding input method window " + win + " at " + pos); 1643 // TODO(multidisplay): IMEs are only supported on the default display. 1644 getDefaultWindowListLocked().add(pos, win); 1645 mWindowsChanged = true; 1646 moveInputMethodDialogsLocked(pos + 1); 1647 return; 1648 } 1649 win.mTargetAppToken = null; 1650 addWindowToListInOrderLocked(win, true); 1651 moveInputMethodDialogsLocked(pos); 1652 } 1653 1654 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) { 1655 WindowList windows = win.getWindowList(); 1656 int wpos = windows.indexOf(win); 1657 if (wpos >= 0) { 1658 if (wpos < interestingPos) interestingPos--; 1659 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing at " + wpos + ": " + win); 1660 windows.remove(wpos); 1661 mWindowsChanged = true; 1662 int NC = win.mChildWindows.size(); 1663 while (NC > 0) { 1664 NC--; 1665 WindowState cw = win.mChildWindows.get(NC); 1666 int cpos = windows.indexOf(cw); 1667 if (cpos >= 0) { 1668 if (cpos < interestingPos) interestingPos--; 1669 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing child at " 1670 + cpos + ": " + cw); 1671 windows.remove(cpos); 1672 } 1673 } 1674 } 1675 return interestingPos; 1676 } 1677 1678 private void reAddWindowToListInOrderLocked(WindowState win) { 1679 addWindowToListInOrderLocked(win, false); 1680 // This is a hack to get all of the child windows added as well 1681 // at the right position. Child windows should be rare and 1682 // this case should be rare, so it shouldn't be that big a deal. 1683 WindowList windows = win.getWindowList(); 1684 int wpos = windows.indexOf(win); 1685 if (wpos >= 0) { 1686 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "ReAdd removing from " + wpos + ": " + win); 1687 windows.remove(wpos); 1688 mWindowsChanged = true; 1689 reAddWindowLocked(wpos, win); 1690 } 1691 } 1692 1693 void logWindowList(final WindowList windows, String prefix) { 1694 int N = windows.size(); 1695 while (N > 0) { 1696 N--; 1697 Slog.v(TAG_WM, prefix + "#" + N + ": " + windows.get(N)); 1698 } 1699 } 1700 1701 void moveInputMethodDialogsLocked(int pos) { 1702 ArrayList<WindowState> dialogs = mInputMethodDialogs; 1703 1704 // TODO(multidisplay): IMEs are only supported on the default display. 1705 WindowList windows = getDefaultWindowListLocked(); 1706 final int N = dialogs.size(); 1707 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Removing " + N + " dialogs w/pos=" + pos); 1708 for (int i=0; i<N; i++) { 1709 pos = tmpRemoveWindowLocked(pos, dialogs.get(i)); 1710 } 1711 if (DEBUG_INPUT_METHOD) { 1712 Slog.v(TAG_WM, "Window list w/pos=" + pos); 1713 logWindowList(windows, " "); 1714 } 1715 1716 if (pos >= 0) { 1717 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken; 1718 // Skip windows owned by the input method. 1719 if (mInputMethodWindow != null) { 1720 while (pos < windows.size()) { 1721 WindowState wp = windows.get(pos); 1722 if (wp == mInputMethodWindow || wp.mAttachedWindow == mInputMethodWindow) { 1723 pos++; 1724 continue; 1725 } 1726 break; 1727 } 1728 } 1729 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Adding " + N + " dialogs at pos=" + pos); 1730 for (int i=0; i<N; i++) { 1731 WindowState win = dialogs.get(i); 1732 win.mTargetAppToken = targetAppToken; 1733 pos = reAddWindowLocked(pos, win); 1734 } 1735 if (DEBUG_INPUT_METHOD) { 1736 Slog.v(TAG_WM, "Final window list:"); 1737 logWindowList(windows, " "); 1738 } 1739 return; 1740 } 1741 for (int i=0; i<N; i++) { 1742 WindowState win = dialogs.get(i); 1743 win.mTargetAppToken = null; 1744 reAddWindowToListInOrderLocked(win); 1745 if (DEBUG_INPUT_METHOD) { 1746 Slog.v(TAG_WM, "No IM target, final list:"); 1747 logWindowList(windows, " "); 1748 } 1749 } 1750 } 1751 1752 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) { 1753 final WindowState imWin = mInputMethodWindow; 1754 final int DN = mInputMethodDialogs.size(); 1755 if (imWin == null && DN == 0) { 1756 return false; 1757 } 1758 1759 // TODO(multidisplay): IMEs are only supported on the default display. 1760 WindowList windows = getDefaultWindowListLocked(); 1761 1762 int imPos = findDesiredInputMethodWindowIndexLocked(true); 1763 if (imPos >= 0) { 1764 // In this case, the input method windows are to be placed 1765 // immediately above the window they are targeting. 1766 1767 // First check to see if the input method windows are already 1768 // located here, and contiguous. 1769 final int N = windows.size(); 1770 WindowState firstImWin = imPos < N 1771 ? windows.get(imPos) : null; 1772 1773 // Figure out the actual input method window that should be 1774 // at the bottom of their stack. 1775 WindowState baseImWin = imWin != null 1776 ? imWin : mInputMethodDialogs.get(0); 1777 if (baseImWin.mChildWindows.size() > 0) { 1778 WindowState cw = baseImWin.mChildWindows.get(0); 1779 if (cw.mSubLayer < 0) baseImWin = cw; 1780 } 1781 1782 if (firstImWin == baseImWin) { 1783 // The windows haven't moved... but are they still contiguous? 1784 // First find the top IM window. 1785 int pos = imPos+1; 1786 while (pos < N) { 1787 if (!(windows.get(pos)).mIsImWindow) { 1788 break; 1789 } 1790 pos++; 1791 } 1792 pos++; 1793 // Now there should be no more input method windows above. 1794 while (pos < N) { 1795 if ((windows.get(pos)).mIsImWindow) { 1796 break; 1797 } 1798 pos++; 1799 } 1800 if (pos >= N) { 1801 // Z order is good. 1802 // The IM target window may be changed, so update the mTargetAppToken. 1803 if (imWin != null) { 1804 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1805 } 1806 return false; 1807 } 1808 } 1809 1810 if (imWin != null) { 1811 if (DEBUG_INPUT_METHOD) { 1812 Slog.v(TAG_WM, "Moving IM from " + imPos); 1813 logWindowList(windows, " "); 1814 } 1815 imPos = tmpRemoveWindowLocked(imPos, imWin); 1816 if (DEBUG_INPUT_METHOD) { 1817 Slog.v(TAG_WM, "List after removing with new pos " + imPos + ":"); 1818 logWindowList(windows, " "); 1819 } 1820 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1821 reAddWindowLocked(imPos, imWin); 1822 if (DEBUG_INPUT_METHOD) { 1823 Slog.v(TAG_WM, "List after moving IM to " + imPos + ":"); 1824 logWindowList(windows, " "); 1825 } 1826 if (DN > 0) moveInputMethodDialogsLocked(imPos+1); 1827 } else { 1828 moveInputMethodDialogsLocked(imPos); 1829 } 1830 1831 } else { 1832 // In this case, the input method windows go in a fixed layer, 1833 // because they aren't currently associated with a focus window. 1834 1835 if (imWin != null) { 1836 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Moving IM from " + imPos); 1837 tmpRemoveWindowLocked(0, imWin); 1838 imWin.mTargetAppToken = null; 1839 reAddWindowToListInOrderLocked(imWin); 1840 if (DEBUG_INPUT_METHOD) { 1841 Slog.v(TAG_WM, "List with no IM target:"); 1842 logWindowList(windows, " "); 1843 } 1844 if (DN > 0) moveInputMethodDialogsLocked(-1); 1845 } else { 1846 moveInputMethodDialogsLocked(-1); 1847 } 1848 1849 } 1850 1851 if (needAssignLayers) { 1852 mLayersController.assignLayersLocked(windows); 1853 } 1854 1855 return true; 1856 } 1857 1858 private static boolean excludeWindowTypeFromTapOutTask(int windowType) { 1859 switch (windowType) { 1860 case TYPE_STATUS_BAR: 1861 case TYPE_NAVIGATION_BAR: 1862 case TYPE_INPUT_METHOD_DIALOG: 1863 return true; 1864 } 1865 return false; 1866 } 1867 1868 public int addWindow(Session session, IWindow client, int seq, 1869 WindowManager.LayoutParams attrs, int viewVisibility, int displayId, 1870 Rect outContentInsets, Rect outStableInsets, Rect outOutsets, 1871 InputChannel outInputChannel) { 1872 int[] appOp = new int[1]; 1873 int res = mPolicy.checkAddPermission(attrs, appOp); 1874 if (res != WindowManagerGlobal.ADD_OKAY) { 1875 return res; 1876 } 1877 1878 boolean reportNewConfig = false; 1879 WindowState attachedWindow = null; 1880 long origId; 1881 final int callingUid = Binder.getCallingUid(); 1882 final int type = attrs.type; 1883 1884 synchronized(mWindowMap) { 1885 if (!mDisplayReady) { 1886 throw new IllegalStateException("Display has not been initialialized"); 1887 } 1888 1889 final DisplayContent displayContent = getDisplayContentLocked(displayId); 1890 if (displayContent == null) { 1891 Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: " 1892 + displayId + ". Aborting."); 1893 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 1894 } 1895 if (!displayContent.hasAccess(session.mUid)) { 1896 Slog.w(TAG_WM, "Attempted to add window to a display for which the application " 1897 + "does not have access: " + displayId + ". Aborting."); 1898 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 1899 } 1900 1901 if (mWindowMap.containsKey(client.asBinder())) { 1902 Slog.w(TAG_WM, "Window " + client + " is already added"); 1903 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 1904 } 1905 1906 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) { 1907 attachedWindow = windowForClientLocked(null, attrs.token, false); 1908 if (attachedWindow == null) { 1909 Slog.w(TAG_WM, "Attempted to add window with token that is not a window: " 1910 + attrs.token + ". Aborting."); 1911 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 1912 } 1913 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW 1914 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) { 1915 Slog.w(TAG_WM, "Attempted to add window with token that is a sub-window: " 1916 + attrs.token + ". Aborting."); 1917 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 1918 } 1919 } 1920 1921 if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) { 1922 Slog.w(TAG_WM, "Attempted to add private presentation window to a non-private display. Aborting."); 1923 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 1924 } 1925 1926 boolean addToken = false; 1927 WindowToken token = mTokenMap.get(attrs.token); 1928 AppWindowToken atoken = null; 1929 boolean addToastWindowRequiresToken = false; 1930 1931 if (token == null) { 1932 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 1933 Slog.w(TAG_WM, "Attempted to add application window with unknown token " 1934 + attrs.token + ". Aborting."); 1935 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1936 } 1937 if (type == TYPE_INPUT_METHOD) { 1938 Slog.w(TAG_WM, "Attempted to add input method window with unknown token " 1939 + attrs.token + ". Aborting."); 1940 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1941 } 1942 if (type == TYPE_VOICE_INTERACTION) { 1943 Slog.w(TAG_WM, "Attempted to add voice interaction window with unknown token " 1944 + attrs.token + ". Aborting."); 1945 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1946 } 1947 if (type == TYPE_WALLPAPER) { 1948 Slog.w(TAG_WM, "Attempted to add wallpaper window with unknown token " 1949 + attrs.token + ". Aborting."); 1950 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1951 } 1952 if (type == TYPE_DREAM) { 1953 Slog.w(TAG_WM, "Attempted to add Dream window with unknown token " 1954 + attrs.token + ". Aborting."); 1955 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1956 } 1957 if (type == TYPE_QS_DIALOG) { 1958 Slog.w(TAG_WM, "Attempted to add QS dialog window with unknown token " 1959 + attrs.token + ". Aborting."); 1960 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1961 } 1962 if (type == TYPE_ACCESSIBILITY_OVERLAY) { 1963 Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with unknown token " 1964 + attrs.token + ". Aborting."); 1965 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1966 } 1967 if (type == TYPE_TOAST) { 1968 // Apps targeting SDK above N MR1 cannot arbitrary add toast windows. 1969 if (doesAddToastWindowRequireToken(attrs.packageName, callingUid, 1970 attachedWindow)) { 1971 Slog.w(TAG_WM, "Attempted to add a toast window with unknown token " 1972 + attrs.token + ". Aborting."); 1973 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1974 } 1975 } 1976 token = new WindowToken(this, attrs.token, -1, false); 1977 addToken = true; 1978 } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 1979 atoken = token.appWindowToken; 1980 if (atoken == null) { 1981 Slog.w(TAG_WM, "Attempted to add window with non-application token " 1982 + token + ". Aborting."); 1983 return WindowManagerGlobal.ADD_NOT_APP_TOKEN; 1984 } else if (atoken.removed) { 1985 Slog.w(TAG_WM, "Attempted to add window with exiting application token " 1986 + token + ". Aborting."); 1987 return WindowManagerGlobal.ADD_APP_EXITING; 1988 } 1989 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) { 1990 // No need for this guy! 1991 if (DEBUG_STARTING_WINDOW || localLOGV) Slog.v( 1992 TAG_WM, "**** NO NEED TO START: " + attrs.getTitle()); 1993 return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED; 1994 } 1995 } else if (type == TYPE_INPUT_METHOD) { 1996 if (token.windowType != TYPE_INPUT_METHOD) { 1997 Slog.w(TAG_WM, "Attempted to add input method window with bad token " 1998 + attrs.token + ". Aborting."); 1999 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2000 } 2001 } else if (type == TYPE_VOICE_INTERACTION) { 2002 if (token.windowType != TYPE_VOICE_INTERACTION) { 2003 Slog.w(TAG_WM, "Attempted to add voice interaction window with bad token " 2004 + attrs.token + ". Aborting."); 2005 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2006 } 2007 } else if (type == TYPE_WALLPAPER) { 2008 if (token.windowType != TYPE_WALLPAPER) { 2009 Slog.w(TAG_WM, "Attempted to add wallpaper window with bad token " 2010 + attrs.token + ". Aborting."); 2011 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2012 } 2013 } else if (type == TYPE_DREAM) { 2014 if (token.windowType != TYPE_DREAM) { 2015 Slog.w(TAG_WM, "Attempted to add Dream window with bad token " 2016 + attrs.token + ". Aborting."); 2017 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2018 } 2019 } else if (type == TYPE_ACCESSIBILITY_OVERLAY) { 2020 if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) { 2021 Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with bad token " 2022 + attrs.token + ". Aborting."); 2023 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2024 } 2025 } else if (type == TYPE_TOAST) { 2026 // Apps targeting SDK above N MR1 cannot arbitrary add toast windows. 2027 addToastWindowRequiresToken = doesAddToastWindowRequireToken(attrs.packageName, 2028 callingUid, attachedWindow); 2029 if (addToastWindowRequiresToken && token.windowType != TYPE_TOAST) { 2030 Slog.w(TAG_WM, "Attempted to add a toast window with bad token " 2031 + attrs.token + ". Aborting."); 2032 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2033 } 2034 } else if (type == TYPE_QS_DIALOG) { 2035 if (token.windowType != TYPE_QS_DIALOG) { 2036 Slog.w(TAG_WM, "Attempted to add QS dialog window with bad token " 2037 + attrs.token + ". Aborting."); 2038 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2039 } 2040 } else if (token.appWindowToken != null) { 2041 Slog.w(TAG_WM, "Non-null appWindowToken for system window of type=" + type); 2042 // It is not valid to use an app token with other system types; we will 2043 // instead make a new token for it (as if null had been passed in for the token). 2044 attrs.token = null; 2045 token = new WindowToken(this, null, -1, false); 2046 addToken = true; 2047 } 2048 2049 WindowState win = new WindowState(this, session, client, token, 2050 attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent); 2051 if (win.mDeathRecipient == null) { 2052 // Client has apparently died, so there is no reason to 2053 // continue. 2054 Slog.w(TAG_WM, "Adding window client " + client.asBinder() 2055 + " that is dead, aborting."); 2056 return WindowManagerGlobal.ADD_APP_EXITING; 2057 } 2058 2059 if (win.getDisplayContent() == null) { 2060 Slog.w(TAG_WM, "Adding window to Display that has been removed."); 2061 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2062 } 2063 2064 mPolicy.adjustWindowParamsLw(win.mAttrs); 2065 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs)); 2066 2067 res = mPolicy.prepareAddWindowLw(win, attrs); 2068 if (res != WindowManagerGlobal.ADD_OKAY) { 2069 return res; 2070 } 2071 2072 final boolean openInputChannels = (outInputChannel != null 2073 && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0); 2074 if (openInputChannels) { 2075 win.openInputChannel(outInputChannel); 2076 } 2077 2078 // If adding a toast requires a token for this app we always schedule hiding 2079 // toast windows to make sure they don't stick around longer then necessary. 2080 // We hide instead of remove such windows as apps aren't prepared to handle 2081 // windows being removed under them. 2082 // 2083 // If the app is older it can add toasts without a token and hence overlay 2084 // other apps. To be maximally compatible with these apps we will hide the 2085 // window after the toast timeout only if the focused window is from another 2086 // UID, otherwise we allow unlimited duration. When a UID looses focus we 2087 // schedule hiding all of its toast windows. 2088 if (type == TYPE_TOAST) { 2089 if (!getDefaultDisplayContentLocked().canAddToastWindowForUid(callingUid)) { 2090 Slog.w(TAG_WM, "Adding more than one toast window for UID at a time."); 2091 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 2092 } 2093 // Make sure this happens before we moved focus as one can make the 2094 // toast focusable to force it not being hidden after the timeout. 2095 // Focusable toasts are always timed out to prevent a focused app to 2096 // show a focusable toasts while it has focus which will be kept on 2097 // the screen after the activity goes away. 2098 if (addToastWindowRequiresToken 2099 || (attrs.flags & LayoutParams.FLAG_NOT_FOCUSABLE) == 0 2100 || mCurrentFocus == null 2101 || mCurrentFocus.mOwnerUid != callingUid) { 2102 mH.sendMessageDelayed( 2103 mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, win), 2104 win.mAttrs.hideTimeoutMilliseconds); 2105 } 2106 } 2107 2108 // From now on, no exceptions or errors allowed! 2109 2110 res = WindowManagerGlobal.ADD_OKAY; 2111 2112 if (excludeWindowTypeFromTapOutTask(type)) { 2113 displayContent.mTapExcludedWindows.add(win); 2114 } 2115 2116 origId = Binder.clearCallingIdentity(); 2117 2118 if (addToken) { 2119 mTokenMap.put(attrs.token, token); 2120 } 2121 win.attach(); 2122 mWindowMap.put(client.asBinder(), win); 2123 if (win.mAppOp != AppOpsManager.OP_NONE) { 2124 int startOpResult = mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), 2125 win.getOwningPackage()); 2126 if ((startOpResult != AppOpsManager.MODE_ALLOWED) && 2127 (startOpResult != AppOpsManager.MODE_DEFAULT)) { 2128 win.setAppOpVisibilityLw(false); 2129 } 2130 } 2131 2132 if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) { 2133 token.appWindowToken.startingWindow = win; 2134 if (DEBUG_STARTING_WINDOW) Slog.v (TAG_WM, "addWindow: " + token.appWindowToken 2135 + " startingWindow=" + win); 2136 } 2137 2138 boolean imMayMove = true; 2139 2140 if (type == TYPE_INPUT_METHOD) { 2141 win.mGivenInsetsPending = true; 2142 mInputMethodWindow = win; 2143 addInputMethodWindowToListLocked(win); 2144 imMayMove = false; 2145 } else if (type == TYPE_INPUT_METHOD_DIALOG) { 2146 mInputMethodDialogs.add(win); 2147 addWindowToListInOrderLocked(win, true); 2148 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true)); 2149 imMayMove = false; 2150 } else { 2151 addWindowToListInOrderLocked(win, true); 2152 if (type == TYPE_WALLPAPER) { 2153 mWallpaperControllerLocked.clearLastWallpaperTimeoutTime(); 2154 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2155 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2156 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2157 } else if (mWallpaperControllerLocked.isBelowWallpaperTarget(win)) { 2158 // If there is currently a wallpaper being shown, and 2159 // the base layer of the new window is below the current 2160 // layer of the target window, then adjust the wallpaper. 2161 // This is to avoid a new window being placed between the 2162 // wallpaper and its target. 2163 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2164 } 2165 } 2166 2167 // If the window is being added to a task that's docked but non-resizeable, 2168 // we need to update this new window's scroll position when it's added. 2169 win.applyScrollIfNeeded(); 2170 2171 // If the window is being added to a stack that's currently adjusted for IME, 2172 // make sure to apply the same adjust to this new window. 2173 win.applyAdjustForImeIfNeeded(); 2174 2175 if (type == TYPE_DOCK_DIVIDER) { 2176 getDefaultDisplayContentLocked().getDockedDividerController().setWindow(win); 2177 } 2178 2179 final WindowStateAnimator winAnimator = win.mWinAnimator; 2180 winAnimator.mEnterAnimationPending = true; 2181 winAnimator.mEnteringAnimation = true; 2182 // Check if we need to prepare a transition for replacing window first. 2183 if (atoken != null && !prepareWindowReplacementTransition(atoken)) { 2184 // If not, check if need to set up a dummy transition during display freeze 2185 // so that the unfreeze wait for the apps to draw. This might be needed if 2186 // the app is relaunching. 2187 prepareNoneTransitionForRelaunching(atoken); 2188 } 2189 2190 if (displayContent.isDefaultDisplay) { 2191 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2192 final Rect taskBounds; 2193 if (atoken != null && atoken.mTask != null) { 2194 taskBounds = mTmpRect; 2195 atoken.mTask.getBounds(mTmpRect); 2196 } else { 2197 taskBounds = null; 2198 } 2199 if (mPolicy.getInsetHintLw(win.mAttrs, taskBounds, mRotation, 2200 displayInfo.logicalWidth, displayInfo.logicalHeight, outContentInsets, 2201 outStableInsets, outOutsets)) { 2202 res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR; 2203 } 2204 } else { 2205 outContentInsets.setEmpty(); 2206 outStableInsets.setEmpty(); 2207 } 2208 2209 if (mInTouchMode) { 2210 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE; 2211 } 2212 if (win.mAppToken == null || !win.mAppToken.clientHidden) { 2213 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE; 2214 } 2215 2216 mInputMonitor.setUpdateInputWindowsNeededLw(); 2217 2218 boolean focusChanged = false; 2219 if (win.canReceiveKeys()) { 2220 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, 2221 false /*updateInputWindows*/); 2222 if (focusChanged) { 2223 imMayMove = false; 2224 } 2225 } 2226 2227 if (imMayMove) { 2228 moveInputMethodWindowsIfNeededLocked(false); 2229 } 2230 2231 mLayersController.assignLayersLocked(displayContent.getWindowList()); 2232 // Don't do layout here, the window must call 2233 // relayout to be displayed, so we'll do it there. 2234 2235 if (focusChanged) { 2236 mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/); 2237 } 2238 mInputMonitor.updateInputWindowsLw(false /*force*/); 2239 2240 if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client " 2241 + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5)); 2242 2243 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) { 2244 reportNewConfig = true; 2245 } 2246 } 2247 2248 if (reportNewConfig) { 2249 sendNewConfiguration(); 2250 } 2251 2252 Binder.restoreCallingIdentity(origId); 2253 2254 return res; 2255 } 2256 2257 private boolean doesAddToastWindowRequireToken(String packageName, int callingUid, 2258 WindowState attachedWindow) { 2259 // Try using the target SDK of the root window 2260 if (attachedWindow != null) { 2261 return attachedWindow.mAppToken != null 2262 && attachedWindow.mAppToken.targetSdk > Build.VERSION_CODES.N_MR1; 2263 } else { 2264 // Otherwise, look at the package 2265 try { 2266 ApplicationInfo appInfo = mContext.getPackageManager() 2267 .getApplicationInfoAsUser(packageName, 0, 2268 UserHandle.getUserId(callingUid)); 2269 if (appInfo.uid != callingUid) { 2270 throw new SecurityException("Package " + packageName + " not in UID " 2271 + callingUid); 2272 } 2273 if (appInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1) { 2274 return true; 2275 } 2276 } catch (PackageManager.NameNotFoundException e) { 2277 /* ignore */ 2278 } 2279 } 2280 return false; 2281 } 2282 2283 /** 2284 * Returns true if we're done setting up any transitions. 2285 */ 2286 private boolean prepareWindowReplacementTransition(AppWindowToken atoken) { 2287 atoken.clearAllDrawn(); 2288 WindowState replacedWindow = null; 2289 for (int i = atoken.windows.size() - 1; i >= 0 && replacedWindow == null; i--) { 2290 WindowState candidate = atoken.windows.get(i); 2291 if (candidate.mAnimatingExit && candidate.mWillReplaceWindow 2292 && candidate.mAnimateReplacingWindow) { 2293 replacedWindow = candidate; 2294 } 2295 } 2296 if (replacedWindow == null) { 2297 // We expect to already receive a request to remove the old window. If it did not 2298 // happen, let's just simply add a window. 2299 return false; 2300 } 2301 // We use the visible frame, because we want the animation to morph the window from what 2302 // was visible to the user to the final destination of the new window. 2303 Rect frame = replacedWindow.mVisibleFrame; 2304 // We treat this as if this activity was opening, so we can trigger the app transition 2305 // animation and piggy-back on existing transition animation infrastructure. 2306 mOpeningApps.add(atoken); 2307 prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_RELAUNCH, ALWAYS_KEEP_CURRENT); 2308 mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top, 2309 frame.width(), frame.height()); 2310 executeAppTransition(); 2311 return true; 2312 } 2313 2314 private void prepareNoneTransitionForRelaunching(AppWindowToken atoken) { 2315 // Set up a none-transition and add the app to opening apps, so that the display 2316 // unfreeze wait for the apps to be drawn. 2317 // Note that if the display unfroze already because app unfreeze timed out, 2318 // we don't set up the transition anymore and just let it go. 2319 if (mDisplayFrozen && !mOpeningApps.contains(atoken) && atoken.isRelaunching()) { 2320 mOpeningApps.add(atoken); 2321 prepareAppTransition(AppTransition.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT); 2322 executeAppTransition(); 2323 } 2324 } 2325 2326 /** 2327 * Returns whether screen capture is disabled for all windows of a specific user. 2328 */ 2329 boolean isScreenCaptureDisabledLocked(int userId) { 2330 Boolean disabled = mScreenCaptureDisabled.get(userId); 2331 if (disabled == null) { 2332 return false; 2333 } 2334 return disabled; 2335 } 2336 2337 boolean isSecureLocked(WindowState w) { 2338 if ((w.mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) { 2339 return true; 2340 } 2341 if (isScreenCaptureDisabledLocked(UserHandle.getUserId(w.mOwnerUid))) { 2342 return true; 2343 } 2344 return false; 2345 } 2346 2347 /** 2348 * Set mScreenCaptureDisabled for specific user 2349 */ 2350 @Override 2351 public void setScreenCaptureDisabled(int userId, boolean disabled) { 2352 int callingUid = Binder.getCallingUid(); 2353 if (callingUid != Process.SYSTEM_UID) { 2354 throw new SecurityException("Only system can call setScreenCaptureDisabled."); 2355 } 2356 2357 synchronized(mWindowMap) { 2358 mScreenCaptureDisabled.put(userId, disabled); 2359 // Update secure surface for all windows belonging to this user. 2360 for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) { 2361 WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 2362 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 2363 final WindowState win = windows.get(winNdx); 2364 if (win.mHasSurface && userId == UserHandle.getUserId(win.mOwnerUid)) { 2365 win.mWinAnimator.setSecureLocked(disabled); 2366 } 2367 } 2368 } 2369 } 2370 } 2371 2372 private void setupWindowForRemoveOnExit(WindowState win) { 2373 win.mRemoveOnExit = true; 2374 win.setDisplayLayoutNeeded(); 2375 // Request a focus update as this window's input channel is already gone. Otherwise 2376 // we could have no focused window in input manager. 2377 final boolean focusChanged = updateFocusedWindowLocked( 2378 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/); 2379 mWindowPlacerLocked.performSurfacePlacement(); 2380 if (focusChanged) { 2381 mInputMonitor.updateInputWindowsLw(false /*force*/); 2382 } 2383 } 2384 2385 public void removeWindow(Session session, IWindow client) { 2386 synchronized(mWindowMap) { 2387 WindowState win = windowForClientLocked(session, client, false); 2388 if (win == null) { 2389 return; 2390 } 2391 removeWindowLocked(win); 2392 } 2393 } 2394 2395 void removeWindowLocked(WindowState win) { 2396 removeWindowLocked(win, false); 2397 } 2398 2399 void removeWindowLocked(WindowState win, boolean keepVisibleDeadWindow) { 2400 win.mWindowRemovalAllowed = true; 2401 if (DEBUG_ADD_REMOVE) Slog.v(TAG, 2402 "removeWindowLocked: " + win + " callers=" + Debug.getCallers(4)); 2403 2404 final boolean startingWindow = win.mAttrs.type == TYPE_APPLICATION_STARTING; 2405 if (startingWindow) { 2406 if (DEBUG_STARTING_WINDOW) Slog.d(TAG_WM, "Starting window removed " + win); 2407 } 2408 2409 if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win == mCurrentFocus) Slog.v( 2410 TAG_WM, "Remove " + win + " client=" 2411 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder())) 2412 + ", surfaceController=" + win.mWinAnimator.mSurfaceController + " Callers=" 2413 + Debug.getCallers(4)); 2414 2415 final long origId = Binder.clearCallingIdentity(); 2416 2417 win.disposeInputChannel(); 2418 2419 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, 2420 "Remove " + win + ": mSurfaceController=" + win.mWinAnimator.mSurfaceController 2421 + " mAnimatingExit=" + win.mAnimatingExit 2422 + " mRemoveOnExit=" + win.mRemoveOnExit 2423 + " mHasSurface=" + win.mHasSurface 2424 + " surfaceShowing=" + win.mWinAnimator.getShown() 2425 + " isAnimationSet=" + win.mWinAnimator.isAnimationSet() 2426 + " app-animation=" 2427 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null) 2428 + " mWillReplaceWindow=" + win.mWillReplaceWindow 2429 + " inPendingTransaction=" 2430 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false) 2431 + " mDisplayFrozen=" + mDisplayFrozen 2432 + " callers=" + Debug.getCallers(6)); 2433 // Visibility of the removed window. Will be used later to update orientation later on. 2434 boolean wasVisible = false; 2435 // First, see if we need to run an animation. If we do, we have to hold off on removing the 2436 // window until the animation is done. If the display is frozen, just remove immediately, 2437 // since the animation wouldn't be seen. 2438 if (win.mHasSurface && okToDisplay()) { 2439 final AppWindowToken appToken = win.mAppToken; 2440 if (win.mWillReplaceWindow) { 2441 // This window is going to be replaced. We need to keep it around until the new one 2442 // gets added, then we will get rid of this one. 2443 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Preserving " + win + " until the new one is " 2444 + "added"); 2445 // TODO: We are overloading mAnimatingExit flag to prevent the window state from 2446 // been removed. We probably need another flag to indicate that window removal 2447 // should be deffered vs. overloading the flag that says we are playing an exit 2448 // animation. 2449 win.mAnimatingExit = true; 2450 win.mReplacingRemoveRequested = true; 2451 Binder.restoreCallingIdentity(origId); 2452 return; 2453 } 2454 2455 if (win.isAnimatingWithSavedSurface() && !appToken.allDrawnExcludingSaved) { 2456 // We started enter animation early with a saved surface, now the app asks to remove 2457 // this window. If we remove it now and the app is not yet drawn, we'll show a 2458 // flicker. Delay the removal now until it's really drawn. 2459 if (DEBUG_ADD_REMOVE) { 2460 Slog.d(TAG_WM, "removeWindowLocked: delay removal of " + win 2461 + " due to early animation"); 2462 } 2463 // Do not set mAnimatingExit to true here, it will cause the surface to be hidden 2464 // immediately after the enter animation is done. If the app is not yet drawn then 2465 // it will show up as a flicker. 2466 setupWindowForRemoveOnExit(win); 2467 Binder.restoreCallingIdentity(origId); 2468 return; 2469 } 2470 // If we are not currently running the exit animation, we need to see about starting one 2471 wasVisible = win.isWinVisibleLw(); 2472 2473 if (keepVisibleDeadWindow) { 2474 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 2475 "Not removing " + win + " because app died while it's visible"); 2476 2477 win.mAppDied = true; 2478 win.setDisplayLayoutNeeded(); 2479 mWindowPlacerLocked.performSurfacePlacement(); 2480 2481 // Set up a replacement input channel since the app is now dead. 2482 // We need to catch tapping on the dead window to restart the app. 2483 win.openInputChannel(null); 2484 mInputMonitor.updateInputWindowsLw(true /*force*/); 2485 2486 Binder.restoreCallingIdentity(origId); 2487 return; 2488 } 2489 2490 final WindowStateAnimator winAnimator = win.mWinAnimator; 2491 if (wasVisible) { 2492 final int transit = (!startingWindow) ? TRANSIT_EXIT : TRANSIT_PREVIEW_DONE; 2493 2494 // Try starting an animation. 2495 if (winAnimator.applyAnimationLocked(transit, false)) { 2496 win.mAnimatingExit = true; 2497 } 2498 //TODO (multidisplay): Magnification is supported only for the default display. 2499 if (mAccessibilityController != null 2500 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 2501 mAccessibilityController.onWindowTransitionLocked(win, transit); 2502 } 2503 } 2504 final boolean isAnimating = 2505 winAnimator.isAnimationSet() && !winAnimator.isDummyAnimation(); 2506 final boolean lastWindowIsStartingWindow = startingWindow && appToken != null 2507 && appToken.allAppWindows.size() == 1; 2508 // We delay the removal of a window if it has a showing surface that can be used to run 2509 // exit animation and it is marked as exiting. 2510 // Also, If isn't the an animating starting window that is the last window in the app. 2511 // We allow the removal of the non-animating starting window now as there is no 2512 // additional window or animation that will trigger its removal. 2513 if (winAnimator.getShown() && win.mAnimatingExit 2514 && (!lastWindowIsStartingWindow || isAnimating)) { 2515 // The exit animation is running or should run... wait for it! 2516 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 2517 "Not removing " + win + " due to exit animation "); 2518 setupWindowForRemoveOnExit(win); 2519 if (appToken != null) { 2520 appToken.updateReportedVisibilityLocked(); 2521 } 2522 Binder.restoreCallingIdentity(origId); 2523 return; 2524 } 2525 } 2526 2527 removeWindowInnerLocked(win); 2528 // Removing a visible window will effect the computed orientation 2529 // So just update orientation if needed. 2530 if (wasVisible && updateOrientationFromAppTokensLocked(false)) { 2531 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 2532 } 2533 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 2534 Binder.restoreCallingIdentity(origId); 2535 } 2536 2537 void removeWindowInnerLocked(WindowState win) { 2538 if (win.mRemoved) { 2539 // Nothing to do. 2540 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 2541 "removeWindowInnerLocked: " + win + " Already removed..."); 2542 return; 2543 } 2544 2545 for (int i = win.mChildWindows.size() - 1; i >= 0; i--) { 2546 WindowState cwin = win.mChildWindows.get(i); 2547 Slog.w(TAG_WM, "Force-removing child win " + cwin + " from container " + win); 2548 removeWindowInnerLocked(cwin); 2549 } 2550 2551 win.mRemoved = true; 2552 2553 if (mInputMethodTarget == win) { 2554 moveInputMethodWindowsIfNeededLocked(false); 2555 } 2556 2557 if (false) { 2558 RuntimeException e = new RuntimeException("here"); 2559 e.fillInStackTrace(); 2560 Slog.w(TAG_WM, "Removing window " + win, e); 2561 } 2562 2563 final int type = win.mAttrs.type; 2564 if (excludeWindowTypeFromTapOutTask(type)) { 2565 final DisplayContent displaycontent = win.getDisplayContent(); 2566 displaycontent.mTapExcludedWindows.remove(win); 2567 } 2568 mPolicy.removeWindowLw(win); 2569 win.removeLocked(); 2570 2571 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "removeWindowInnerLocked: " + win); 2572 mWindowMap.remove(win.mClient.asBinder()); 2573 if (win.mAppOp != AppOpsManager.OP_NONE) { 2574 mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage()); 2575 } 2576 2577 mPendingRemove.remove(win); 2578 mResizingWindows.remove(win); 2579 mWindowsChanged = true; 2580 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Final remove of window: " + win); 2581 2582 if (mInputMethodWindow == win) { 2583 mInputMethodWindow = null; 2584 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) { 2585 mInputMethodDialogs.remove(win); 2586 } 2587 2588 final WindowToken token = win.mToken; 2589 final AppWindowToken atoken = win.mAppToken; 2590 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Removing " + win + " from " + token); 2591 token.windows.remove(win); 2592 if (atoken != null) { 2593 atoken.allAppWindows.remove(win); 2594 } 2595 if (localLOGV) Slog.v( 2596 TAG_WM, "**** Removing window " + win + ": count=" 2597 + token.windows.size()); 2598 if (token.windows.size() == 0) { 2599 if (!token.explicit) { 2600 mTokenMap.remove(token.token); 2601 } else if (atoken != null) { 2602 atoken.firstWindowDrawn = false; 2603 atoken.clearAllDrawn(); 2604 } 2605 } 2606 2607 if (atoken != null) { 2608 if (atoken.startingWindow == win) { 2609 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win); 2610 scheduleRemoveStartingWindowLocked(atoken); 2611 } else 2612 if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) { 2613 // If this is the last window and we had requested a starting 2614 // transition window, well there is no point now. 2615 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingWindow"); 2616 atoken.startingData = null; 2617 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) { 2618 // If this is the last window except for a starting transition 2619 // window, we need to get rid of the starting transition. 2620 scheduleRemoveStartingWindowLocked(atoken); 2621 } 2622 } 2623 2624 if (type == TYPE_WALLPAPER) { 2625 mWallpaperControllerLocked.clearLastWallpaperTimeoutTime(); 2626 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2627 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2628 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2629 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2630 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2631 } 2632 2633 final WindowList windows = win.getWindowList(); 2634 if (windows != null) { 2635 windows.remove(win); 2636 if (!mWindowPlacerLocked.isInLayout()) { 2637 mLayersController.assignLayersLocked(windows); 2638 win.setDisplayLayoutNeeded(); 2639 mWindowPlacerLocked.performSurfacePlacement(); 2640 if (win.mAppToken != null) { 2641 win.mAppToken.updateReportedVisibilityLocked(); 2642 } 2643 } 2644 } 2645 2646 mInputMonitor.updateInputWindowsLw(true /*force*/); 2647 } 2648 2649 public void updateAppOpsState() { 2650 synchronized(mWindowMap) { 2651 final int numDisplays = mDisplayContents.size(); 2652 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 2653 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 2654 final int numWindows = windows.size(); 2655 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 2656 final WindowState win = windows.get(winNdx); 2657 if (win.mAppOp != AppOpsManager.OP_NONE) { 2658 final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(), 2659 win.getOwningPackage()); 2660 win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED || 2661 mode == AppOpsManager.MODE_DEFAULT); 2662 } 2663 } 2664 } 2665 } 2666 } 2667 2668 static void logSurface(WindowState w, String msg, boolean withStackTrace) { 2669 String str = " SURFACE " + msg + ": " + w; 2670 if (withStackTrace) { 2671 logWithStack(TAG, str); 2672 } else { 2673 Slog.i(TAG_WM, str); 2674 } 2675 } 2676 2677 static void logSurface(SurfaceControl s, String title, String msg) { 2678 String str = " SURFACE " + s + ": " + msg + " / " + title; 2679 Slog.i(TAG_WM, str); 2680 } 2681 2682 static void logWithStack(String tag, String s) { 2683 RuntimeException e = null; 2684 if (SHOW_STACK_CRAWLS) { 2685 e = new RuntimeException(); 2686 e.fillInStackTrace(); 2687 } 2688 Slog.i(tag, s, e); 2689 } 2690 2691 void setTransparentRegionWindow(Session session, IWindow client, Region region) { 2692 long origId = Binder.clearCallingIdentity(); 2693 try { 2694 synchronized (mWindowMap) { 2695 WindowState w = windowForClientLocked(session, client, false); 2696 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, 2697 "transparentRegionHint=" + region, false); 2698 2699 if ((w != null) && w.mHasSurface) { 2700 w.mWinAnimator.setTransparentRegionHintLocked(region); 2701 } 2702 } 2703 } finally { 2704 Binder.restoreCallingIdentity(origId); 2705 } 2706 } 2707 2708 void setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets, 2709 Rect visibleInsets, Region touchableRegion) { 2710 long origId = Binder.clearCallingIdentity(); 2711 try { 2712 synchronized (mWindowMap) { 2713 WindowState w = windowForClientLocked(session, client, false); 2714 if (DEBUG_LAYOUT) Slog.d(TAG, "setInsetsWindow " + w 2715 + ", contentInsets=" + w.mGivenContentInsets + " -> " + contentInsets 2716 + ", visibleInsets=" + w.mGivenVisibleInsets + " -> " + visibleInsets 2717 + ", touchableRegion=" + w.mGivenTouchableRegion + " -> " + touchableRegion 2718 + ", touchableInsets " + w.mTouchableInsets + " -> " + touchableInsets); 2719 if (w != null) { 2720 w.mGivenInsetsPending = false; 2721 w.mGivenContentInsets.set(contentInsets); 2722 w.mGivenVisibleInsets.set(visibleInsets); 2723 w.mGivenTouchableRegion.set(touchableRegion); 2724 w.mTouchableInsets = touchableInsets; 2725 if (w.mGlobalScale != 1) { 2726 w.mGivenContentInsets.scale(w.mGlobalScale); 2727 w.mGivenVisibleInsets.scale(w.mGlobalScale); 2728 w.mGivenTouchableRegion.scale(w.mGlobalScale); 2729 } 2730 w.setDisplayLayoutNeeded(); 2731 mWindowPlacerLocked.performSurfacePlacement(); 2732 } 2733 } 2734 } finally { 2735 Binder.restoreCallingIdentity(origId); 2736 } 2737 } 2738 2739 public void getWindowDisplayFrame(Session session, IWindow client, 2740 Rect outDisplayFrame) { 2741 synchronized(mWindowMap) { 2742 WindowState win = windowForClientLocked(session, client, false); 2743 if (win == null) { 2744 outDisplayFrame.setEmpty(); 2745 return; 2746 } 2747 outDisplayFrame.set(win.mDisplayFrame); 2748 } 2749 } 2750 2751 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) { 2752 synchronized (mWindowMap) { 2753 if (mAccessibilityController != null) { 2754 WindowState window = mWindowMap.get(token); 2755 //TODO (multidisplay): Magnification is supported only for the default display. 2756 if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 2757 mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle); 2758 } 2759 } 2760 } 2761 } 2762 2763 public IWindowId getWindowId(IBinder token) { 2764 synchronized (mWindowMap) { 2765 WindowState window = mWindowMap.get(token); 2766 return window != null ? window.mWindowId : null; 2767 } 2768 } 2769 2770 public void pokeDrawLock(Session session, IBinder token) { 2771 synchronized (mWindowMap) { 2772 WindowState window = windowForClientLocked(session, token, false); 2773 if (window != null) { 2774 window.pokeDrawLockLw(mDrawLockTimeoutMillis); 2775 } 2776 } 2777 } 2778 2779 void repositionChild(Session session, IWindow client, 2780 int left, int top, int right, int bottom, 2781 long frameNumber, Rect outFrame) { 2782 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "repositionChild"); 2783 long origId = Binder.clearCallingIdentity(); 2784 2785 try { 2786 synchronized(mWindowMap) { 2787 WindowState win = windowForClientLocked(session, client, false); 2788 if (win == null) { 2789 return; 2790 } 2791 if (win.mAttachedWindow == null) { 2792 throw new IllegalArgumentException( 2793 "repositionChild called but window is not" 2794 + "attached to a parent win=" + win); 2795 } 2796 2797 win.mAttrs.x = left; 2798 win.mAttrs.y = top; 2799 win.mAttrs.width = right - left; 2800 win.mAttrs.height = bottom - top; 2801 win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight); 2802 2803 if (win.mHasSurface) { 2804 if (SHOW_TRANSACTIONS) { 2805 Slog.i(TAG_WM, ">>> OPEN TRANSACTION repositionChild"); 2806 } 2807 2808 SurfaceControl.openTransaction(); 2809 2810 try { 2811 2812 win.applyGravityAndUpdateFrame(win.mContainingFrame, win.mDisplayFrame); 2813 win.mWinAnimator.computeShownFrameLocked(); 2814 2815 win.mWinAnimator.setSurfaceBoundariesLocked(false); 2816 2817 if (frameNumber > 0) { 2818 win.mWinAnimator.deferTransactionUntilParentFrame(frameNumber); 2819 } 2820 2821 } finally { 2822 SurfaceControl.closeTransaction(); 2823 if (SHOW_TRANSACTIONS) { 2824 Slog.i(TAG_WM, "<<< CLOSE TRANSACTION repositionChild"); 2825 } 2826 } 2827 } 2828 2829 outFrame = win.mCompatFrame; 2830 } 2831 } finally { 2832 Binder.restoreCallingIdentity(origId); 2833 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 2834 } 2835 } 2836 2837 public int relayoutWindow(Session session, IWindow client, int seq, 2838 WindowManager.LayoutParams attrs, int requestedWidth, 2839 int requestedHeight, int viewVisibility, int flags, 2840 Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, 2841 Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame, 2842 Configuration outConfig, Surface outSurface) { 2843 int result = 0; 2844 boolean configChanged; 2845 boolean hasStatusBarPermission = 2846 mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 2847 == PackageManager.PERMISSION_GRANTED; 2848 2849 long origId = Binder.clearCallingIdentity(); 2850 synchronized(mWindowMap) { 2851 WindowState win = windowForClientLocked(session, client, false); 2852 if (win == null) { 2853 return 0; 2854 } 2855 2856 WindowStateAnimator winAnimator = win.mWinAnimator; 2857 if (viewVisibility != View.GONE) { 2858 win.setRequestedSize(requestedWidth, requestedHeight); 2859 } 2860 2861 int attrChanges = 0; 2862 int flagChanges = 0; 2863 if (attrs != null) { 2864 mPolicy.adjustWindowParamsLw(attrs); 2865 // if they don't have the permission, mask out the status bar bits 2866 if (seq == win.mSeq) { 2867 int systemUiVisibility = attrs.systemUiVisibility 2868 | attrs.subtreeSystemUiVisibility; 2869 if ((systemUiVisibility & DISABLE_MASK) != 0) { 2870 if (!hasStatusBarPermission) { 2871 systemUiVisibility &= ~DISABLE_MASK; 2872 } 2873 } 2874 win.mSystemUiVisibility = systemUiVisibility; 2875 } 2876 if (win.mAttrs.type != attrs.type) { 2877 throw new IllegalArgumentException( 2878 "Window type can not be changed after the window is added."); 2879 } 2880 2881 // Odd choice but less odd than embedding in copyFrom() 2882 if ((attrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY) 2883 != 0) { 2884 attrs.x = win.mAttrs.x; 2885 attrs.y = win.mAttrs.y; 2886 attrs.width = win.mAttrs.width; 2887 attrs.height = win.mAttrs.height; 2888 } 2889 2890 flagChanges = win.mAttrs.flags ^= attrs.flags; 2891 attrChanges = win.mAttrs.copyFrom(attrs); 2892 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED 2893 | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) { 2894 win.mLayoutNeeded = true; 2895 } 2896 } 2897 2898 if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility 2899 + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs); 2900 winAnimator.mSurfaceDestroyDeferred = (flags & RELAYOUT_DEFER_SURFACE_DESTROY) != 0; 2901 win.mEnforceSizeCompat = 2902 (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0; 2903 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) { 2904 winAnimator.mAlpha = attrs.alpha; 2905 } 2906 win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight); 2907 2908 if (win.mAttrs.surfaceInsets.left != 0 2909 || win.mAttrs.surfaceInsets.top != 0 2910 || win.mAttrs.surfaceInsets.right != 0 2911 || win.mAttrs.surfaceInsets.bottom != 0) { 2912 winAnimator.setOpaqueLocked(false); 2913 } 2914 2915 boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0; 2916 final boolean isDefaultDisplay = win.isDefaultDisplay(); 2917 boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility 2918 || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0) 2919 || (!win.mRelayoutCalled)); 2920 2921 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility 2922 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0; 2923 wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0; 2924 if ((flagChanges & FLAG_SECURE) != 0 && winAnimator.mSurfaceController != null) { 2925 winAnimator.mSurfaceController.setSecure(isSecureLocked(win)); 2926 } 2927 2928 win.mRelayoutCalled = true; 2929 win.mInRelayout = true; 2930 2931 final int oldVisibility = win.mViewVisibility; 2932 win.mViewVisibility = viewVisibility; 2933 if (DEBUG_SCREEN_ON) { 2934 RuntimeException stack = new RuntimeException(); 2935 stack.fillInStackTrace(); 2936 Slog.i(TAG_WM, "Relayout " + win + ": oldVis=" + oldVisibility 2937 + " newVis=" + viewVisibility, stack); 2938 } 2939 if (viewVisibility == View.VISIBLE && 2940 (win.mAppToken == null || !win.mAppToken.clientHidden)) { 2941 result = relayoutVisibleWindow(outConfig, result, win, winAnimator, attrChanges, 2942 oldVisibility); 2943 try { 2944 result = createSurfaceControl(outSurface, result, win, winAnimator); 2945 } catch (Exception e) { 2946 mInputMonitor.updateInputWindowsLw(true /*force*/); 2947 2948 Slog.w(TAG_WM, "Exception thrown when creating surface for client " 2949 + client + " (" + win.mAttrs.getTitle() + ")", 2950 e); 2951 Binder.restoreCallingIdentity(origId); 2952 return 0; 2953 } 2954 if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { 2955 focusMayChange = isDefaultDisplay; 2956 } 2957 if (win.mAttrs.type == TYPE_INPUT_METHOD && mInputMethodWindow == null) { 2958 mInputMethodWindow = win; 2959 imMayMove = true; 2960 } 2961 win.adjustStartingWindowFlags(); 2962 } else { 2963 winAnimator.mEnterAnimationPending = false; 2964 winAnimator.mEnteringAnimation = false; 2965 final boolean usingSavedSurfaceBeforeVisible = 2966 oldVisibility != View.VISIBLE && win.isAnimatingWithSavedSurface(); 2967 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { 2968 if (winAnimator.hasSurface() && !win.mAnimatingExit 2969 && usingSavedSurfaceBeforeVisible) { 2970 Slog.d(TAG, "Ignoring layout to invisible when using saved surface " + win); 2971 } 2972 } 2973 2974 if (winAnimator.hasSurface() && !win.mAnimatingExit 2975 && !usingSavedSurfaceBeforeVisible) { 2976 if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Relayout invis " + win 2977 + ": mAnimatingExit=" + win.mAnimatingExit); 2978 // If we are not currently running the exit animation, we 2979 // need to see about starting one. 2980 // We don't want to animate visibility of windows which are pending 2981 // replacement. In the case of activity relaunch child windows 2982 // could request visibility changes as they are detached from the main 2983 // application window during the tear down process. If we satisfied 2984 // these visibility changes though, we would cause a visual glitch 2985 // hiding the window before it's replacement was available. 2986 // So we just do nothing on our side. 2987 if (!win.mWillReplaceWindow) { 2988 focusMayChange = tryStartExitingAnimation( 2989 win, winAnimator, isDefaultDisplay, focusMayChange); 2990 } 2991 result |= RELAYOUT_RES_SURFACE_CHANGED; 2992 } 2993 if (viewVisibility == View.VISIBLE && winAnimator.hasSurface()) { 2994 // We already told the client to go invisible, but the message may not be 2995 // handled yet, or it might want to draw a last frame. If we already have a 2996 // surface, let the client use that, but don't create new surface at this point. 2997 winAnimator.mSurfaceController.getSurface(outSurface); 2998 } else { 2999 if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win); 3000 3001 try { 3002 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmReleaseOutSurface_" 3003 + win.mAttrs.getTitle()); 3004 outSurface.release(); 3005 } finally { 3006 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 3007 } 3008 } 3009 } 3010 3011 if (focusMayChange) { 3012 //System.out.println("Focus may change: " + win.mAttrs.getTitle()); 3013 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 3014 false /*updateInputWindows*/)) { 3015 imMayMove = false; 3016 } 3017 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus); 3018 } 3019 3020 // updateFocusedWindowLocked() already assigned layers so we only need to 3021 // reassign them at this point if the IM window state gets shuffled 3022 boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0; 3023 if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) { 3024 // Little hack here -- we -should- be able to rely on the 3025 // function to return true if the IME has moved and needs 3026 // its layer recomputed. However, if the IME was hidden 3027 // and isn't actually moved in the list, its layer may be 3028 // out of data so we make sure to recompute it. 3029 mLayersController.assignLayersLocked(win.getWindowList()); 3030 } 3031 3032 if (wallpaperMayMove) { 3033 getDefaultDisplayContentLocked().pendingLayoutChanges |= 3034 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 3035 } 3036 3037 win.setDisplayLayoutNeeded(); 3038 win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0; 3039 configChanged = updateOrientationFromAppTokensLocked(false); 3040 mWindowPlacerLocked.performSurfacePlacement(); 3041 if (toBeDisplayed && win.mIsWallpaper) { 3042 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 3043 mWallpaperControllerLocked.updateWallpaperOffset( 3044 win, displayInfo.logicalWidth, displayInfo.logicalHeight, false); 3045 } 3046 if (win.mAppToken != null) { 3047 win.mAppToken.updateReportedVisibilityLocked(); 3048 } 3049 if (winAnimator.mReportSurfaceResized) { 3050 winAnimator.mReportSurfaceResized = false; 3051 result |= WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED; 3052 } 3053 if (mPolicy.isNavBarForcedShownLw(win)) { 3054 result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR; 3055 } 3056 if (!win.isGoneForLayoutLw()) { 3057 win.mResizedWhileGone = false; 3058 } 3059 outFrame.set(win.mCompatFrame); 3060 outOverscanInsets.set(win.mOverscanInsets); 3061 outContentInsets.set(win.mContentInsets); 3062 outVisibleInsets.set(win.mVisibleInsets); 3063 outStableInsets.set(win.mStableInsets); 3064 outOutsets.set(win.mOutsets); 3065 outBackdropFrame.set(win.getBackdropFrame(win.mFrame)); 3066 if (localLOGV) Slog.v( 3067 TAG_WM, "Relayout given client " + client.asBinder() 3068 + ", requestedWidth=" + requestedWidth 3069 + ", requestedHeight=" + requestedHeight 3070 + ", viewVisibility=" + viewVisibility 3071 + "\nRelayout returning frame=" + outFrame 3072 + ", surface=" + outSurface); 3073 3074 if (localLOGV || DEBUG_FOCUS) Slog.v( 3075 TAG_WM, "Relayout of " + win + ": focusMayChange=" + focusMayChange); 3076 3077 result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0; 3078 3079 mInputMonitor.updateInputWindowsLw(true /*force*/); 3080 3081 if (DEBUG_LAYOUT) { 3082 Slog.v(TAG_WM, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString()); 3083 } 3084 win.mInRelayout = false; 3085 } 3086 3087 if (configChanged) { 3088 sendNewConfiguration(); 3089 } 3090 Binder.restoreCallingIdentity(origId); 3091 return result; 3092 } 3093 3094 private boolean tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator, 3095 boolean isDefaultDisplay, boolean focusMayChange) { 3096 // Try starting an animation; if there isn't one, we 3097 // can destroy the surface right away. 3098 int transit = WindowManagerPolicy.TRANSIT_EXIT; 3099 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 3100 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 3101 } 3102 if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) { 3103 focusMayChange = isDefaultDisplay; 3104 win.mAnimatingExit = true; 3105 win.mWinAnimator.mAnimating = true; 3106 } else if (win.mWinAnimator.isAnimationSet()) { 3107 // Currently in a hide animation... turn this into 3108 // an exit. 3109 win.mAnimatingExit = true; 3110 win.mWinAnimator.mAnimating = true; 3111 } else if (mWallpaperControllerLocked.isWallpaperTarget(win)) { 3112 // If the wallpaper is currently behind this 3113 // window, we need to change both of them inside 3114 // of a transaction to avoid artifacts. 3115 win.mAnimatingExit = true; 3116 win.mWinAnimator.mAnimating = true; 3117 } else { 3118 if (mInputMethodWindow == win) { 3119 mInputMethodWindow = null; 3120 } 3121 win.destroyOrSaveSurface(); 3122 } 3123 //TODO (multidisplay): Magnification is supported only for the default 3124 if (mAccessibilityController != null 3125 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 3126 mAccessibilityController.onWindowTransitionLocked(win, transit); 3127 } 3128 return focusMayChange; 3129 } 3130 3131 private int createSurfaceControl(Surface outSurface, int result, WindowState win, 3132 WindowStateAnimator winAnimator) { 3133 if (!win.mHasSurface) { 3134 result |= RELAYOUT_RES_SURFACE_CHANGED; 3135 } 3136 WindowSurfaceController surfaceController = winAnimator.createSurfaceLocked(); 3137 if (surfaceController != null) { 3138 surfaceController.getSurface(outSurface); 3139 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " OUT SURFACE " + outSurface + ": copied"); 3140 } else { 3141 // For some reason there isn't a surface. Clear the 3142 // caller's object so they see the same state. 3143 Slog.w(TAG_WM, "Failed to create surface control for " + win); 3144 outSurface.release(); 3145 } 3146 return result; 3147 } 3148 3149 private int relayoutVisibleWindow(Configuration outConfig, int result, WindowState win, 3150 WindowStateAnimator winAnimator, int attrChanges, int oldVisibility) { 3151 result |= !win.isVisibleLw() ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0; 3152 if (win.mAnimatingExit) { 3153 Slog.d(TAG, "relayoutVisibleWindow: " + win + " mAnimatingExit=true, mRemoveOnExit=" 3154 + win.mRemoveOnExit + ", mDestroying=" + win.mDestroying); 3155 3156 winAnimator.cancelExitAnimationForNextAnimationLocked(); 3157 win.mAnimatingExit = false; 3158 } 3159 if (win.mDestroying) { 3160 win.mDestroying = false; 3161 mDestroySurface.remove(win); 3162 } 3163 if (oldVisibility == View.GONE) { 3164 winAnimator.mEnterAnimationPending = true; 3165 } 3166 3167 win.mLastVisibleLayoutRotation = mRotation; 3168 3169 winAnimator.mEnteringAnimation = true; 3170 if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { 3171 win.prepareWindowToDisplayDuringRelayout(outConfig); 3172 } 3173 if ((attrChanges & LayoutParams.FORMAT_CHANGED) != 0) { 3174 // If the format can't be changed in place, preserve the old surface until the app draws 3175 // on the new one. This prevents blinking when we change elevation of freeform and 3176 // pinned windows. 3177 if (!winAnimator.tryChangeFormatInPlaceLocked()) { 3178 winAnimator.preserveSurfaceLocked(); 3179 result |= RELAYOUT_RES_SURFACE_CHANGED 3180 | WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME; 3181 } 3182 } 3183 3184 // If we're starting a drag-resize, we'll be changing the surface size as well as 3185 // notifying the client to render to with an offset from the surface's top-left. 3186 if (win.isDragResizeChanged() || win.isResizedWhileNotDragResizing()) { 3187 win.setDragResizing(); 3188 win.setResizedWhileNotDragResizing(false); 3189 // We can only change top level windows to the full-screen surface when 3190 // resizing (as we only have one full-screen surface). So there is no need 3191 // to preserve and destroy windows which are attached to another, they 3192 // will keep their surface and its size may change over time. 3193 if (win.mHasSurface && win.mAttachedWindow == null) { 3194 winAnimator.preserveSurfaceLocked(); 3195 result |= WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME; 3196 } 3197 } 3198 final boolean freeformResizing = win.isDragResizing() 3199 && win.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM; 3200 final boolean dockedResizing = win.isDragResizing() 3201 && win.getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER; 3202 result |= freeformResizing ? WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM : 0; 3203 result |= dockedResizing ? WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED : 0; 3204 if (win.isAnimatingWithSavedSurface()) { 3205 // If we're animating with a saved surface now, request client to report draw. 3206 // We still need to know when the real thing is drawn. 3207 result |= WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME; 3208 } 3209 return result; 3210 } 3211 3212 public void performDeferredDestroyWindow(Session session, IWindow client) { 3213 long origId = Binder.clearCallingIdentity(); 3214 3215 try { 3216 synchronized (mWindowMap) { 3217 WindowState win = windowForClientLocked(session, client, false); 3218 if (win == null || win.mWillReplaceWindow) { 3219 return; 3220 } 3221 3222 win.mWinAnimator.destroyDeferredSurfaceLocked(); 3223 } 3224 } finally { 3225 Binder.restoreCallingIdentity(origId); 3226 } 3227 } 3228 3229 public boolean outOfMemoryWindow(Session session, IWindow client) { 3230 long origId = Binder.clearCallingIdentity(); 3231 3232 try { 3233 synchronized (mWindowMap) { 3234 WindowState win = windowForClientLocked(session, client, false); 3235 if (win == null) { 3236 return false; 3237 } 3238 return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false); 3239 } 3240 } finally { 3241 Binder.restoreCallingIdentity(origId); 3242 } 3243 } 3244 3245 public void finishDrawingWindow(Session session, IWindow client) { 3246 final long origId = Binder.clearCallingIdentity(); 3247 try { 3248 synchronized (mWindowMap) { 3249 WindowState win = windowForClientLocked(session, client, false); 3250 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "finishDrawingWindow: " + win + " mDrawState=" 3251 + (win != null ? win.mWinAnimator.drawStateToString() : "null")); 3252 if (win != null && win.mWinAnimator.finishDrawingLocked()) { 3253 if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 3254 getDefaultDisplayContentLocked().pendingLayoutChanges |= 3255 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 3256 } 3257 win.setDisplayLayoutNeeded(); 3258 mWindowPlacerLocked.requestTraversal(); 3259 } 3260 } 3261 } finally { 3262 Binder.restoreCallingIdentity(origId); 3263 } 3264 } 3265 3266 private boolean applyAnimationLocked(AppWindowToken atoken, WindowManager.LayoutParams lp, 3267 int transit, boolean enter, boolean isVoiceInteraction) { 3268 // Only apply an animation if the display isn't frozen. If it is 3269 // frozen, there is no reason to animate and it can cause strange 3270 // artifacts when we unfreeze the display if some different animation 3271 // is running. 3272 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked"); 3273 if (okToDisplay()) { 3274 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 3275 final int width = displayInfo.appWidth; 3276 final int height = displayInfo.appHeight; 3277 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM, 3278 "applyAnimation: atoken=" + atoken); 3279 3280 // Determine the visible rect to calculate the thumbnail clip 3281 final WindowState win = atoken.findMainWindow(); 3282 final Rect frame = new Rect(0, 0, width, height); 3283 final Rect displayFrame = new Rect(0, 0, 3284 displayInfo.logicalWidth, displayInfo.logicalHeight); 3285 final Rect insets = new Rect(); 3286 Rect surfaceInsets = null; 3287 final boolean freeform = win != null && win.inFreeformWorkspace(); 3288 if (win != null) { 3289 // Containing frame will usually cover the whole screen, including dialog windows. 3290 // For freeform workspace windows it will not cover the whole screen and it also 3291 // won't exactly match the final freeform window frame (e.g. when overlapping with 3292 // the status bar). In that case we need to use the final frame. 3293 if (freeform) { 3294 frame.set(win.mFrame); 3295 } else { 3296 frame.set(win.mContainingFrame); 3297 } 3298 surfaceInsets = win.getAttrs().surfaceInsets; 3299 insets.set(win.mContentInsets); 3300 } 3301 3302 if (atoken.mLaunchTaskBehind) { 3303 // Differentiate the two animations. This one which is briefly on the screen 3304 // gets the !enter animation, and the other activity which remains on the 3305 // screen gets the enter animation. Both appear in the mOpeningApps set. 3306 enter = false; 3307 } 3308 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition." 3309 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter 3310 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets); 3311 Animation a = mAppTransition.loadAnimation(lp, transit, enter, mCurConfiguration.uiMode, 3312 mCurConfiguration.orientation, frame, displayFrame, insets, surfaceInsets, 3313 isVoiceInteraction, freeform, atoken.mTask.mTaskId); 3314 if (a != null) { 3315 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken); 3316 final int containingWidth = frame.width(); 3317 final int containingHeight = frame.height(); 3318 atoken.mAppAnimator.setAnimation(a, containingWidth, containingHeight, 3319 mAppTransition.canSkipFirstFrame(), mAppTransition.getAppStackClipMode()); 3320 } 3321 } else { 3322 atoken.mAppAnimator.clearAnimation(); 3323 } 3324 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 3325 3326 return atoken.mAppAnimator.animation != null; 3327 } 3328 3329 // ------------------------------------------------------------- 3330 // Application Window Tokens 3331 // ------------------------------------------------------------- 3332 3333 public void validateAppTokens(int stackId, List<TaskGroup> tasks) { 3334 synchronized (mWindowMap) { 3335 int t = tasks.size() - 1; 3336 if (t < 0) { 3337 Slog.w(TAG_WM, "validateAppTokens: empty task list"); 3338 return; 3339 } 3340 3341 TaskGroup task = tasks.get(0); 3342 int taskId = task.taskId; 3343 Task targetTask = mTaskIdToTask.get(taskId); 3344 DisplayContent displayContent = targetTask.getDisplayContent(); 3345 if (displayContent == null) { 3346 Slog.w(TAG_WM, "validateAppTokens: no Display for taskId=" + taskId); 3347 return; 3348 } 3349 3350 final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks(); 3351 int taskNdx; 3352 for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) { 3353 AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens; 3354 task = tasks.get(t); 3355 List<IApplicationToken> tokens = task.tokens; 3356 3357 DisplayContent lastDisplayContent = displayContent; 3358 displayContent = mTaskIdToTask.get(taskId).getDisplayContent(); 3359 if (displayContent != lastDisplayContent) { 3360 Slog.w(TAG_WM, "validateAppTokens: displayContent changed in TaskGroup list!"