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