2 * Copyright (C) 2007 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.server.wm;
19 import static android.Manifest.permission.MANAGE_APP_TOKENS;
20 import static android.Manifest.permission.READ_FRAME_BUFFER;
21 import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
22 import static android.Manifest.permission.RESTRICTED_VR_ACCESS;
23 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
24 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
25 import static android.app.StatusBarManager.DISABLE_MASK;
26 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
27 import static android.content.Intent.ACTION_USER_REMOVED;
28 import static android.content.Intent.EXTRA_USER_HANDLE;
29 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
30 import static android.os.Process.ROOT_UID;
31 import static android.os.Process.SHELL_UID;
32 import static android.os.Process.SYSTEM_UID;
33 import static android.os.Process.myPid;
34 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
35 import static android.os.UserHandle.USER_NULL;
36 import static android.view.Display.DEFAULT_DISPLAY;
37 import static android.view.Display.INVALID_DISPLAY;
38 import static android.view.WindowManager.DOCKED_INVALID;
39 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
40 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
41 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
42 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
43 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
44 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
45 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
46 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
47 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
48 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
49 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
50 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
51 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
52 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
53 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
54 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
55 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
56 import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
57 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
58 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
59 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
60 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
61 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
62 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
63 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
64 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
65 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
66 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
67 import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
68 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
69 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
70 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
71 import static com.android.server.LockGuard.INDEX_WINDOW;
72 import static com.android.server.LockGuard.installLock;
73 import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
74 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END;
75 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
76 import static com.android.server.wm.KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED;
77 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
78 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
79 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
80 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
81 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
82 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
83 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
84 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
85 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
86 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
87 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
88 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
89 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
90 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
91 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
92 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
93 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
94 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
95 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
96 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
97 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
98 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
99 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
100 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
101 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
102 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSACTIONS;
103 import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
104 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
105 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
107 import android.Manifest;
108 import android.Manifest.permission;
109 import android.animation.AnimationHandler;
110 import android.animation.ValueAnimator;
111 import android.annotation.IntDef;
112 import android.annotation.NonNull;
113 import android.annotation.Nullable;
114 import android.app.ActivityManager;
115 import android.app.ActivityManager.TaskSnapshot;
116 import android.app.ActivityManagerInternal;
117 import android.app.ActivityThread;
118 import android.app.AppOpsManager;
119 import android.app.IActivityManager;
120 import android.content.BroadcastReceiver;
121 import android.content.ContentResolver;
122 import android.content.Context;
123 import android.content.Intent;
124 import android.content.IntentFilter;
125 import android.content.pm.ApplicationInfo;
126 import android.content.pm.PackageManager;
127 import android.content.res.Configuration;
128 import android.database.ContentObserver;
129 import android.graphics.Bitmap;
130 import android.graphics.GraphicBuffer;
131 import android.graphics.Matrix;
132 import android.graphics.PixelFormat;
133 import android.graphics.Point;
134 import android.graphics.Rect;
135 import android.graphics.RectF;
136 import android.graphics.Region;
137 import android.hardware.configstore.V1_0.ISurfaceFlingerConfigs;
138 import android.hardware.configstore.V1_0.OptionalBool;
139 import android.hardware.display.DisplayManager;
140 import android.hardware.display.DisplayManagerInternal;
141 import android.hardware.input.InputManager;
142 import android.net.Uri;
143 import android.os.Binder;
144 import android.os.Build;
145 import android.os.Bundle;
146 import android.os.Debug;
147 import android.os.Handler;
148 import android.os.IBinder;
149 import android.os.IRemoteCallback;
150 import android.os.Looper;
151 import android.os.Message;
152 import android.os.Parcel;
153 import android.os.ParcelFileDescriptor;
154 import android.os.PowerManager;
155 import android.os.PowerManagerInternal;
156 import android.os.PowerSaveState;
157 import android.os.RemoteException;
158 import android.os.ServiceManager;
159 import android.os.StrictMode;
160 import android.os.SystemClock;
161 import android.os.SystemProperties;
162 import android.os.SystemService;
163 import android.os.Trace;
164 import android.os.UserHandle;
165 import android.os.WorkSource;
166 import android.provider.Settings;
167 import android.text.format.DateUtils;
168 import android.util.ArraySet;
169 import android.util.DisplayMetrics;
170 import android.util.EventLog;
171 import android.util.Log;
172 import android.util.MergedConfiguration;
173 import android.util.Pair;
174 import android.util.Slog;
175 import android.util.SparseArray;
176 import android.util.SparseIntArray;
177 import android.util.TimeUtils;
178 import android.util.TypedValue;
179 import android.view.AppTransitionAnimationSpec;
180 import android.view.Display;
181 import android.view.DisplayInfo;
182 import android.view.Gravity;
183 import android.view.IAppTransitionAnimationSpecsFuture;
184 import android.view.IDockedStackListener;
185 import android.view.IInputFilter;
186 import android.view.IOnKeyguardExitResult;
187 import android.view.IPinnedStackListener;
188 import android.view.IRotationWatcher;
189 import android.view.IWallpaperVisibilityListener;
190 import android.view.IWindow;
191 import android.view.IWindowId;
192 import android.view.IWindowManager;
193 import android.view.IWindowSession;
194 import android.view.IWindowSessionCallback;
195 import android.view.InputChannel;
196 import android.view.InputDevice;
197 import android.view.InputEvent;
198 import android.view.InputEventReceiver;
199 import android.view.KeyEvent;
200 import android.view.MagnificationSpec;
201 import android.view.MotionEvent;
202 import android.view.PointerIcon;
203 import android.view.Surface;
204 import android.view.Surface.OutOfResourcesException;
205 import android.view.SurfaceControl;
206 import android.view.SurfaceSession;
207 import android.view.View;
208 import android.view.WindowContentFrameStats;
209 import android.view.WindowManager;
210 import android.view.WindowManager.LayoutParams;
211 import android.view.WindowManagerGlobal;
212 import android.view.WindowManagerInternal;
213 import android.view.WindowManagerPolicy;
214 import android.view.WindowManagerPolicy.PointerEventListener;
215 import android.view.WindowManagerPolicy.ScreenOffListener;
216 import android.view.animation.Animation;
217 import android.view.inputmethod.InputMethodManagerInternal;
219 import com.android.internal.R;
220 import com.android.internal.app.IAssistScreenshotReceiver;
221 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
222 import com.android.internal.os.IResultReceiver;
223 import com.android.internal.policy.IKeyguardDismissCallback;
224 import com.android.internal.policy.IShortcutService;
225 import com.android.internal.util.DumpUtils;
226 import com.android.internal.util.FastPrintWriter;
227 import com.android.internal.view.IInputContext;
228 import com.android.internal.view.IInputMethodClient;
229 import com.android.internal.view.IInputMethodManager;
230 import com.android.internal.view.WindowManagerPolicyThread;
231 import com.android.server.AnimationThread;
232 import com.android.server.DisplayThread;
233 import com.android.server.EventLogTags;
234 import com.android.server.FgThread;
235 import com.android.server.LocalServices;
236 import com.android.server.UiThread;
237 import com.android.server.Watchdog;
238 import com.android.server.input.InputManagerService;
239 import com.android.server.power.BatterySaverPolicy.ServiceType;
240 import com.android.server.power.ShutdownThread;
242 import java.io.BufferedWriter;
243 import java.io.DataInputStream;
245 import java.io.FileDescriptor;
246 import java.io.FileInputStream;
247 import java.io.FileNotFoundException;
248 import java.io.IOException;
249 import java.io.OutputStream;
250 import java.io.OutputStreamWriter;
251 import java.io.PrintWriter;
252 import java.io.StringWriter;
253 import java.lang.annotation.Retention;
254 import java.lang.annotation.RetentionPolicy;
255 import java.net.Socket;
256 import java.text.DateFormat;
257 import java.util.ArrayList;
258 import java.util.Date;
259 import java.util.List;
261 public class WindowManagerService extends IWindowManager.Stub
262 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
263 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowManagerService" : TAG_WM;
265 static final int LAYOUT_REPEAT_THRESHOLD = 4;
267 static final boolean PROFILE_ORIENTATION = false;
268 static final boolean localLOGV = DEBUG;
270 /** How much to multiply the policy's type layer, to reserve room
271 * for multiple windows of the same type and Z-ordering adjustment
272 * with TYPE_LAYER_OFFSET. */
273 static final int TYPE_LAYER_MULTIPLIER = 10000;
275 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
276 * or below others in the same layer. */
277 static final int TYPE_LAYER_OFFSET = 1000;
279 /** How much to increment the layer for each window, to reserve room
280 * for effect surfaces between them.
282 static final int WINDOW_LAYER_MULTIPLIER = 5;
285 * Dim surface layer is immediately below target window.
287 static final int LAYER_OFFSET_DIM = 1;
290 * Animation thumbnail is as far as possible below the window above
291 * the thumbnail (or in other words as far as possible above the window
294 static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER - 1;
296 /** The maximum length we will accept for a loaded animation duration:
297 * this is 10 seconds.
299 static final int MAX_ANIMATION_DURATION = 10 * 1000;
301 /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
302 static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
304 /** Amount of time (in milliseconds) to delay before declaring a seamless rotation timeout. */
305 static final int SEAMLESS_ROTATION_TIMEOUT_DURATION = 2000;
307 /** Amount of time (in milliseconds) to delay before declaring a window replacement timeout. */
308 static final int WINDOW_REPLACEMENT_TIMEOUT_DURATION = 2000;
310 /** Amount of time to allow a last ANR message to exist before freeing the memory. */
311 static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours
313 * If true, the window manager will do its own custom freezing and general
314 * management of the screen during rotation.
316 static final boolean CUSTOM_SCREEN_ROTATION = true;
318 // Maximum number of milliseconds to wait for input devices to be enumerated before
319 // proceding with safe mode detection.
320 private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
322 // Default input dispatching timeout in nanoseconds.
323 static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
325 // Poll interval in milliseconds for watching boot animation finished.
326 private static final int BOOT_ANIMATION_POLL_INTERVAL = 200;
328 // The name of the boot animation service in init.rc.
329 private static final String BOOT_ANIMATION_SERVICE = "bootanim";
331 static final int UPDATE_FOCUS_NORMAL = 0;
332 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
333 static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
334 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
336 private static final String SYSTEM_SECURE = "ro.secure";
337 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
339 private static final String DENSITY_OVERRIDE = "ro.config.density_override";
340 private static final String SIZE_OVERRIDE = "ro.config.size_override";
342 private static final int MAX_SCREENSHOT_RETRIES = 3;
344 private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
346 // Used to indicate that if there is already a transition set, it should be preserved when
347 // trying to apply a new one.
348 private static final boolean ALWAYS_KEEP_CURRENT = true;
350 private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f;
352 // Enums for animation scale update types.
353 @Retention(RetentionPolicy.SOURCE)
354 @IntDef({WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE, ANIMATION_DURATION_SCALE})
355 private @interface UpdateAnimationScaleMode {};
356 private static final int WINDOW_ANIMATION_SCALE = 0;
357 private static final int TRANSITION_ANIMATION_SCALE = 1;
358 private static final int ANIMATION_DURATION_SCALE = 2;
360 final private KeyguardDisableHandler mKeyguardDisableHandler;
361 boolean mKeyguardGoingAway;
362 // VR Vr2d Display Id.
363 int mVr2dDisplayId = INVALID_DISPLAY;
365 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
367 public void onReceive(Context context, Intent intent) {
368 switch (intent.getAction()) {
369 case ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED:
370 mKeyguardDisableHandler.sendEmptyMessage(KEYGUARD_POLICY_CHANGED);
372 case ACTION_USER_REMOVED:
373 final int userId = intent.getIntExtra(EXTRA_USER_HANDLE, USER_NULL);
374 if (userId != USER_NULL) {
375 synchronized (mWindowMap) {
376 mScreenCaptureDisabled.remove(userId);
383 final WindowSurfacePlacer mWindowPlacerLocked;
386 * Current user when multi-user is enabled. Don't show windows of
387 * non-current user. Also see mCurrentProfileIds.
391 * Users that are profiles of the current user. These are also allowed to show windows
392 * on the current user.
394 int[] mCurrentProfileIds = new int[] {};
396 final Context mContext;
398 final boolean mHaveInputMethods;
400 final boolean mHasPermanentDpad;
401 final long mDrawLockTimeoutMillis;
402 final boolean mAllowAnimationsInLowPowerMode;
404 final boolean mAllowBootMessages;
406 final boolean mLimitedAlphaCompositing;
407 final int mMaxUiWidth;
409 final WindowManagerPolicy mPolicy;
411 final IActivityManager mActivityManager;
412 final ActivityManagerInternal mAmInternal;
414 final AppOpsManager mAppOps;
416 final DisplaySettings mDisplaySettings;
418 /** If the system should display notifications for apps displaying an alert window. */
419 boolean mShowAlertWindowNotifications = true;
422 * All currently active sessions with clients.
424 final ArraySet<Session> mSessions = new ArraySet<>();
427 * Mapping from an IWindow IBinder to the server's Window object.
428 * This is also used as the lock for all of our state.
429 * NOTE: Never call into methods that lock ActivityManagerService while holding this object.
431 final WindowHashMap mWindowMap = new WindowHashMap();
434 * List of window tokens that have finished starting their application,
435 * and now need to have the policy remove their windows.
437 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<>();
440 * List of window tokens that have finished drawing their own windows and
441 * no longer need to show any saved surfaces. Windows that's still showing
442 * saved surfaces will be cleaned up after next animation pass.
444 final ArrayList<AppWindowToken> mFinishedEarlyAnim = new ArrayList<>();
447 * List of app window tokens that are waiting for replacing windows. If the
448 * replacement doesn't come in time the stale windows needs to be disposed of.
450 final ArrayList<AppWindowToken> mWindowReplacementTimeouts = new ArrayList<>();
453 * Windows that are being resized. Used so we can tell the client about
454 * the resize after closing the transaction in which we resized the
455 * underlying surface.
457 final ArrayList<WindowState> mResizingWindows = new ArrayList<>();
460 * Windows whose animations have ended and now must be removed.
462 final ArrayList<WindowState> mPendingRemove = new ArrayList<>();
465 * Used when processing mPendingRemove to avoid working on the original array.
467 WindowState[] mPendingRemoveTmp = new WindowState[20];
470 * Windows whose surface should be destroyed.
472 final ArrayList<WindowState> mDestroySurface = new ArrayList<>();
475 * Windows with a preserved surface waiting to be destroyed. These windows
476 * are going through a surface change. We keep the old surface around until
477 * the first frame on the new surface finishes drawing.
479 final ArrayList<WindowState> mDestroyPreservedSurface = new ArrayList<>();
482 * Windows that have lost input focus and are waiting for the new
483 * focus window to be displayed before they are told about this.
485 ArrayList<WindowState> mLosingFocus = new ArrayList<>();
488 * This is set when we have run out of memory, and will either be an empty
489 * list or contain windows that need to be force removed.
491 final ArrayList<WindowState> mForceRemoves = new ArrayList<>();
494 * Windows that clients are waiting to have drawn.
496 ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>();
498 * And the callback to make when they've all been drawn.
500 Runnable mWaitingForDrawnCallback;
502 /** List of window currently causing non-system overlay windows to be hidden. */
503 private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>();
506 * Stores for each user whether screencapture is disabled
507 * This array is essentially a cache for all userId for
508 * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled}
510 private SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>();
512 IInputMethodManager mInputMethodManager;
514 AccessibilityController mAccessibilityController;
516 final SurfaceSession mFxSession;
517 Watermark mWatermark;
518 StrictModeFlash mStrictModeFlash;
519 CircularDisplayMask mCircularDisplayMask;
520 EmulatorDisplayOverlay mEmulatorDisplayOverlay;
522 final float[] mTmpFloats = new float[9];
523 final Rect mTmpRect = new Rect();
524 final Rect mTmpRect2 = new Rect();
525 final Rect mTmpRect3 = new Rect();
526 final RectF mTmpRectF = new RectF();
528 final Matrix mTmpTransform = new Matrix();
530 boolean mDisplayReady;
532 boolean mDisplayEnabled = false;
533 boolean mSystemBooted = false;
534 boolean mForceDisplayEnabled = false;
535 boolean mShowingBootMessages = false;
536 boolean mBootAnimationStopped = false;
538 // Following variables are for debugging screen wakelock only.
539 WindowState mLastWakeLockHoldingWindow = null;
540 WindowState mLastWakeLockObscuringWindow = null;
542 /** Dump of the windows and app tokens at the time of the last ANR. Cleared after
543 * LAST_ANR_LIFETIME_DURATION_MSECS */
544 String mLastANRState;
546 // The root of the device window hierarchy.
547 RootWindowContainer mRoot;
549 int mDockedStackCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
550 Rect mDockedStackCreateBounds;
552 private final SparseIntArray mTmpTaskIds = new SparseIntArray();
554 boolean mForceResizableTasks = false;
555 boolean mSupportsPictureInPicture = false;
557 int getDragLayerLocked() {
558 return mPolicy.getWindowLayerFromTypeLw(TYPE_DRAG) * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
561 class RotationWatcher {
562 final IRotationWatcher mWatcher;
563 final IBinder.DeathRecipient mDeathRecipient;
564 final int mDisplayId;
565 RotationWatcher(IRotationWatcher watcher, IBinder.DeathRecipient deathRecipient,
568 mDeathRecipient = deathRecipient;
569 mDisplayId = displayId;
573 ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<>();
574 int mDeferredRotationPauseCount;
575 final WallpaperVisibilityListeners mWallpaperVisibilityListeners =
576 new WallpaperVisibilityListeners();
578 int mSystemDecorLayer = 0;
579 final Rect mScreenRect = new Rect();
581 boolean mDisplayFrozen = false;
582 long mDisplayFreezeTime = 0;
583 int mLastDisplayFreezeDuration = 0;
584 Object mLastFinishedFreezeSource = null;
585 boolean mWaitingForConfig = false;
586 boolean mSwitchingUser = false;
588 final static int WINDOWS_FREEZING_SCREENS_NONE = 0;
589 final static int WINDOWS_FREEZING_SCREENS_ACTIVE = 1;
590 final static int WINDOWS_FREEZING_SCREENS_TIMEOUT = 2;
591 int mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
593 boolean mClientFreezingScreen = false;
594 int mAppsFreezingScreen = 0;
598 // Last systemUiVisibility we received from status bar.
599 int mLastStatusBarVisibility = 0;
600 // Last systemUiVisibility we dispatched to windows.
601 int mLastDispatchedSystemUiVisibility = 0;
603 // State while inside of layoutAndPlaceSurfacesLocked().
604 boolean mFocusMayChange;
606 // This is held as long as we have the screen frozen, to give us time to
607 // perform a rotation animation when turning off shows the lock screen which
608 // changes the orientation.
609 private final PowerManager.WakeLock mScreenFrozenLock;
611 final AppTransition mAppTransition;
612 boolean mSkipAppTransitionAnimation = false;
614 final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<>();
615 final ArraySet<AppWindowToken> mClosingApps = new ArraySet<>();
617 final UnknownAppVisibilityController mUnknownAppVisibilityController =
618 new UnknownAppVisibilityController(this);
619 final TaskSnapshotController mTaskSnapshotController;
621 boolean mIsTouchDevice;
623 final H mH = new H();
626 * Handler for things to run that have direct impact on an animation, i.e. animation tick,
627 * layout, starting window creation, whereas {@link H} runs things that are still important, but
630 final Handler mAnimationHandler = new Handler(AnimationThread.getHandler().getLooper());
632 WindowState mCurrentFocus = null;
633 WindowState mLastFocus = null;
635 /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
636 private final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>();
637 /** Windows removed since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
638 private final ArrayList<WindowState> mWinRemovedSinceNullFocus = new ArrayList<>();
640 /** This just indicates the window the input method is on top of, not
641 * necessarily the window its input is going to. */
642 WindowState mInputMethodTarget = null;
644 /** If true hold off on modifying the animation layer of mInputMethodTarget */
645 boolean mInputMethodTargetWaitingAnim;
647 WindowState mInputMethodWindow = null;
649 boolean mHardKeyboardAvailable;
650 WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
651 SettingsObserver mSettingsObserver;
653 // A count of the windows which are 'seamlessly rotated', e.g. a surface
654 // at an old orientation is being transformed. We freeze orientation updates
655 // while any windows are seamlessly rotated, so we need to track when this
656 // hits zero so we can apply deferred orientation updates.
657 int mSeamlessRotationCount = 0;
659 private final class SettingsObserver extends ContentObserver {
660 private final Uri mDisplayInversionEnabledUri =
661 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
662 private final Uri mWindowAnimationScaleUri =
663 Settings.Global.getUriFor(Settings.Global.WINDOW_ANIMATION_SCALE);
664 private final Uri mTransitionAnimationScaleUri =
665 Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE);
666 private final Uri mAnimationDurationScaleUri =
667 Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE);
669 public SettingsObserver() {
670 super(new Handler());
671 ContentResolver resolver = mContext.getContentResolver();
672 resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this,
673 UserHandle.USER_ALL);
674 resolver.registerContentObserver(mWindowAnimationScaleUri, false, this,
675 UserHandle.USER_ALL);
676 resolver.registerContentObserver(mTransitionAnimationScaleUri, false, this,
677 UserHandle.USER_ALL);
678 resolver.registerContentObserver(mAnimationDurationScaleUri, false, this,
679 UserHandle.USER_ALL);
683 public void onChange(boolean selfChange, Uri uri) {
688 if (mDisplayInversionEnabledUri.equals(uri)) {
689 updateCircularDisplayMaskIfNeeded();
691 @UpdateAnimationScaleMode
693 if (mWindowAnimationScaleUri.equals(uri)) {
694 mode = WINDOW_ANIMATION_SCALE;
695 } else if (mTransitionAnimationScaleUri.equals(uri)) {
696 mode = TRANSITION_ANIMATION_SCALE;
697 } else if (mAnimationDurationScaleUri.equals(uri)) {
698 mode = ANIMATION_DURATION_SCALE;
700 // Ignoring unrecognized content changes
703 Message m = mH.obtainMessage(H.UPDATE_ANIMATION_SCALE, mode, 0);
709 boolean mAnimateWallpaperWithTarget;
711 // TODO: Move to RootWindowContainer
712 AppWindowToken mFocusedApp = null;
714 PowerManager mPowerManager;
715 PowerManagerInternal mPowerManagerInternal;
717 private float mWindowAnimationScaleSetting = 1.0f;
718 private float mTransitionAnimationScaleSetting = 1.0f;
719 private float mAnimatorDurationScaleSetting = 1.0f;
720 private boolean mAnimationsDisabled = false;
722 final InputManagerService mInputManager;
723 final DisplayManagerInternal mDisplayManagerInternal;
724 final DisplayManager mDisplayManager;
725 private final Display[] mDisplays;
727 // Indicates whether this device supports wide color gamut rendering
728 private boolean mHasWideColorGamutSupport;
730 // Who is holding the screen on.
731 private Session mHoldingScreenOn;
732 private PowerManager.WakeLock mHoldingScreenWakeLock;
734 boolean mTurnOnScreen;
736 // Whether or not a layout can cause a wake up when theater mode is enabled.
737 boolean mAllowTheaterModeWakeFromLayout;
739 TaskPositioner mTaskPositioner;
740 DragState mDragState = null;
742 // For frozen screen animations.
743 private int mExitAnimId, mEnterAnimId;
745 // The display that the rotation animation is applying to.
746 private int mFrozenDisplayId;
748 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
749 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
750 int mTransactionSequence;
752 final WindowAnimator mAnimator;
754 final BoundsAnimationController mBoundsAnimationController;
756 private final PointerEventDispatcher mPointerEventDispatcher;
758 private WindowContentFrameStats mTempWindowRenderStats;
760 final class DragInputEventReceiver extends InputEventReceiver {
761 // Set, if stylus button was down at the start of the drag.
762 private boolean mStylusButtonDownAtStart;
763 // Indicates the first event to check for button state.
764 private boolean mIsStartEvent = true;
765 // Set to true to ignore input events after the drag gesture is complete but the drag events
766 // are still being dispatched.
767 private boolean mMuteInput = false;
769 public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
770 super(inputChannel, looper);
774 public void onInputEvent(InputEvent event, int displayId) {
775 boolean handled = false;
777 if (mDragState == null) {
778 // The drag has ended but the clean-up message has not been processed by
779 // window manager. Drop events that occur after this until window manager
780 // has a chance to clean-up the input handle.
784 if (event instanceof MotionEvent
785 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0
787 final MotionEvent motionEvent = (MotionEvent)event;
788 boolean endDrag = false;
789 final float newX = motionEvent.getRawX();
790 final float newY = motionEvent.getRawY();
791 final boolean isStylusButtonDown =
792 (motionEvent.getButtonState() & MotionEvent.BUTTON_STYLUS_PRIMARY) != 0;
795 if (isStylusButtonDown) {
796 // First event and the button was down, check for the button being
797 // lifted in the future, if that happens we'll drop the item.
798 mStylusButtonDownAtStart = true;
800 mIsStartEvent = false;
803 switch (motionEvent.getAction()) {
804 case MotionEvent.ACTION_DOWN: {
806 Slog.w(TAG_WM, "Unexpected ACTION_DOWN in drag layer");
810 case MotionEvent.ACTION_MOVE: {
811 if (mStylusButtonDownAtStart && !isStylusButtonDown) {
812 if (DEBUG_DRAG) Slog.d(TAG_WM, "Button no longer pressed; dropping at "
813 + newX + "," + newY);
815 synchronized (mWindowMap) {
816 endDrag = mDragState.notifyDropLw(newX, newY);
819 synchronized (mWindowMap) {
820 // move the surface and tell the involved window(s) where we are
821 mDragState.notifyMoveLw(newX, newY);
826 case MotionEvent.ACTION_UP: {
827 if (DEBUG_DRAG) Slog.d(TAG_WM, "Got UP on move channel; dropping at "
828 + newX + "," + newY);
830 synchronized (mWindowMap) {
831 endDrag = mDragState.notifyDropLw(newX, newY);
835 case MotionEvent.ACTION_CANCEL: {
836 if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag cancelled!");
843 if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ended; tearing down state");
844 // tell all the windows that the drag has ended
845 synchronized (mWindowMap) {
846 // endDragLw will post back to looper to dispose the receiver
847 // since we still need the receiver for the last finishInputEvent.
848 mDragState.endDragLw();
850 mStylusButtonDownAtStart = false;
851 mIsStartEvent = true;
856 } catch (Exception e) {
857 Slog.e(TAG_WM, "Exception caught by drag handleMotion", e);
859 finishInputEvent(event, handled);
865 * Whether the UI is currently running in touch mode (not showing
866 * navigational focus because the user is directly pressing the screen).
868 boolean mInTouchMode;
870 private ViewServer mViewServer;
871 final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
872 boolean mWindowsChanged = false;
874 public interface WindowChangeListener {
875 public void windowsChanged();
876 public void focusChanged();
879 final Configuration mTempConfiguration = new Configuration();
881 // If true, only the core apps and services are being launched because the device
882 // is in a special boot mode, such as being encrypted or waiting for a decryption password.
883 // For example, when this flag is true, there will be no wallpaper service.
884 final boolean mOnlyCore;
886 // List of clients without a transtiton animation that we notify once we are done transitioning
887 // since they won't be notified through the app window animator.
888 final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
890 static WindowManagerThreadPriorityBooster sThreadPriorityBooster =
891 new WindowManagerThreadPriorityBooster();
893 static void boostPriorityForLockedSection() {
894 sThreadPriorityBooster.boost();
897 static void resetPriorityAfterLockedSection() {
898 sThreadPriorityBooster.reset();
901 void openSurfaceTransaction() {
903 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "openSurfaceTransaction");
904 synchronized (mWindowMap) {
905 if (mRoot.mSurfaceTraceEnabled) {
906 mRoot.mRemoteEventTrace.openSurfaceTransaction();
908 SurfaceControl.openTransaction();
911 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
916 * Closes a surface transaction.
918 void closeSurfaceTransaction() {
920 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction");
921 synchronized (mWindowMap) {
922 if (mRoot.mSurfaceTraceEnabled) {
923 mRoot.mRemoteEventTrace.closeSurfaceTransaction();
925 SurfaceControl.closeTransaction();
928 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
933 * Executes an empty animation transaction without holding the WM lock to simulate
934 * back-pressure. See {@link WindowAnimator#animate} why this is needed.
936 void executeEmptyAnimationTransaction() {
938 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "openSurfaceTransaction");
939 synchronized (mWindowMap) {
940 if (mRoot.mSurfaceTraceEnabled) {
941 mRoot.mRemoteEventTrace.openSurfaceTransaction();
943 SurfaceControl.openTransaction();
944 SurfaceControl.setAnimationTransaction();
945 if (mRoot.mSurfaceTraceEnabled) {
946 mRoot.mRemoteEventTrace.closeSurfaceTransaction();
950 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
953 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction");
954 SurfaceControl.closeTransaction();
956 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
960 /** Listener to notify activity manager about app transitions. */
961 final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier
962 = new WindowManagerInternal.AppTransitionListener() {
965 public void onAppTransitionCancelledLocked(int transit) {
966 mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_CANCELLED);
970 public void onAppTransitionFinishedLocked(IBinder token) {
971 mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_FINISHED);
972 final AppWindowToken atoken = mRoot.getAppWindowToken(token);
973 if (atoken == null) {
976 if (atoken.mLaunchTaskBehind) {
978 mActivityManager.notifyLaunchTaskBehindComplete(atoken.token);
979 } catch (RemoteException e) {
981 atoken.mLaunchTaskBehind = false;
983 atoken.updateReportedVisibilityLocked();
984 if (atoken.mEnteringAnimation) {
985 atoken.mEnteringAnimation = false;
987 mActivityManager.notifyEnterAnimationComplete(atoken.token);
988 } catch (RemoteException e) {
995 final ArrayList<AppFreezeListener> mAppFreezeListeners = new ArrayList<>();
997 interface AppFreezeListener {
998 void onAppFreezeTimeout();
1001 private static WindowManagerService sInstance;
1002 static WindowManagerService getInstance() {
1006 public static WindowManagerService main(final Context context, final InputManagerService im,
1007 final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
1008 WindowManagerPolicy policy) {
1009 DisplayThread.getHandler().runWithScissors(() ->
1010 sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
1011 onlyCore, policy), 0);
1015 private void initPolicy() {
1016 UiThread.getHandler().runWithScissors(new Runnable() {
1019 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
1021 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
1026 private WindowManagerService(Context context, InputManagerService inputManager,
1027 boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
1028 WindowManagerPolicy policy) {
1029 installLock(this, INDEX_WINDOW);
1030 mRoot = new RootWindowContainer(this);
1032 mHaveInputMethods = haveInputMethods;
1033 mAllowBootMessages = showBootMsgs;
1034 mOnlyCore = onlyCore;
1035 mLimitedAlphaCompositing = context.getResources().getBoolean(
1036 com.android.internal.R.bool.config_sf_limitedAlpha);
1037 mHasPermanentDpad = context.getResources().getBoolean(
1038 com.android.internal.R.bool.config_hasPermanentDpad);
1039 mInTouchMode = context.getResources().getBoolean(
1040 com.android.internal.R.bool.config_defaultInTouchMode);
1041 mDrawLockTimeoutMillis = context.getResources().getInteger(
1042 com.android.internal.R.integer.config_drawLockTimeoutMillis);
1043 mAllowAnimationsInLowPowerMode = context.getResources().getBoolean(
1044 com.android.internal.R.bool.config_allowAnimationsInLowPowerMode);
1045 mMaxUiWidth = context.getResources().getInteger(
1046 com.android.internal.R.integer.config_maxUiWidth);
1047 mInputManager = inputManager; // Must be before createDisplayContentLocked.
1048 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
1049 mDisplaySettings = new DisplaySettings();
1050 mDisplaySettings.readSettingsLocked();
1052 mWindowPlacerLocked = new WindowSurfacePlacer(this);
1054 mTaskSnapshotController = new TaskSnapshotController(this);
1056 LocalServices.addService(WindowManagerPolicy.class, mPolicy);
1058 if(mInputManager != null) {
1059 final InputChannel inputChannel = mInputManager.monitorInput(TAG_WM);
1060 mPointerEventDispatcher = inputChannel != null
1061 ? new PointerEventDispatcher(inputChannel) : null;
1063 mPointerEventDispatcher = null;
1066 mFxSession = new SurfaceSession();
1067 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
1068 mDisplays = mDisplayManager.getDisplays();
1069 for (Display display : mDisplays) {
1070 createDisplayContentLocked(display);
1073 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
1075 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1076 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
1078 if (mPowerManagerInternal != null) {
1079 mPowerManagerInternal.registerLowPowerModeObserver(
1080 new PowerManagerInternal.LowPowerModeListener() {
1082 public int getServiceType() {
1083 return ServiceType.ANIMATION;
1087 public void onLowPowerModeChanged(PowerSaveState result) {
1088 synchronized (mWindowMap) {
1089 final boolean enabled = result.batterySaverEnabled;
1090 if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
1091 mAnimationsDisabled = enabled;
1092 dispatchNewAnimatorScaleLocked(null);
1097 mAnimationsDisabled = mPowerManagerInternal
1098 .getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled;
1100 mScreenFrozenLock = mPowerManager.newWakeLock(
1101 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
1102 mScreenFrozenLock.setReferenceCounted(false);
1104 mAppTransition = new AppTransition(context, this);
1105 mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier);
1107 final AnimationHandler animationHandler = new AnimationHandler();
1108 animationHandler.setProvider(new SfVsyncFrameCallbackProvider());
1109 mBoundsAnimationController = new BoundsAnimationController(context, mAppTransition,
1110 AnimationThread.getHandler(), animationHandler);
1112 mActivityManager = ActivityManager.getService();
1113 mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
1114 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
1115 AppOpsManager.OnOpChangedInternalListener opListener =
1116 new AppOpsManager.OnOpChangedInternalListener() {
1117 @Override public void onOpChanged(int op, String packageName) {
1118 updateAppOpsState();
1121 mAppOps.startWatchingMode(OP_SYSTEM_ALERT_WINDOW, null, opListener);
1122 mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener);
1124 // Get persisted window scale setting
1125 mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
1126 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
1127 mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
1128 Settings.Global.TRANSITION_ANIMATION_SCALE,
1129 context.getResources().getFloat(
1130 R.dimen.config_appTransitionAnimationDurationScaleDefault));
1132 setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
1133 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
1135 IntentFilter filter = new IntentFilter();
1136 // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
1137 filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
1138 // Listen to user removal broadcasts so that we can remove the user-specific data.
1139 filter.addAction(Intent.ACTION_USER_REMOVED);
1140 mContext.registerReceiver(mBroadcastReceiver, filter);
1142 mSettingsObserver = new SettingsObserver();
1144 mHoldingScreenWakeLock = mPowerManager.newWakeLock(
1145 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
1146 mHoldingScreenWakeLock.setReferenceCounted(false);
1148 mAnimator = new WindowAnimator(this);
1150 mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
1151 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
1154 LocalServices.addService(WindowManagerInternal.class, new LocalService());
1157 // Add ourself to the Watchdog monitors.
1158 Watchdog.getInstance().addMonitor(this);
1160 openSurfaceTransaction();
1162 createWatermarkInTransaction();
1164 closeSurfaceTransaction();
1167 showEmulatorDisplayOverlayIfNeeded();
1170 public InputMonitor getInputMonitor() {
1171 return mInputMonitor;
1175 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1176 throws RemoteException {
1178 return super.onTransact(code, data, reply, flags);
1179 } catch (RuntimeException e) {
1180 // The window manager only throws security exceptions, so let's
1182 if (!(e instanceof SecurityException)) {
1183 Slog.wtf(TAG_WM, "Window Manager Crash", e);
1189 static boolean excludeWindowTypeFromTapOutTask(int windowType) {
1190 switch (windowType) {
1191 case TYPE_STATUS_BAR:
1192 case TYPE_NAVIGATION_BAR:
1193 case TYPE_INPUT_METHOD_DIALOG:
1199 public int addWindow(Session session, IWindow client, int seq,
1200 WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
1201 Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
1202 InputChannel outInputChannel) {
1203 int[] appOp = new int[1];
1204 int res = mPolicy.checkAddPermission(attrs, appOp);
1205 if (res != WindowManagerGlobal.ADD_OKAY) {
1209 boolean reportNewConfig = false;
1210 WindowState parentWindow = null;
1212 final int callingUid = Binder.getCallingUid();
1213 final int type = attrs.type;
1215 synchronized(mWindowMap) {
1216 if (!mDisplayReady) {
1217 throw new IllegalStateException("Display has not been initialialized");
1220 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
1221 if (displayContent == null) {
1222 Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "
1223 + displayId + ". Aborting.");
1224 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1226 if (!displayContent.hasAccess(session.mUid)
1227 && !mDisplayManagerInternal.isUidPresentOnDisplay(session.mUid, displayId)) {
1228 Slog.w(TAG_WM, "Attempted to add window to a display for which the application "
1229 + "does not have access: " + displayId + ". Aborting.");
1230 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1233 if (mWindowMap.containsKey(client.asBinder())) {
1234 Slog.w(TAG_WM, "Window " + client + " is already added");
1235 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
1238 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
1239 parentWindow = windowForClientLocked(null, attrs.token, false);
1240 if (parentWindow == null) {
1241 Slog.w(TAG_WM, "Attempted to add window with token that is not a window: "
1242 + attrs.token + ". Aborting.");
1243 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
1245 if (parentWindow.mAttrs.type >= FIRST_SUB_WINDOW
1246 && parentWindow.mAttrs.type <= LAST_SUB_WINDOW) {
1247 Slog.w(TAG_WM, "Attempted to add window with token that is a sub-window: "
1248 + attrs.token + ". Aborting.");
1249 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
1253 if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
1254 Slog.w(TAG_WM, "Attempted to add private presentation window to a non-private display. Aborting.");
1255 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
1258 AppWindowToken atoken = null;
1259 final boolean hasParent = parentWindow != null;
1260 // Use existing parent window token for child windows since they go in the same token
1261 // as there parent window so we can apply the same policy on them.
1262 WindowToken token = displayContent.getWindowToken(
1263 hasParent ? parentWindow.mAttrs.token : attrs.token);
1264 // If this is a child window, we want to apply the same type checking rules as the
1265 // parent window type.
1266 final int rootType = hasParent ? parentWindow.mAttrs.type : type;
1268 boolean addToastWindowRequiresToken = false;
1270 if (token == null) {
1271 if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
1272 Slog.w(TAG_WM, "Attempted to add application window with unknown token "
1273 + attrs.token + ". Aborting.");
1274 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1276 if (rootType == TYPE_INPUT_METHOD) {
1277 Slog.w(TAG_WM, "Attempted to add input method window with unknown token "
1278 + attrs.token + ". Aborting.");
1279 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1281 if (rootType == TYPE_VOICE_INTERACTION) {
1282 Slog.w(TAG_WM, "Attempted to add voice interaction window with unknown token "
1283 + attrs.token + ". Aborting.");
1284 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1286 if (rootType == TYPE_WALLPAPER) {
1287 Slog.w(TAG_WM, "Attempted to add wallpaper window with unknown token "
1288 + attrs.token + ". Aborting.");
1289 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1291 if (rootType == TYPE_DREAM) {
1292 Slog.w(TAG_WM, "Attempted to add Dream window with unknown token "
1293 + attrs.token + ". Aborting.");
1294 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1296 if (rootType == TYPE_QS_DIALOG) {
1297 Slog.w(TAG_WM, "Attempted to add QS dialog window with unknown token "
1298 + attrs.token + ". Aborting.");
1299 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1301 if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
1302 Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with unknown token "
1303 + attrs.token + ". Aborting.");
1304 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1306 if (type == TYPE_TOAST) {
1307 // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
1308 if (doesAddToastWindowRequireToken(attrs.packageName, callingUid,
1310 Slog.w(TAG_WM, "Attempted to add a toast window with unknown token "
1311 + attrs.token + ". Aborting.");
1312 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1315 final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();
1316 token = new WindowToken(this, binder, type, false, displayContent,
1317 session.mCanAddInternalSystemWindow);
1318 } else if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
1319 atoken = token.asAppWindowToken();
1320 if (atoken == null) {
1321 Slog.w(TAG_WM, "Attempted to add window with non-application token "
1322 + token + ". Aborting.");
1323 return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
1324 } else if (atoken.removed) {
1325 Slog.w(TAG_WM, "Attempted to add window with exiting application token "
1326 + token + ". Aborting.");
1327 return WindowManagerGlobal.ADD_APP_EXITING;
1329 } else if (rootType == TYPE_INPUT_METHOD) {
1330 if (token.windowType != TYPE_INPUT_METHOD) {
1331 Slog.w(TAG_WM, "Attempted to add input method window with bad token "
1332 + attrs.token + ". Aborting.");
1333 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1335 } else if (rootType == TYPE_VOICE_INTERACTION) {
1336 if (token.windowType != TYPE_VOICE_INTERACTION) {
1337 Slog.w(TAG_WM, "Attempted to add voice interaction window with bad token "
1338 + attrs.token + ". Aborting.");
1339 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1341 } else if (rootType == TYPE_WALLPAPER) {
1342 if (token.windowType != TYPE_WALLPAPER) {
1343 Slog.w(TAG_WM, "Attempted to add wallpaper window with bad token "
1344 + attrs.token + ". Aborting.");
1345 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1347 } else if (rootType == TYPE_DREAM) {
1348 if (token.windowType != TYPE_DREAM) {
1349 Slog.w(TAG_WM, "Attempted to add Dream window with bad token "
1350 + attrs.token + ". Aborting.");
1351 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1353 } else if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
1354 if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
1355 Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with bad token "
1356 + attrs.token + ". Aborting.");
1357 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1359 } else if (type == TYPE_TOAST) {
1360 // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
1361 addToastWindowRequiresToken = doesAddToastWindowRequireToken(attrs.packageName,
1362 callingUid, parentWindow);
1363 if (addToastWindowRequiresToken && token.windowType != TYPE_TOAST) {
1364 Slog.w(TAG_WM, "Attempted to add a toast window with bad token "
1365 + attrs.token + ". Aborting.");
1366 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1368 } else if (type == TYPE_QS_DIALOG) {
1369 if (token.windowType != TYPE_QS_DIALOG) {
1370 Slog.w(TAG_WM, "Attempted to add QS dialog window with bad token "
1371 + attrs.token + ". Aborting.");
1372 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1374 } else if (token.asAppWindowToken() != null) {
1375 Slog.w(TAG_WM, "Non-null appWindowToken for system window of rootType=" + rootType);
1376 // It is not valid to use an app token with other system types; we will
1377 // instead make a new token for it (as if null had been passed in for the token).
1379 token = new WindowToken(this, client.asBinder(), type, false, displayContent,
1380 session.mCanAddInternalSystemWindow);
1383 final WindowState win = new WindowState(this, session, client, token, parentWindow,
1384 appOp[0], seq, attrs, viewVisibility, session.mUid,
1385 session.mCanAddInternalSystemWindow);
1386 if (win.mDeathRecipient == null) {
1387 // Client has apparently died, so there is no reason to
1389 Slog.w(TAG_WM, "Adding window client " + client.asBinder()
1390 + " that is dead, aborting.");
1391 return WindowManagerGlobal.ADD_APP_EXITING;
1394 if (win.getDisplayContent() == null) {
1395 Slog.w(TAG_WM, "Adding window to Display that has been removed.");
1396 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1399 mPolicy.adjustWindowParamsLw(win.mAttrs);
1400 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
1402 res = mPolicy.prepareAddWindowLw(win, attrs);
1403 if (res != WindowManagerGlobal.ADD_OKAY) {
1407 final boolean openInputChannels = (outInputChannel != null
1408 && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
1409 if (openInputChannels) {
1410 win.openInputChannel(outInputChannel);
1413 // If adding a toast requires a token for this app we always schedule hiding
1414 // toast windows to make sure they don't stick around longer then necessary.
1415 // We hide instead of remove such windows as apps aren't prepared to handle
1416 // windows being removed under them.
1418 // If the app is older it can add toasts without a token and hence overlay
1419 // other apps. To be maximally compatible with these apps we will hide the
1420 // window after the toast timeout only if the focused window is from another
1421 // UID, otherwise we allow unlimited duration. When a UID looses focus we
1422 // schedule hiding all of its toast windows.
1423 if (type == TYPE_TOAST) {
1424 if (!getDefaultDisplayContentLocked().canAddToastWindowForUid(callingUid)) {
1425 Slog.w(TAG_WM, "Adding more than one toast window for UID at a time.");
1426 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
1428 // Make sure this happens before we moved focus as one can make the
1429 // toast focusable to force it not being hidden after the timeout.
1430 // Focusable toasts are always timed out to prevent a focused app to
1431 // show a focusable toasts while it has focus which will be kept on
1432 // the screen after the activity goes away.
1433 if (addToastWindowRequiresToken
1434 || (attrs.flags & LayoutParams.FLAG_NOT_FOCUSABLE) == 0
1435 || mCurrentFocus == null
1436 || mCurrentFocus.mOwnerUid != callingUid) {
1437 mH.sendMessageDelayed(
1438 mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, win),
1439 win.mAttrs.hideTimeoutMilliseconds);
1443 // From now on, no exceptions or errors allowed!
1445 res = WindowManagerGlobal.ADD_OKAY;
1446 if (mCurrentFocus == null) {
1447 mWinAddedSinceNullFocus.add(win);
1450 if (excludeWindowTypeFromTapOutTask(type)) {
1451 displayContent.mTapExcludedWindows.add(win);
1454 origId = Binder.clearCallingIdentity();
1457 mWindowMap.put(client.asBinder(), win);
1458 if (win.mAppOp != AppOpsManager.OP_NONE) {
1459 int startOpResult = mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(),
1460 win.getOwningPackage());
1461 if ((startOpResult != AppOpsManager.MODE_ALLOWED) &&
1462 (startOpResult != AppOpsManager.MODE_DEFAULT)) {
1463 win.setAppOpVisibilityLw(false);
1467 final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
1468 win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
1470 final AppWindowToken aToken = token.asAppWindowToken();
1471 if (type == TYPE_APPLICATION_STARTING && aToken != null) {
1472 aToken.startingWindow = win;
1473 if (DEBUG_STARTING_WINDOW) Slog.v (TAG_WM, "addWindow: " + aToken
1474 + " startingWindow=" + win);
1477 boolean imMayMove = true;
1479 win.mToken.addWindow(win);
1480 if (type == TYPE_INPUT_METHOD) {
1481 win.mGivenInsetsPending = true;
1482 setInputMethodWindowLocked(win);
1484 } else if (type == TYPE_INPUT_METHOD_DIALOG) {
1485 displayContent.computeImeTarget(true /* updateImeTarget */);
1488 if (type == TYPE_WALLPAPER) {
1489 displayContent.mWallpaperController.clearLastWallpaperTimeoutTime();
1490 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1491 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
1492 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1493 } else if (displayContent.mWallpaperController.isBelowWallpaperTarget(win)) {
1494 // If there is currently a wallpaper being shown, and
1495 // the base layer of the new window is below the current
1496 // layer of the target window, then adjust the wallpaper.
1497 // This is to avoid a new window being placed between the
1498 // wallpaper and its target.
1499 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1503 // If the window is being added to a stack that's currently adjusted for IME,
1504 // make sure to apply the same adjust to this new window.
1505 win.applyAdjustForImeIfNeeded();
1507 if (type == TYPE_DOCK_DIVIDER) {
1508 mRoot.getDisplayContent(displayId).getDockedDividerController().setWindow(win);
1511 final WindowStateAnimator winAnimator = win.mWinAnimator;
1512 winAnimator.mEnterAnimationPending = true;
1513 winAnimator.mEnteringAnimation = true;
1514 // Check if we need to prepare a transition for replacing window first.
1515 if (atoken != null && atoken.isVisible()
1516 && !prepareWindowReplacementTransition(atoken)) {
1517 // If not, check if need to set up a dummy transition during display freeze
1518 // so that the unfreeze wait for the apps to draw. This might be needed if
1519 // the app is relaunching.
1520 prepareNoneTransitionForRelaunching(atoken);
1523 if (displayContent.isDefaultDisplay) {
1524 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
1525 final Rect taskBounds;
1526 if (atoken != null && atoken.getTask() != null) {
1527 taskBounds = mTmpRect;
1528 atoken.getTask().getBounds(mTmpRect);
1532 if (mPolicy.getInsetHintLw(win.mAttrs, taskBounds, displayInfo.rotation,
1533 displayInfo.logicalWidth, displayInfo.logicalHeight, outContentInsets,
1534 outStableInsets, outOutsets)) {
1535 res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR;
1538 outContentInsets.setEmpty();
1539 outStableInsets.setEmpty();
1543 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
1545 if (win.mAppToken == null || !win.mAppToken.isClientHidden()) {
1546 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
1549 mInputMonitor.setUpdateInputWindowsNeededLw();
1551 boolean focusChanged = false;
1552 if (win.canReceiveKeys()) {
1553 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
1554 false /*updateInputWindows*/);
1561 displayContent.computeImeTarget(true /* updateImeTarget */);
1564 // Don't do layout here, the window must call
1565 // relayout to be displayed, so we'll do it there.
1566 displayContent.assignWindowLayers(false /* setLayoutNeeded */);
1569 mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
1571 mInputMonitor.updateInputWindowsLw(false /*force*/);
1573 if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client "
1574 + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5));
1576 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false, displayId)) {
1577 reportNewConfig = true;
1581 if (reportNewConfig) {
1582 sendNewConfiguration(displayId);
1585 Binder.restoreCallingIdentity(origId);
1590 private boolean doesAddToastWindowRequireToken(String packageName, int callingUid,
1591 WindowState attachedWindow) {
1592 // Try using the target SDK of the root window
1593 if (attachedWindow != null) {
1594 return attachedWindow.mAppToken != null
1595 && attachedWindow.mAppToken.mTargetSdk >= Build.VERSION_CODES.O;
1597 // Otherwise, look at the package
1599 ApplicationInfo appInfo = mContext.getPackageManager()
1600 .getApplicationInfoAsUser(packageName, 0,
1601 UserHandle.getUserId(callingUid));
1602 if (appInfo.uid != callingUid) {
1603 throw new SecurityException("Package " + packageName + " not in UID "
1606 if (appInfo.targetSdkVersion >= Build.VERSION_CODES.O) {
1609 } catch (PackageManager.NameNotFoundException e) {
1617 * Returns true if we're done setting up any transitions.
1619 private boolean prepareWindowReplacementTransition(AppWindowToken atoken) {
1620 atoken.clearAllDrawn();
1621 final WindowState replacedWindow = atoken.getReplacingWindow();
1622 if (replacedWindow == null) {
1623 // We expect to already receive a request to remove the old window. If it did not
1624 // happen, let's just simply add a window.
1627 // We use the visible frame, because we want the animation to morph the window from what
1628 // was visible to the user to the final destination of the new window.
1629 Rect frame = replacedWindow.mVisibleFrame;
1630 // We treat this as if this activity was opening, so we can trigger the app transition
1631 // animation and piggy-back on existing transition animation infrastructure.
1632 mOpeningApps.add(atoken);
1633 prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_RELAUNCH, ALWAYS_KEEP_CURRENT);
1634 mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top,
1635 frame.width(), frame.height());
1636 executeAppTransition();
1640 private void prepareNoneTransitionForRelaunching(AppWindowToken atoken) {
1641 // Set up a none-transition and add the app to opening apps, so that the display
1642 // unfreeze wait for the apps to be drawn.
1643 // Note that if the display unfroze already because app unfreeze timed out,
1644 // we don't set up the transition anymore and just let it go.
1645 if (mDisplayFrozen && !mOpeningApps.contains(atoken) && atoken.isRelaunching()) {
1646 mOpeningApps.add(atoken);
1647 prepareAppTransition(AppTransition.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT);
1648 executeAppTransition();
1653 * Returns whether screen capture is disabled for all windows of a specific user.
1655 boolean isScreenCaptureDisabledLocked(int userId) {
1656 Boolean disabled = mScreenCaptureDisabled.get(userId);
1657 if (disabled == null) {
1663 boolean isSecureLocked(WindowState w) {
1664 if ((w.mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
1667 if (isScreenCaptureDisabledLocked(UserHandle.getUserId(w.mOwnerUid))) {
1674 public void enableSurfaceTrace(ParcelFileDescriptor pfd) {
1675 final int callingUid = Binder.getCallingUid();
1676 if (callingUid != SHELL_UID && callingUid != ROOT_UID) {
1677 throw new SecurityException("Only shell can call enableSurfaceTrace");
1680 synchronized (mWindowMap) {
1681 mRoot.enableSurfaceTrace(pfd);
1686 public void disableSurfaceTrace() {
1687 final int callingUid = Binder.getCallingUid();
1688 if (callingUid != SHELL_UID && callingUid != ROOT_UID &&
1689 callingUid != SYSTEM_UID) {
1690 throw new SecurityException("Only shell can call disableSurfaceTrace");
1692 synchronized (mWindowMap) {
1693 mRoot.disableSurfaceTrace();
1698 * Set mScreenCaptureDisabled for specific user
1701 public void setScreenCaptureDisabled(int userId, boolean disabled) {
1702 int callingUid = Binder.getCallingUid();
1703 if (callingUid != SYSTEM_UID) {
1704 throw new SecurityException("Only system can call setScreenCaptureDisabled.");
1707 synchronized(mWindowMap) {
1708 mScreenCaptureDisabled.put(userId, disabled);
1709 // Update secure surface for all windows belonging to this user.
1710 mRoot.setSecureSurfaceState(userId, disabled);
1714 void removeWindow(Session session, IWindow client) {
1715 synchronized(mWindowMap) {
1716 WindowState win = windowForClientLocked(session, client, false);
1720 win.removeIfPossible();
1725 * Performs some centralized bookkeeping clean-up on the window that is being removed.
1726 * NOTE: Should only be called from {@link WindowState#removeImmediately()}
1727 * TODO: Maybe better handled with a method {@link WindowContainer#removeChild} if we can
1728 * figure-out a good way to have all parents of a WindowState doing the same thing without
1729 * forgetting to add the wiring when a new parent of WindowState is added.
1731 void postWindowRemoveCleanupLocked(WindowState win) {
1732 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "postWindowRemoveCleanupLocked: " + win);
1733 mWindowMap.remove(win.mClient.asBinder());
1734 if (win.mAppOp != AppOpsManager.OP_NONE) {
1735 mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
1738 if (mCurrentFocus == null) {
1739 mWinRemovedSinceNullFocus.add(win);
1741 mPendingRemove.remove(win);
1742 mResizingWindows.remove(win);
1743 updateNonSystemOverlayWindowsVisibilityIfNeeded(win, false /* surfaceShown */);
1744 mWindowsChanged = true;
1745 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Final remove of window: " + win);
1747 if (mInputMethodWindow == win) {
1748 setInputMethodWindowLocked(null);
1751 final WindowToken token = win.mToken;
1752 final AppWindowToken atoken = win.mAppToken;
1753 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Removing " + win + " from " + token);
1754 // Window will already be removed from token before this post clean-up method is called.
1755 if (token.isEmpty()) {
1756 if (!token.mPersistOnEmpty) {
1757 token.removeImmediately();
1758 } else if (atoken != null) {
1759 // TODO: Should this be moved into AppWindowToken.removeWindow? Might go away after
1761 atoken.firstWindowDrawn = false;
1762 atoken.clearAllDrawn();
1763 final TaskStack stack = atoken.getStack();
1764 if (stack != null) {
1765 stack.mExitingAppTokens.remove(atoken);
1770 if (atoken != null) {
1771 atoken.postWindowRemoveStartingWindowCleanup(win);
1774 final DisplayContent dc = win.getDisplayContent();
1775 if (win.mAttrs.type == TYPE_WALLPAPER) {
1776 dc.mWallpaperController.clearLastWallpaperTimeoutTime();
1777 dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1778 } else if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
1779 dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1782 if (dc != null && !mWindowPlacerLocked.isInLayout()) {
1783 dc.assignWindowLayers(true /* setLayoutNeeded */);
1784 mWindowPlacerLocked.performSurfacePlacement();
1785 if (win.mAppToken != null) {
1786 win.mAppToken.updateReportedVisibilityLocked();
1790 mInputMonitor.updateInputWindowsLw(true /*force*/);
1793 void setInputMethodWindowLocked(WindowState win) {
1794 mInputMethodWindow = win;
1795 final DisplayContent dc = win != null
1796 ? win.getDisplayContent() : getDefaultDisplayContentLocked();
1797 dc.computeImeTarget(true /* updateImeTarget */);
1800 private void updateAppOpsState() {
1801 synchronized(mWindowMap) {
1802 mRoot.updateAppOpsState();
1806 static void logSurface(WindowState w, String msg, boolean withStackTrace) {
1807 String str = " SURFACE " + msg + ": " + w;
1808 if (withStackTrace) {
1809 logWithStack(TAG, str);
1811 Slog.i(TAG_WM, str);
1815 static void logSurface(SurfaceControl s, String title, String msg) {
1816 String str = " SURFACE " + s + ": " + msg + " / " + title;
1817 Slog.i(TAG_WM, str);
1820 static void logWithStack(String tag, String s) {
1821 RuntimeException e = null;
1822 if (SHOW_STACK_CRAWLS) {
1823 e = new RuntimeException();
1824 e.fillInStackTrace();
1829 void setTransparentRegionWindow(Session session, IWindow client, Region region) {
1830 long origId = Binder.clearCallingIdentity();
1832 synchronized (mWindowMap) {
1833 WindowState w = windowForClientLocked(session, client, false);
1834 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
1835 "transparentRegionHint=" + region, false);
1837 if ((w != null) && w.mHasSurface) {
1838 w.mWinAnimator.setTransparentRegionHintLocked(region);
1842 Binder.restoreCallingIdentity(origId);
1846 void setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets,
1847 Rect visibleInsets, Region touchableRegion) {
1848 long origId = Binder.clearCallingIdentity();
1850 synchronized (mWindowMap) {
1851 WindowState w = windowForClientLocked(session, client, false);
1852 if (DEBUG_LAYOUT) Slog.d(TAG, "setInsetsWindow " + w
1853 + ", contentInsets=" + w.mGivenContentInsets + " -> " + contentInsets
1854 + ", visibleInsets=" + w.mGivenVisibleInsets + " -> " + visibleInsets
1855 + ", touchableRegion=" + w.mGivenTouchableRegion + " -> " + touchableRegion
1856 + ", touchableInsets " + w.mTouchableInsets + " -> " + touchableInsets);
1858 w.mGivenInsetsPending = false;
1859 w.mGivenContentInsets.set(contentInsets);
1860 w.mGivenVisibleInsets.set(visibleInsets);
1861 w.mGivenTouchableRegion.set(touchableRegion);
1862 w.mTouchableInsets = touchableInsets;
1863 if (w.mGlobalScale != 1) {
1864 w.mGivenContentInsets.scale(w.mGlobalScale);
1865 w.mGivenVisibleInsets.scale(w.mGlobalScale);
1866 w.mGivenTouchableRegion.scale(w.mGlobalScale);
1868 w.setDisplayLayoutNeeded();
1869 mWindowPlacerLocked.performSurfacePlacement();
1873 Binder.restoreCallingIdentity(origId);
1877 public void getWindowDisplayFrame(Session session, IWindow client,
1878 Rect outDisplayFrame) {
1879 synchronized(mWindowMap) {
1880 WindowState win = windowForClientLocked(session, client, false);
1882 outDisplayFrame.setEmpty();
1885 outDisplayFrame.set(win.mDisplayFrame);
1889 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
1890 synchronized (mWindowMap) {
1891 if (mAccessibilityController != null) {
1892 WindowState window = mWindowMap.get(token);
1893 //TODO (multidisplay): Magnification is supported only for the default display.
1894 if (window != null && window.getDisplayId() == DEFAULT_DISPLAY) {
1895 mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle);
1901 public IWindowId getWindowId(IBinder token) {
1902 synchronized (mWindowMap) {
1903 WindowState window = mWindowMap.get(token);
1904 return window != null ? window.mWindowId : null;
1908 public void pokeDrawLock(Session session, IBinder token) {
1909 synchronized (mWindowMap) {
1910 WindowState window = windowForClientLocked(session, token, false);
1911 if (window != null) {
1912 window.pokeDrawLockLw(mDrawLockTimeoutMillis);
1917 public int relayoutWindow(Session session, IWindow client, int seq,
1918 WindowManager.LayoutParams attrs, int requestedWidth,
1919 int requestedHeight, int viewVisibility, int flags,
1920 Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
1921 Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
1922 MergedConfiguration mergedConfiguration, Surface outSurface) {
1924 boolean configChanged;
1925 boolean hasStatusBarPermission =
1926 mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
1927 == PackageManager.PERMISSION_GRANTED;
1929 long origId = Binder.clearCallingIdentity();
1930 final int displayId;
1931 synchronized(mWindowMap) {
1932 WindowState win = windowForClientLocked(session, client, false);
1936 displayId = win.getDisplayId();
1938 WindowStateAnimator winAnimator = win.mWinAnimator;
1939 if (viewVisibility != View.GONE) {
1940 win.setRequestedSize(requestedWidth, requestedHeight);
1943 int attrChanges = 0;
1944 int flagChanges = 0;
1945 if (attrs != null) {
1946 mPolicy.adjustWindowParamsLw(attrs);
1947 // if they don't have the permission, mask out the status bar bits
1948 if (seq == win.mSeq) {
1949 int systemUiVisibility = attrs.systemUiVisibility
1950 | attrs.subtreeSystemUiVisibility;
1951 if ((systemUiVisibility & DISABLE_MASK) != 0) {
1952 if (!hasStatusBarPermission) {
1953 systemUiVisibility &= ~DISABLE_MASK;
1956 win.mSystemUiVisibility = systemUiVisibility;
1958 if (win.mAttrs.type != attrs.type) {
1959 throw new IllegalArgumentException(
1960 "Window type can not be changed after the window is added.");
1963 // Odd choice but less odd than embedding in copyFrom()
1964 if ((attrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY)
1966 attrs.x = win.mAttrs.x;
1967 attrs.y = win.mAttrs.y;
1968 attrs.width = win.mAttrs.width;
1969 attrs.height = win.mAttrs.height;
1972 flagChanges = win.mAttrs.flags ^= attrs.flags;
1973 attrChanges = win.mAttrs.copyFrom(attrs);
1974 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
1975 | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
1976 win.mLayoutNeeded = true;
1978 if (win.mAppToken != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0
1979 || (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) {
1980 win.mAppToken.checkKeyguardFlagsChanged();
1982 if (((attrChanges & LayoutParams.ACCESSIBILITY_TITLE_CHANGED) != 0)
1983 && (mAccessibilityController != null)
1984 && (win.getDisplayId() == DEFAULT_DISPLAY)) {
1985 // No move or resize, but the controller checks for title changes as well
1986 mAccessibilityController.onSomeWindowResizedOrMovedLocked();
1989 if ((flagChanges & PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
1990 updateNonSystemOverlayWindowsVisibilityIfNeeded(
1991 win, win.mWinAnimator.getShown());
1995 if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility
1996 + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
1997 winAnimator.mSurfaceDestroyDeferred = (flags & RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
1998 win.mEnforceSizeCompat =
1999 (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
2000 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2001 winAnimator.mAlpha = attrs.alpha;
2003 win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
2005 if (win.mAttrs.surfaceInsets.left != 0
2006 || win.mAttrs.surfaceInsets.top != 0
2007 || win.mAttrs.surfaceInsets.right != 0
2008 || win.mAttrs.surfaceInsets.bottom != 0) {
2009 winAnimator.setOpaqueLocked(false);
2012 boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
2013 final boolean isDefaultDisplay = win.isDefaultDisplay();
2014 boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
2015 || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
2016 || (!win.mRelayoutCalled));
2018 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2019 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
2020 wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
2021 if ((flagChanges & FLAG_SECURE) != 0 && winAnimator.mSurfaceController != null) {
2022 winAnimator.mSurfaceController.setSecure(isSecureLocked(win));
2025 win.mRelayoutCalled = true;
2026 win.mInRelayout = true;
2028 final int oldVisibility = win.mViewVisibility;
2029 win.mViewVisibility = viewVisibility;
2030 if (DEBUG_SCREEN_ON) {
2031 RuntimeException stack = new RuntimeException();
2032 stack.fillInStackTrace();
2033 Slog.i(TAG_WM, "Relayout " + win + ": oldVis=" + oldVisibility
2034 + " newVis=" + viewVisibility, stack);
2037 // We should only relayout if the view is visible, it is a starting window, or the
2038 // associated appToken is not hidden.
2039 final boolean shouldRelayout = viewVisibility == View.VISIBLE &&
2040 (win.mAppToken == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
2041 || !win.mAppToken.isClientHidden());
2043 if (shouldRelayout) {
2044 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_1");
2046 // We are about to create a surface, but we didn't run a layout yet. So better run
2047 // a layout now that we already know the right size, as a resize call will make the
2048 // surface transaction blocking until next vsync and slow us down.
2049 // TODO: Ideally we'd create the surface after running layout a bit further down,
2050 // but moving this seems to be too risky at this point in the release.
2051 if (win.mLayoutSeq == -1) {
2052 win.setDisplayLayoutNeeded();
2053 mWindowPlacerLocked.performSurfacePlacement(true);
2055 result = win.relayoutVisibleWindow(result, attrChanges, oldVisibility);
2058 result = createSurfaceControl(outSurface, result, win, winAnimator);
2059 } catch (Exception e) {
2060 mInputMonitor.updateInputWindowsLw(true /*force*/);
2062 Slog.w(TAG_WM, "Exception thrown when creating surface for client "
2063 + client + " (" + win.mAttrs.getTitle() + ")",
2065 Binder.restoreCallingIdentity(origId);
2068 if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
2069 focusMayChange = isDefaultDisplay;
2071 if (win.mAttrs.type == TYPE_INPUT_METHOD && mInputMethodWindow == null) {
2072 setInputMethodWindowLocked(win);
2075 win.adjustStartingWindowFlags();
2076 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2078 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_2");
2080 winAnimator.mEnterAnimationPending = false;
2081 winAnimator.mEnteringAnimation = false;
2082 final boolean usingSavedSurfaceBeforeVisible =
2083 oldVisibility != View.VISIBLE && win.isAnimatingWithSavedSurface();
2084 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
2085 if (winAnimator.hasSurface() && !win.mAnimatingExit
2086 && usingSavedSurfaceBeforeVisible) {
2087 Slog.d(TAG, "Ignoring layout to invisible when using saved surface " + win);
2091 if (winAnimator.hasSurface() && !win.mAnimatingExit
2092 && !usingSavedSurfaceBeforeVisible) {
2093 if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Relayout invis " + win
2094 + ": mAnimatingExit=" + win.mAnimatingExit);
2095 // If we are not currently running the exit animation, we
2096 // need to see about starting one.
2097 // We don't want to animate visibility of windows which are pending
2098 // replacement. In the case of activity relaunch child windows
2099 // could request visibility changes as they are detached from the main
2100 // application window during the tear down process. If we satisfied
2101 // these visibility changes though, we would cause a visual glitch
2102 // hiding the window before it's replacement was available.
2103 // So we just do nothing on our side.
2104 if (!win.mWillReplaceWindow) {
2105 focusMayChange = tryStartExitingAnimation(
2106 win, winAnimator, isDefaultDisplay, focusMayChange);
2108 result |= RELAYOUT_RES_SURFACE_CHANGED;
2110 if (viewVisibility == View.VISIBLE && winAnimator.hasSurface()) {
2111 // We already told the client to go invisible, but the message may not be
2112 // handled yet, or it might want to draw a last frame. If we already have a
2113 // surface, let the client use that, but don't create new surface at this point.
2114 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: getSurface");
2115 winAnimator.mSurfaceController.getSurface(outSurface);
2116 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2118 if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win);
2121 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wmReleaseOutSurface_"
2122 + win.mAttrs.getTitle());
2123 outSurface.release();
2125 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2129 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2132 if (focusMayChange) {
2133 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
2134 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
2135 false /*updateInputWindows*/)) {
2138 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
2141 // updateFocusedWindowLocked() already assigned layers so we only need to
2142 // reassign them at this point if the IM window state gets shuffled
2143 boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
2144 final DisplayContent dc = win.getDisplayContent();
2146 dc.computeImeTarget(true /* updateImeTarget */);
2147 if (toBeDisplayed) {
2148 // Little hack here -- we -should- be able to rely on the function to return
2149 // true if the IME has moved and needs its layer recomputed. However, if the IME
2150 // was hidden and isn't actually moved in the list, its layer may be out of data
2151 // so we make sure to recompute it.
2152 dc.assignWindowLayers(false /* setLayoutNeeded */);
2156 if (wallpaperMayMove) {
2157 win.getDisplayContent().pendingLayoutChanges |=
2158 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2161 if (win.mAppToken != null) {
2162 mUnknownAppVisibilityController.notifyRelayouted(win.mAppToken);
2165 win.setDisplayLayoutNeeded();
2166 win.mGivenInsetsPending = (flags & WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
2167 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
2168 "relayoutWindow: updateOrientationFromAppTokens");
2169 configChanged = updateOrientationFromAppTokensLocked(false, displayId);
2170 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2172 // We may be deferring layout passes at the moment, but since the client is interested
2173 // in the new out values right now we need to force a layout.
2174 mWindowPlacerLocked.performSurfacePlacement(true /* force */);
2175 if (toBeDisplayed && win.mIsWallpaper) {
2176 DisplayInfo displayInfo = win.getDisplayContent().getDisplayInfo();
2177 dc.mWallpaperController.updateWallpaperOffset(
2178 win, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
2180 if (win.mAppToken != null) {
2181 win.mAppToken.updateReportedVisibilityLocked();
2183 if (winAnimator.mReportSurfaceResized) {
2184 winAnimator.mReportSurfaceResized = false;
2185 result |= WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED;
2187 if (mPolicy.isNavBarForcedShownLw(win)) {
2188 result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR;
2190 if (!win.isGoneForLayoutLw()) {
2191 win.mResizedWhileGone = false;
2194 // We must always send the latest {@link MergedConfiguration}, regardless of whether we
2195 // have already reported it. The client might not have processed the previous value yet
2196 // and needs process it before handling the corresponding window frame. the variable
2197 // {@code mergedConfiguration} is an out parameter that will be passed back to the
2198 // client over IPC and checked there.
2199 // Note: in the cases where the window is tied to an activity, we should not send a
2200 // configuration update when the window has requested to be hidden. Doing so can lead
2201 // to the client erroneously accepting a configuration that would have otherwise caused
2202 // an activity restart. We instead hand back the last reported
2203 // {@link MergedConfiguration}.
2204 if (shouldRelayout) {
2205 win.getMergedConfiguration(mergedConfiguration);
2207 win.getLastReportedMergedConfiguration(mergedConfiguration);
2210 win.setLastReportedMergedConfiguration(mergedConfiguration);
2212 outFrame.set(win.mCompatFrame);
2213 outOverscanInsets.set(win.mOverscanInsets);
2214 outContentInsets.set(win.mContentInsets);
2215 win.mLastRelayoutContentInsets.set(win.mContentInsets);
2216 outVisibleInsets.set(win.mVisibleInsets);
2217 outStableInsets.set(win.mStableInsets);
2218 outOutsets.set(win.mOutsets);
2219 outBackdropFrame.set(win.getBackdropFrame(win.mFrame));
2220 if (localLOGV) Slog.v(
2221 TAG_WM, "Relayout given client " + client.asBinder()
2222 + ", requestedWidth=" + requestedWidth
2223 + ", requestedHeight=" + requestedHeight
2224 + ", viewVisibility=" + viewVisibility
2225 + "\nRelayout returning frame=" + outFrame
2226 + ", surface=" + outSurface);
2228 if (localLOGV || DEBUG_FOCUS) Slog.v(
2229 TAG_WM, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
2231 result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0;
2233 mInputMonitor.updateInputWindowsLw(true /*force*/);
2236 Slog.v(TAG_WM, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
2238 win.mInRelayout = false;
2241 if (configChanged) {
2242 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: sendNewConfiguration");
2243 sendNewConfiguration(displayId);
2244 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2246 Binder.restoreCallingIdentity(origId);
2250 private boolean tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator,
2251 boolean isDefaultDisplay, boolean focusMayChange) {
2252 // Try starting an animation; if there isn't one, we
2253 // can destroy the surface right away.
2254 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2255 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2256 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2258 if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) {
2259 focusMayChange = isDefaultDisplay;
2260 win.mAnimatingExit = true;
2261 win.mWinAnimator.mAnimating = true;
2262 } else if (win.mWinAnimator.isAnimationSet()) {
2263 // Currently in a hide animation... turn this into
2265 win.mAnimatingExit = true;
2266 win.mWinAnimator.mAnimating = true;
2267 } else if (win.getDisplayContent().mWallpaperController.isWallpaperTarget(win)) {
2268 // If the wallpaper is currently behind this
2269 // window, we need to change both of them inside
2270 // of a transaction to avoid artifacts.
2271 win.mAnimatingExit = true;
2272 win.mWinAnimator.mAnimating = true;
2274 if (mInputMethodWindow == win) {
2275 setInputMethodWindowLocked(null);
2277 boolean stopped = win.mAppToken != null ? win.mAppToken.mAppStopped : false;
2278 // We set mDestroying=true so AppWindowToken#notifyAppStopped in-to destroy surfaces
2279 // will later actually destroy the surface if we do not do so here. Normally we leave
2280 // this to the exit animation.
2281 win.mDestroying = true;
2282 win.destroySurface(false, stopped);
2284 // TODO(multidisplay): Magnification is supported only for the default display.
2285 if (mAccessibilityController != null && win.getDisplayId() == DEFAULT_DISPLAY) {
2286 mAccessibilityController.onWindowTransitionLocked(win, transit);
2289 // When we start the exit animation we take the Surface from the client
2290 // so it will stop perturbing it. We need to likewise takeaway the SurfaceFlinger
2291 // side child surfaces, so they will remain preserved in their current state
2292 // (rather than be cleaned up immediately by the app code).
2293 SurfaceControl.openTransaction();
2294 winAnimator.detachChildren();
2295 SurfaceControl.closeTransaction();
2297 return focusMayChange;
2300 private int createSurfaceControl(Surface outSurface, int result, WindowState win,
2301 WindowStateAnimator winAnimator) {
2302 if (!win.mHasSurface) {
2303 result |= RELAYOUT_RES_SURFACE_CHANGED;
2306 WindowSurfaceController surfaceController;
2308 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");
2309 surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
2311 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2313 if (surfaceController != null) {
2314 surfaceController.getSurface(outSurface);
2315 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " OUT SURFACE " + outSurface + ": copied");
2317 // For some reason there isn't a surface. Clear the
2318 // caller's object so they see the same state.
2319 Slog.w(TAG_WM, "Failed to create surface control for " + win);
2320 outSurface.release();
2326 public boolean outOfMemoryWindow(Session session, IWindow client) {
2327 final long origId = Binder.clearCallingIdentity();
2330 synchronized (mWindowMap) {
2331 WindowState win = windowForClientLocked(session, client, false);
2335 return mRoot.reclaimSomeSurfaceMemory(win.mWinAnimator, "from-client", false);
2338 Binder.restoreCallingIdentity(origId);
2342 void finishDrawingWindow(Session session, IWindow client) {
2343 final long origId = Binder.clearCallingIdentity();
2345 synchronized (mWindowMap) {
2346 WindowState win = windowForClientLocked(session, client, false);
2347 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "finishDrawingWindow: " + win + " mDrawState="
2348 + (win != null ? win.mWinAnimator.drawStateToString() : "null"));
2349 if (win != null && win.mWinAnimator.finishDrawingLocked()) {
2350 if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
2351 win.getDisplayContent().pendingLayoutChanges |=
2352 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2354 win.setDisplayLayoutNeeded();
2355 mWindowPlacerLocked.requestTraversal();
2359 Binder.restoreCallingIdentity(origId);
2363 boolean applyAnimationLocked(AppWindowToken atoken, WindowManager.LayoutParams lp,
2364 int transit, boolean enter, boolean isVoiceInteraction) {
2365 // Only apply an animation if the display isn't frozen. If it is
2366 // frozen, there is no reason to animate and it can cause strange
2367 // artifacts when we unfreeze the display if some different animation
2369 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked");
2370 if (atoken.okToAnimate()) {
2371 final DisplayContent displayContent = atoken.getTask().getDisplayContent();
2372 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2373 final int width = displayInfo.appWidth;
2374 final int height = displayInfo.appHeight;
2375 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2376 "applyAnimation: atoken=" + atoken);
2378 // Determine the visible rect to calculate the thumbnail clip
2379 final WindowState win = atoken.findMainWindow();
2380 final Rect frame = new Rect(0, 0, width, height);
2381 final Rect displayFrame = new Rect(0, 0,
2382 displayInfo.logicalWidth, displayInfo.logicalHeight);
2383 final Rect insets = new Rect();
2384 final Rect stableInsets = new Rect();
2385 Rect surfaceInsets = null;
2386 final boolean freeform = win != null && win.inFreeformWorkspace();
2388 // Containing frame will usually cover the whole screen, including dialog windows.
2389 // For freeform workspace windows it will not cover the whole screen and it also
2390 // won't exactly match the final freeform window frame (e.g. when overlapping with
2391 // the status bar). In that case we need to use the final frame.
2393 frame.set(win.mFrame);
2395 frame.set(win.mContainingFrame);
2397 surfaceInsets = win.getAttrs().surfaceInsets;
2398 insets.set(win.mContentInsets);
2399 stableInsets.set(win.mStableInsets);
2402 if (atoken.mLaunchTaskBehind) {
2403 // Differentiate the two animations. This one which is briefly on the screen
2404 // gets the !enter animation, and the other activity which remains on the
2405 // screen gets the enter animation. Both appear in the mOpeningApps set.
2408 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2409 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2410 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2411 final Configuration displayConfig = displayContent.getConfiguration();
2412 Animation a = mAppTransition.loadAnimation(lp, transit, enter, displayConfig.uiMode,
2413 displayConfig.orientation, frame, displayFrame, insets, surfaceInsets,
2414 stableInsets, isVoiceInteraction, freeform, atoken.getTask().mTaskId);
2416 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken);
2417 final int containingWidth = frame.width();
2418 final int containingHeight = frame.height();
2419 atoken.mAppAnimator.setAnimation(a, containingWidth, containingHeight, width,
2420 height, mAppTransition.canSkipFirstFrame(),
2421 mAppTransition.getAppStackClipMode(),
2422 transit, mAppTransition.getTransitFlags());
2425 atoken.mAppAnimator.clearAnimation();
2427 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2429 return atoken.mAppAnimator.animation != null;
2432 boolean checkCallingPermission(String permission, String func) {
2433 // Quick check: if the calling permission is me, it's all okay.
2434 if (Binder.getCallingPid() == myPid()) {
2438 if (mContext.checkCallingPermission(permission)
2439 == PackageManager.PERMISSION_GRANTED) {
2442 final String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid()
2443 + ", uid=" + Binder.getCallingUid() + " requires " + permission;
2444 Slog.w(TAG_WM, msg);
2449 public void addWindowToken(IBinder binder, int type, int displayId) {
2450 if (!checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()")) {
2451 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2454 synchronized(mWindowMap) {
2455 final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId);
2456 WindowToken token = dc.getWindowToken(binder);
2457 if (token != null) {
2458 Slog.w(TAG_WM, "addWindowToken: Attempted to add binder token: " + binder
2459 + " for already created window token: " + token
2460 + " displayId=" + displayId);
2463 if (type == TYPE_WALLPAPER) {
2464 new WallpaperWindowToken(this, binder, true, dc,
2465 true /* ownerCanManageAppTokens */);
2467 new WindowToken(this, binder, type, true, dc, true /* ownerCanManageAppTokens */);
2473 public void removeWindowToken(IBinder binder, int displayId) {
2474 if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeWindowToken()")) {
2475 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2478 final long origId = Binder.clearCallingIdentity();
2480 synchronized (mWindowMap) {
2481 final DisplayContent dc = mRoot.getDisplayContent(displayId);
2483 Slog.w(TAG_WM, "removeWindowToken: Attempted to remove token: " + binder
2484 + " for non-exiting displayId=" + displayId);
2488 final WindowToken token = dc.removeWindowToken(binder);
2489 if (token == null) {
2491 "removeWindowToken: Attempted to remove non-existing token: " + binder);
2495 mInputMonitor.updateInputWindowsLw(true /*force*/);
2498 Binder.restoreCallingIdentity(origId);
2503 public Configuration updateOrientationFromAppTokens(Configuration currentConfig,
2504 IBinder freezeThisOneIfNeeded, int displayId) {
2505 if (!checkCallingPermission(MANAGE_APP_TOKENS, "updateOrientationFromAppTokens()")) {
2506 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2509 final Configuration config;
2510 final long ident = Binder.clearCallingIdentity();
2512 synchronized(mWindowMap) {
2513 config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded,
2517 Binder.restoreCallingIdentity(ident);
2523 private Configuration updateOrientationFromAppTokensLocked(Configuration currentConfig,
2524 IBinder freezeThisOneIfNeeded, int displayId) {
2525 if (!mDisplayReady) {
2528 Configuration config = null;
2530 if (updateOrientationFromAppTokensLocked(false, displayId)) {
2531 // If we changed the orientation but mOrientationChangeComplete is already true,
2532 // we used seamless rotation, and we don't need to freeze the screen.
2533 if (freezeThisOneIfNeeded != null && !mRoot.mOrientationChangeComplete) {
2534 final AppWindowToken atoken = mRoot.getAppWindowToken(freezeThisOneIfNeeded);
2535 if (atoken != null) {
2536 atoken.startFreezingScreen();
2539 config = computeNewConfigurationLocked(displayId);
2541 } else if (currentConfig != null) {
2542 // No obvious action we need to take, but if our current state mismatches the activity
2543 // manager's, update it, disregarding font scale, which should remain set to the value
2544 // of the previous configuration.
2545 // Here we're calling Configuration#unset() instead of setToDefaults() because we need
2546 // to keep override configs clear of non-empty values (e.g. fontSize).
2547 mTempConfiguration.unset();
2548 mTempConfiguration.updateFrom(currentConfig);
2549 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
2550 displayContent.computeScreenConfiguration(mTempConfiguration);
2551 if (currentConfig.diff(mTempConfiguration) != 0) {
2552 mWaitingForConfig = true;
2553 displayContent.setLayoutNeeded();
2554 int anim[] = new int[2];
2555 if (displayContent.isDimming()) {
2556 anim[0] = anim[1] = 0;
2558 mPolicy.selectRotationAnimationLw(anim);
2560 startFreezingDisplayLocked(false, anim[0], anim[1], displayContent);
2561 config = new Configuration(mTempConfiguration);
2569 * Determine the new desired orientation of the display, returning a non-null new Configuration
2570 * if it has changed from the current orientation. IF TRUE IS RETURNED SOMEONE MUST CALL
2571 * {@link #setNewDisplayOverrideConfiguration(Configuration, int)} TO TELL THE WINDOW MANAGER IT
2572 * CAN UNFREEZE THE SCREEN. This will typically be done for you if you call
2573 * {@link #sendNewConfiguration(int)}.
2575 * The orientation is computed from non-application windows first. If none of the
2576 * non-application windows specify orientation, the orientation is computed from application
2578 * @see android.view.IWindowManager#updateOrientationFromAppTokens(Configuration, IBinder, int)
2580 boolean updateOrientationFromAppTokensLocked(boolean inTransaction, int displayId) {
2581 long ident = Binder.clearCallingIdentity();
2583 final DisplayContent dc = mRoot.getDisplayContent(displayId);
2584 final int req = dc.getOrientation();
2585 if (req != dc.getLastOrientation()) {
2586 dc.setLastOrientation(req);
2587 //send a message to Policy indicating orientation change to take
2588 //action like disabling/enabling sensors etc.,
2589 // TODO(multi-display): Implement policy for secondary displays.
2590 if (dc.isDefaultDisplay) {
2591 mPolicy.setCurrentOrientationLw(req);
2593 if (dc.updateRotationUnchecked(inTransaction)) {
2601 Binder.restoreCallingIdentity(ident);
2605 // If this is true we have updated our desired orientation, but not yet
2606 // changed the real orientation our applied our screen rotation animation.
2607 // For example, because a previous screen rotation was in progress.
2608 boolean rotationNeedsUpdateLocked() {
2609 // TODO(multi-display): Check for updates on all displays. Need to have per-display policy
2610 // to implement WindowManagerPolicy#rotationForOrientationLw() correctly.
2611 final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
2612 final int lastOrientation = defaultDisplayContent.getLastOrientation();
2613 final int oldRotation = defaultDisplayContent.getRotation();
2614 final boolean oldAltOrientation = defaultDisplayContent.getAltOrientation();
2616 final int rotation = mPolicy.rotationForOrientationLw(lastOrientation,
2618 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
2619 lastOrientation, rotation);
2620 if (oldRotation == rotation && oldAltOrientation == altOrientation) {
2627 public int[] setNewDisplayOverrideConfiguration(Configuration overrideConfig, int displayId) {
2628 if (!checkCallingPermission(MANAGE_APP_TOKENS, "setNewDisplayOverrideConfiguration()")) {
2629 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2632 synchronized(mWindowMap) {
2633 if (mWaitingForConfig) {
2634 mWaitingForConfig = false;
2635 mLastFinishedFreezeSource = "new-config";
2637 return mRoot.setDisplayOverrideConfigurationIfNeeded(overrideConfig, displayId);
2641 void setFocusTaskRegionLocked(AppWindowToken previousFocus) {
2642 final Task focusedTask = mFocusedApp != null ? mFocusedApp.getTask() : null;
2643 final Task previousTask = previousFocus != null ? previousFocus.getTask() : null;
2644 final DisplayContent focusedDisplayContent =
2645 focusedTask != null ? focusedTask.getDisplayContent() : null;
2646 final DisplayContent previousDisplayContent =
2647 previousTask != null ? previousTask.getDisplayContent() : null;
2648 if (previousDisplayContent != null && previousDisplayContent != focusedDisplayContent) {
2649 previousDisplayContent.setTouchExcludeRegion(null);
2651 if (focusedDisplayContent != null) {
2652 focusedDisplayContent.setTouchExcludeRegion(focusedTask);
2657 public void setFocusedApp(IBinder token, boolean moveFocusNow) {
2658 if (!checkCallingPermission(MANAGE_APP_TOKENS, "setFocusedApp()")) {
2659 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2662 synchronized(mWindowMap) {
2663 final AppWindowToken newFocus;
2664 if (token == null) {
2665 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Clearing focused app, was " + mFocusedApp);
2668 newFocus = mRoot.getAppWindowToken(token);
2669 if (newFocus == null) {
2670 Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token);
2672 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Set focused app to: " + newFocus
2673 + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow);
2676 final boolean changed = mFocusedApp != newFocus;
2678 AppWindowToken prev = mFocusedApp;
2679 mFocusedApp = newFocus;
2680 mInputMonitor.setFocusedAppLw(newFocus);
2681 setFocusTaskRegionLocked(prev);
2684 if (moveFocusNow && changed) {
2685 final long origId = Binder.clearCallingIdentity();
2686 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
2687 Binder.restoreCallingIdentity(origId);
2693 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
2694 prepareAppTransition(transit, alwaysKeepCurrent, 0 /* flags */, false /* forceOverride */);
2698 * @param transit What kind of transition is happening. Use one of the constants
2699 * AppTransition.TRANSIT_*.
2700 * @param alwaysKeepCurrent If true and a transition is already set, new transition will NOT
2702 * @param flags Additional flags for the app transition, Use a combination of the constants
2703 * AppTransition.TRANSIT_FLAG_*.
2704 * @param forceOverride Always override the transit, not matter what was set previously.
2706 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent, int flags,
2707 boolean forceOverride) {
2708 if (!checkCallingPermission(MANAGE_APP_TOKENS, "prepareAppTransition()")) {
2709 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2711 synchronized(mWindowMap) {
2712 boolean prepared = mAppTransition.prepareAppTransitionLocked(transit, alwaysKeepCurrent,
2713 flags, forceOverride);
2714 // TODO (multidisplay): associate app transitions with displays
2715 final DisplayContent dc = mRoot.getDisplayContent(DEFAULT_DISPLAY);
2716 if (prepared && dc != null && dc.okToAnimate()) {
2717 mSkipAppTransitionAnimation = false;
2723 public int getPendingAppTransition() {
2724 return mAppTransition.getAppTransition();
2728 public void overridePendingAppTransition(String packageName,
2729 int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
2730 synchronized(mWindowMap) {
2731 mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim,
2737 public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
2739 synchronized(mWindowMap) {
2740 mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth,
2746 public void overridePendingAppTransitionClipReveal(int startX, int startY,
2747 int startWidth, int startHeight) {
2748 synchronized(mWindowMap) {
2749 mAppTransition.overridePendingAppTransitionClipReveal(startX, startY, startWidth,
2755 public void overridePendingAppTransitionThumb(GraphicBuffer srcThumb, int startX,
2756 int startY, IRemoteCallback startedCallback, boolean scaleUp) {
2757 synchronized(mWindowMap) {
2758 mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY,
2759 startedCallback, scaleUp);
2764 public void overridePendingAppTransitionAspectScaledThumb(GraphicBuffer srcThumb, int startX,
2765 int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
2767 synchronized(mWindowMap) {
2768 mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX, startY,
2769 targetWidth, targetHeight, startedCallback, scaleUp);
2774 public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
2775 IRemoteCallback onAnimationStartedCallback, IRemoteCallback onAnimationFinishedCallback,
2777 synchronized (mWindowMap) {
2778 mAppTransition.overridePendingAppTransitionMultiThumb(specs, onAnimationStartedCallback,
2779 onAnimationFinishedCallback, scaleUp);
2780 prolongAnimationsFromSpecs(specs, scaleUp);
2785 void prolongAnimationsFromSpecs(@NonNull AppTransitionAnimationSpec[] specs, boolean scaleUp) {
2786 // This is used by freeform <-> recents windows transition. We need to synchronize
2787 // the animation with the appearance of the content of recents, so we will make
2788 // animation stay on the first or last frame a little longer.
2789 mTmpTaskIds.clear();
2790 for (int i = specs.length - 1; i >= 0; i--) {
2791 mTmpTaskIds.put(specs[i].taskId, 0);
2793 for (final WindowState win : mWindowMap.values()) {
2794 final Task task = win.getTask();
2795 if (task != null && mTmpTaskIds.get(task.mTaskId, -1) != -1
2796 && task.inFreeformWorkspace()) {
2797 final AppWindowToken appToken = win.mAppToken;
2798 if (appToken != null && appToken.mAppAnimator != null) {
2799 appToken.mAppAnimator.startProlongAnimation(scaleUp ?
2800 PROLONG_ANIMATION_AT_START : PROLONG_ANIMATION_AT_END);
2807 public void overridePendingAppTransitionInPlace(String packageName, int anim) {
2808 synchronized(mWindowMap) {
2809 mAppTransition.overrideInPlaceAppTransition(packageName, anim);
2814 public void overridePendingAppTransitionMultiThumbFuture(
2815 IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback,
2817 synchronized(mWindowMap) {
2818 mAppTransition.overridePendingAppTransitionMultiThumbFuture(specsFuture, callback,
2824 public void endProlongedAnimations() {
2825 synchronized (mWindowMap) {
2826 for (final WindowState win : mWindowMap.values()) {
2827 final AppWindowToken appToken = win.mAppToken;
2828 if (appToken != null && appToken.mAppAnimator != null) {
2829 appToken.mAppAnimator.endProlongedAnimation();
2832 mAppTransition.notifyProlongedAnimationsEnded();
2837 public void executeAppTransition() {
2838 if (!checkCallingPermission(MANAGE_APP_TOKENS, "executeAppTransition()")) {
2839 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2842 synchronized(mWindowMap) {
2843 if (DEBUG_APP_TRANSITIONS) Slog.w(TAG_WM, "Execute app transition: " + mAppTransition
2844 + " Callers=" + Debug.getCallers(5));
2845 if (mAppTransition.isTransitionSet()) {
2846 mAppTransition.setReady();
2847 final long origId = Binder.clearCallingIdentity();
2849 mWindowPlacerLocked.performSurfacePlacement();
2851 Binder.restoreCallingIdentity(origId);
2857 public void setAppFullscreen(IBinder token, boolean toOpaque) {
2858 synchronized (mWindowMap) {
2859 final AppWindowToken atoken = mRoot.getAppWindowToken(token);
2860 if (atoken != null) {
2861 atoken.setFillsParent(toOpaque);
2862 setWindowOpaqueLocked(token, toOpaque);
2863 mWindowPlacerLocked.requestTraversal();
2868 public void setWindowOpaque(IBinder token, boolean isOpaque) {
2869 synchronized (mWindowMap) {
2870 setWindowOpaqueLocked(token, isOpaque);
2874 private void setWindowOpaqueLocked(IBinder token, boolean isOpaque) {
2875 final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
2876 if (wtoken != null) {
2877 final WindowState win = wtoken.findMainWindow();
2879 win.mWinAnimator.setOpaqueLocked(isOpaque);
2884 void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) {
2885 if (transit != TRANSIT_UNSET) {
2886 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
2887 wtoken.mAppAnimator.setNullAnimation();
2889 applyAnimationLocked(wtoken, null, transit, false, false);
2893 public void setDockedStackCreateState(int mode, Rect bounds) {
2894 synchronized (mWindowMap) {
2895 setDockedStackCreateStateLocked(mode, bounds);
2899 void setDockedStackCreateStateLocked(int mode, Rect bounds) {
2900 mDockedStackCreateMode = mode;
2901 mDockedStackCreateBounds = bounds;
2904 public boolean isValidPictureInPictureAspectRatio(int displayId, float aspectRatio) {
2905 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
2906 return displayContent.getPinnedStackController().isValidPictureInPictureAspectRatio(
2911 public void getStackBounds(int stackId, Rect bounds) {
2912 synchronized (mWindowMap) {
2913 final TaskStack stack = mRoot.getStackById(stackId);
2914 if (stack != null) {
2915 stack.getBounds(bounds);
2923 public void notifyShowingDreamChanged() {
2924 notifyKeyguardFlagsChanged(null /* callback */);
2928 public WindowManagerPolicy.WindowState getInputMethodWindowLw() {
2929 return mInputMethodWindow;
2933 public void notifyKeyguardTrustedChanged() {
2934 mH.sendEmptyMessage(H.NOTIFY_KEYGUARD_TRUSTED_CHANGED);
2938 public void onKeyguardShowingAndNotOccludedChanged() {
2939 mH.sendEmptyMessage(H.RECOMPUTE_FOCUS);
2943 public void screenTurningOff(ScreenOffListener listener) {
2944 mTaskSnapshotController.screenTurningOff(listener);
2948 * Starts deferring layout passes. Useful when doing multiple changes but to optimize
2949 * performance, only one layout pass should be done. This can be called multiple times, and
2950 * layouting will be resumed once the last caller has called {@link #continueSurfaceLayout}
2952 public void deferSurfaceLayout() {
2953 synchronized (mWindowMap) {
2954 mWindowPlacerLocked.deferLayout();
2959 * Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()}
2961 public void continueSurfaceLayout() {
2962 synchronized (mWindowMap) {
2963 mWindowPlacerLocked.continueLayout();
2968 * @return true if the activity contains windows that have
2969 * {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set
2971 public boolean containsShowWhenLockedWindow(IBinder token) {
2972 synchronized (mWindowMap) {
2973 final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
2974 return wtoken != null && wtoken.containsShowWhenLockedWindow();
2979 * @return true if the activity contains windows that have
2980 * {@link LayoutParams#FLAG_DISMISS_KEYGUARD} set
2982 public boolean containsDismissKeyguardWindow(IBinder token) {
2983 synchronized (mWindowMap) {
2984 final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
2985 return wtoken != null && wtoken.containsDismissKeyguardWindow();
2990 * Notifies activity manager that some Keyguard flags have changed and that it needs to
2991 * reevaluate the visibilities of the activities.
2992 * @param callback Runnable to be called when activity manager is done reevaluating visibilities
2994 void notifyKeyguardFlagsChanged(@Nullable Runnable callback) {
2995 final Runnable wrappedCallback = callback != null
2996 ? () -> { synchronized (mWindowMap) { callback.run(); } }
2998 mH.obtainMessage(H.NOTIFY_KEYGUARD_FLAGS_CHANGED, wrappedCallback).sendToTarget();
3001 public boolean isKeyguardTrusted() {
3002 synchronized (mWindowMap) {
3003 return mPolicy.isKeyguardTrustedLw();
3007 public void setKeyguardGoingAway(boolean keyguardGoingAway) {
3008 synchronized (mWindowMap) {
3009 mKeyguardGoingAway = keyguardGoingAway;
3013 // -------------------------------------------------------------
3014 // Misc IWindowSession methods
3015 // -------------------------------------------------------------
3018 public void startFreezingScreen(int exitAnim, int enterAnim) {
3019 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
3020 "startFreezingScreen()")) {
3021 throw new SecurityException("Requires FREEZE_SCREEN permission");
3024 synchronized(mWindowMap) {
3025 if (!mClientFreezingScreen) {
3026 mClientFreezingScreen = true;
3027 final long origId = Binder.clearCallingIdentity();
3029 startFreezingDisplayLocked(false, exitAnim, enterAnim);
3030 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
3031 mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
3033 Binder.restoreCallingIdentity(origId);
3040 public void stopFreezingScreen() {
3041 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
3042 "stopFreezingScreen()")) {
3043 throw new SecurityException("Requires FREEZE_SCREEN permission");
3046 synchronized(mWindowMap) {
3047 if (mClientFreezingScreen) {
3048 mClientFreezingScreen = false;
3049 mLastFinishedFreezeSource = "client";
3050 final long origId = Binder.clearCallingIdentity();
3052 stopFreezingDisplayLocked();
3054 Binder.restoreCallingIdentity(origId);
3061 public void disableKeyguard(IBinder token, String tag) {
3062 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
3063 != PackageManager.PERMISSION_GRANTED) {
3064 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
3066 // If this isn't coming from the system then don't allow disabling the lockscreen
3067 // to bypass security.
3068 if (Binder.getCallingUid() != SYSTEM_UID && isKeyguardSecure()) {
3069 Log.d(TAG_WM, "current mode is SecurityMode, ignore disableKeyguard");
3073 // If this isn't coming from the current profiles, ignore it.
3074 if (!isCurrentProfileLocked(UserHandle.getCallingUserId())) {
3075 Log.d(TAG_WM, "non-current profiles, ignore disableKeyguard");
3079 if (token == null) {
3080 throw new IllegalArgumentException("token == null");
3083 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
3084 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
3088 public void reenableKeyguard(IBinder token) {
3089 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
3090 != PackageManager.PERMISSION_GRANTED) {
3091 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
3094 if (token == null) {
3095 throw new IllegalArgumentException("token == null");
3098 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
3099 KeyguardDisableHandler.KEYGUARD_REENABLE, token));
3103 * @see android.app.KeyguardManager#exitKeyguardSecurely
3106 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
3107 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
3108 != PackageManager.PERMISSION_GRANTED) {
3109 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
3112 if (callback == null) {
3113 throw new IllegalArgumentException("callback == null");
3116 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
3118 public void onKeyguardExitResult(boolean success) {
3120 callback.onKeyguardExitResult(success);
3121 } catch (RemoteException e) {
3122 // Client has died, we don't care.
3129 public boolean inKeyguardRestrictedInputMode() {
3130 return mPolicy.inKeyguardRestrictedKeyInputMode();
3134 public boolean isKeyguardLocked() {
3135 return mPolicy.isKeyguardLocked();
3138 public boolean isKeyguardShowingAndNotOccluded() {
3139 return mPolicy.isKeyguardShowingAndNotOccluded();
3143 public boolean isKeyguardSecure() {
3144 int userId = UserHandle.getCallingUserId();
3145 long origId = Binder.clearCallingIdentity();
3147 return mPolicy.isKeyguardSecure(userId);
3149 Binder.restoreCallingIdentity(origId);
3153 public boolean isShowingDream() {
3154 synchronized (mWindowMap) {
3155 return mPolicy.isShowingDreamLw();
3160 public void dismissKeyguard(IKeyguardDismissCallback callback) {
3161 checkCallingPermission(permission.CONTROL_KEYGUARD, "dismissKeyguard");
3162 synchronized(mWindowMap) {
3163 mPolicy.dismissKeyguardLw(callback);
3167 public void onKeyguardOccludedChanged(boolean occluded) {
3168 synchronized (mWindowMap) {
3169 mPolicy.onKeyguardOccludedChangedLw(occluded);
3174 public void setSwitchingUser(boolean switching) {
3175 if (!checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
3176 "setSwitchingUser()")) {
3177 throw new SecurityException("Requires INTERACT_ACROSS_USERS_FULL permission");
3179 mPolicy.setSwitchingUser(switching);
3180 synchronized (mWindowMap) {
3181 mSwitchingUser = switching;
3185 void showGlobalActions() {
3186 mPolicy.showGlobalActions();
3190 public void closeSystemDialogs(String reason) {
3191 synchronized(mWindowMap) {
3192 mRoot.closeSystemDialogs(reason);
3196 static float fixScale(float scale) {
3197 if (scale < 0) scale = 0;
3198 else if (scale > 20) scale = 20;
3199 return Math.abs(scale);
3203 public void setAnimationScale(int which, float scale) {
3204 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
3205 "setAnimationScale()")) {
3206 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
3209 scale = fixScale(scale);
3211 case 0: mWindowAnimationScaleSetting = scale; break;
3212 case 1: mTransitionAnimationScaleSetting = scale; break;
3213 case 2: mAnimatorDurationScaleSetting = scale; break;
3217 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
3221 public void setAnimationScales(float[] scales) {
3222 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
3223 "setAnimationScale()")) {
3224 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
3227 if (scales != null) {
3228 if (scales.length >= 1) {
3229 mWindowAnimationScaleSetting = fixScale(scales[0]);
3231 if (scales.length >= 2) {
3232 mTransitionAnimationScaleSetting = fixScale(scales[1]);
3234 if (scales.length >= 3) {
3235 mAnimatorDurationScaleSetting = fixScale(scales[2]);
3236 dispatchNewAnimatorScaleLocked(null);
3241 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
3244 private void setAnimatorDurationScale(float scale) {
3245 mAnimatorDurationScaleSetting = scale;
3246 ValueAnimator.setDurationScale(scale);
3249 public float getWindowAnimationScaleLocked() {
3250 return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting;
3253 public float getTransitionAnimationScaleLocked() {
3254 return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting;
3258 public float getAnimationScale(int which) {
3260 case 0: return mWindowAnimationScaleSetting;
3261 case 1: return mTransitionAnimationScaleSetting;
3262 case 2: return mAnimatorDurationScaleSetting;
3268 public float[] getAnimationScales() {
3269 return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting,
3270 mAnimatorDurationScaleSetting };
3274 public float getCurrentAnimatorScale() {
3275 synchronized(mWindowMap) {
3276 return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting;
3280 void dispatchNewAnimatorScaleLocked(Session session) {
3281 mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget();
3285 public void registerPointerEventListener(PointerEventListener listener) {
3286 mPointerEventDispatcher.registerInputEventListener(listener);
3290 public void unregisterPointerEventListener(PointerEventListener listener) {
3291 mPointerEventDispatcher.unregisterInputEventListener(listener);
3294 /** Check if the service is set to dispatch pointer events. */
3295 boolean canDispatchPointerEvents() {
3296 return mPointerEventDispatcher != null;
3299 // Called by window manager policy. Not exposed externally.
3301 public int getLidState() {
3302 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
3303 InputManagerService.SW_LID);
3305 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
3307 } else if (sw == 0) {
3308 // Switch state: AKEY_STATE_UP.
3311 // Switch state: AKEY_STATE_UNKNOWN.
3316 // Called by window manager policy. Not exposed externally.
3318 public void lockDeviceNow() {
3322 // Called by window manager policy. Not exposed externally.
3324 public int getCameraLensCoverState() {
3325 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
3326 InputManagerService.SW_CAMERA_LENS_COVER);
3328 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
3329 return CAMERA_LENS_COVERED;
3330 } else if (sw == 0) {
3331 // Switch state: AKEY_STATE_UP.
3332 return CAMERA_LENS_UNCOVERED;
3334 // Switch state: AKEY_STATE_UNKNOWN.
3335 return CAMERA_LENS_COVER_ABSENT;
3339 // Called by window manager policy. Not exposed externally.
3341 public void switchInputMethod(boolean forwardDirection) {
3342 final InputMethodManagerInternal inputMethodManagerInternal =
3343 LocalServices.getService(InputMethodManagerInternal.class);
3344 if (inputMethodManagerInternal != null) {
3345 inputMethodManagerInternal.switchInputMethod(forwardDirection);
3349 // Called by window manager policy. Not exposed externally.
3351 public void shutdown(boolean confirm) {
3352 // Pass in the UI context, since ShutdownThread requires it (to show UI).
3353 ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(),
3354 PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
3357 // Called by window manager policy. Not exposed externally.
3359 public void reboot(boolean confirm) {
3360 // Pass in the UI context, since ShutdownThread requires it (to show UI).
3361 ShutdownThread.reboot(ActivityThread.currentActivityThread().getSystemUiContext(),
3362 PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
3365 // Called by window manager policy. Not exposed externally.
3367 public void rebootSafeMode(boolean confirm) {
3368 // Pass in the UI context, since ShutdownThread requires it (to show UI).
3369 ShutdownThread.rebootSafeMode(ActivityThread.currentActivityThread().getSystemUiContext(),
3373 public void setCurrentProfileIds(final int[] currentProfileIds) {
3374 synchronized (mWindowMap) {
3375 mCurrentProfileIds = currentProfileIds;
3379 public void setCurrentUser(final int newUserId, final int[] currentProfileIds) {
3380 synchronized (mWindowMap) {
3381 mCurrentUserId = newUserId;
3382 mCurrentProfileIds = currentProfileIds;
3383 mAppTransition.setCurrentUser(newUserId);
3384 mPolicy.setCurrentUserLw(newUserId);
3386 // If keyguard was disabled, re-enable it
3387 // TODO: Keep track of keyguardEnabled state per user and use here...
3388 // e.g. enabled = mKeyguardDisableHandler.getEnabledStateForUser(newUserId);
3389 mPolicy.enableKeyguard(true);
3391 // Hide windows that should not be seen by the new user.
3393 mWindowPlacerLocked.performSurfacePlacement();
3395 // Notify whether the docked stack exists for the current user
3396 final DisplayContent displayContent = getDefaultDisplayContentLocked();
3397 final TaskStack stack = displayContent.getDockedStackIgnoringVisibility();
3398 displayContent.mDividerControllerLocked.notifyDockedStackExistsChanged(
3399 stack != null && stack.hasTaskForUser(newUserId));
3401 // If the display is already prepared, update the density.
3402 // Otherwise, we'll update it when it's prepared.
3403 if (mDisplayReady) {
3404 final int forcedDensity = getForcedDisplayDensityForUserLocked(newUserId);
3405 final int targetDensity = forcedDensity != 0 ? forcedDensity
3406 : displayContent.mInitialDisplayDensity;
3407 setForcedDisplayDensityLocked(displayContent, targetDensity);
3412 /* Called by WindowState */
3413 boolean isCurrentProfileLocked(int userId) {
3414 if (userId == mCurrentUserId) return true;
3415 for (int i = 0; i < mCurrentProfileIds.length; i++) {
3416 if (mCurrentProfileIds[i] == userId) return true;
3421 public void enableScreenAfterBoot() {
3422 synchronized(mWindowMap) {
3424 RuntimeException here = new RuntimeException("here");
3425 here.fillInStackTrace();
3426 Slog.i(TAG_WM, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
3427 + " mForceDisplayEnabled=" + mForceDisplayEnabled
3428 + " mShowingBootMessages=" + mShowingBootMessages
3429 + " mSystemBooted=" + mSystemBooted, here);
3431 if (mSystemBooted) {
3434 mSystemBooted = true;
3435 hideBootMessagesLocked();
3436 // If the screen still doesn't come up after 30 seconds, give
3437 // up and turn it on.
3438 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30 * 1000);
3441 mPolicy.systemBooted();
3443 performEnableScreen();
3447 public void enableScreenIfNeeded() {
3448 synchronized (mWindowMap) {
3449 enableScreenIfNeededLocked();
3453 void enableScreenIfNeededLocked() {
3455 RuntimeException here = new RuntimeException("here");
3456 here.fillInStackTrace();
3457 Slog.i(TAG_WM, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
3458 + " mForceDisplayEnabled=" + mForceDisplayEnabled
3459 + " mShowingBootMessages=" + mShowingBootMessages
3460 + " mSystemBooted=" + mSystemBooted, here);
3462 if (mDisplayEnabled) {
3465 if (!mSystemBooted && !mShowingBootMessages) {
3468 mH.sendEmptyMessage(H.ENABLE_SCREEN);
3471 public void performBootTimeout() {
3472 synchronized(mWindowMap) {
3473 if (mDisplayEnabled) {
3476 Slog.w(TAG_WM, "***** BOOT TIMEOUT: forcing display enabled");
3477 mForceDisplayEnabled = true;
3479 performEnableScreen();
3483 * Called when System UI has been started.
3485 public void onSystemUiStarted() {
3486 mPolicy.onSystemUiStarted();
3489 private void performEnableScreen() {
3490 synchronized(mWindowMap) {
3491 if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
3492 + " mForceDisplayEnabled=" + mForceDisplayEnabled
3493 + " mShowingBootMessages=" + mShowingBootMessages
3494 + " mSystemBooted=" + mSystemBooted
3495 + " mOnlyCore=" + mOnlyCore,
3496 new RuntimeException("here").fillInStackTrace());
3497 if (mDisplayEnabled) {
3500 if (!mSystemBooted && !mShowingBootMessages) {
3504 if (!mShowingBootMessages && !mPolicy.canDismissBootAnimation()) {
3508 // Don't enable the screen until all existing windows have been drawn.
3509 if (!mForceDisplayEnabled
3510 // TODO(multidisplay): Expand to all displays?
3511 && getDefaultDisplayContentLocked().checkWaitingForWindows()) {
3515 if (!mBootAnimationStopped) {
3516 Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
3517 // stop boot animation
3518 // formerly we would just kill the process, but we now ask it to exit so it
3519 // can choose where to stop the animation.
3520 SystemProperties.set("service.bootanim.exit", "1");
3521 mBootAnimationStopped = true;
3524 if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {
3525 if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: Waiting for anim complete");
3530 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
3531 if (surfaceFlinger != null) {
3532 Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
3533 Parcel data = Parcel.obtain();
3534 data.writeInterfaceToken("android.ui.ISurfaceComposer");
3535 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
3539 } catch (RemoteException ex) {
3540 Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!");
3543 EventLog.writeEvent(EventLogTags.WM_BOOT_ANIMATION_DONE, SystemClock.uptimeMillis());
3544 Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
3545 mDisplayEnabled = true;
3546 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, "******************** ENABLING SCREEN!");
3548 // Enable input dispatch.
3549 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
3553 mActivityManager.bootAnimationComplete();
3554 } catch (RemoteException e) {
3557 mPolicy.enableScreenAfterBoot();
3559 // Make sure the last requested orientation has been applied.
3560 updateRotationUnchecked(false, false);
3563 private boolean checkBootAnimationCompleteLocked() {
3564 if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) {
3565 mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED);
3566 mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED,
3567 BOOT_ANIMATION_POLL_INTERVAL);
3568 if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Waiting for anim complete");
3571 if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Animation complete!");
3575 public void showBootMessage(final CharSequence msg, final boolean always) {
3576 boolean first = false;
3577 synchronized(mWindowMap) {
3579 RuntimeException here = new RuntimeException("here");
3580 here.fillInStackTrace();
3581 Slog.i(TAG_WM, "showBootMessage: msg=" + msg + " always=" + always
3582 + " mAllowBootMessages=" + mAllowBootMessages
3583 + " mShowingBootMessages=" + mShowingBootMessages
3584 + " mSystemBooted=" + mSystemBooted, here);
3586 if (!mAllowBootMessages) {
3589 if (!mShowingBootMessages) {
3595 if (mSystemBooted) {
3598 mShowingBootMessages = true;
3599 mPolicy.showBootMessage(msg, always);
3602 performEnableScreen();
3606 public void hideBootMessagesLocked() {
3608 RuntimeException here = new RuntimeException("here");
3609 here.fillInStackTrace();
3610 Slog.i(TAG_WM, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
3611 + " mForceDisplayEnabled=" + mForceDisplayEnabled
3612 + " mShowingBootMessages=" + mShowingBootMessages
3613 + " mSystemBooted=" + mSystemBooted, here);
3615 if (mShowingBootMessages) {
3616 mShowingBootMessages = false;
3617 mPolicy.hideBootMessages();
3622 public void setInTouchMode(boolean mode) {
3623 synchronized(mWindowMap) {
3624 mInTouchMode = mode;
3628 private void updateCircularDisplayMaskIfNeeded() {
3629 if (mContext.getResources().getConfiguration().isScreenRound()
3630 && mContext.getResources().getBoolean(
3631 com.android.internal.R.bool.config_windowShowCircularMask)) {
3632 final int currentUserId;
3633 synchronized(mWindowMap) {
3634 currentUserId = mCurrentUserId;
3636 // Device configuration calls for a circular display mask, but we only enable the mask
3637 // if the accessibility color inversion feature is disabled, as the inverted mask
3638 // causes artifacts.
3639 int inversionState = Settings.Secure.getIntForUser(mContext.getContentResolver(),
3640 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, currentUserId);
3641 int showMask = (inversionState == 1) ? 0 : 1;
3642 Message m = mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK);
3648 public void showEmulatorDisplayOverlayIfNeeded() {
3649 if (mContext.getResources().getBoolean(
3650 com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay)
3651 && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false)
3652 && Build.IS_EMULATOR) {
3653 mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY));
3657 public void showCircularMask(boolean visible) {
3658 synchronized(mWindowMap) {
3660 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
3661 ">>> OPEN TRANSACTION showCircularMask(visible=" + visible + ")");
3662 openSurfaceTransaction();
3665 // TODO(multi-display): support multiple displays
3666 if (mCircularDisplayMask == null) {
3667 int screenOffset = mContext.getResources().getInteger(
3668 com.android.internal.R.integer.config_windowOutsetBottom);
3669 int maskThickness = mContext.getResources().getDimensionPixelSize(
3670 com.android.internal.R.dimen.circular_display_mask_thickness);
3672 mCircularDisplayMask = new CircularDisplayMask(
3673 getDefaultDisplayContentLocked().getDisplay(),
3675 mPolicy.getWindowLayerFromTypeLw(
3676 WindowManager.LayoutParams.TYPE_POINTER)
3677 * TYPE_LAYER_MULTIPLIER + 10, screenOffset, maskThickness);
3679 mCircularDisplayMask.setVisibility(true);
3680 } else if (mCircularDisplayMask != null) {
3681 mCircularDisplayMask.setVisibility(false);
3682 mCircularDisplayMask = null;
3685 closeSurfaceTransaction();
3686 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
3687 "<<< CLOSE TRANSACTION showCircularMask(visible=" + visible + ")");
3692 public void showEmulatorDisplayOverlay() {
3693 synchronized(mWindowMap) {
3695 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
3696 ">>> OPEN TRANSACTION showEmulatorDisplayOverlay");
3697 openSurfaceTransaction();
3699 if (mEmulatorDisplayOverlay == null) {
3700 mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(
3702 getDefaultDisplayContentLocked().getDisplay(),
3704 mPolicy.getWindowLayerFromTypeLw(
3705 WindowManager.LayoutParams.TYPE_POINTER)
3706 * TYPE_LAYER_MULTIPLIER + 10);
3708 mEmulatorDisplayOverlay.setVisibility(true);
3710 closeSurfaceTransaction();
3711 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
3712 "<<< CLOSE TRANSACTION showEmulatorDisplayOverlay");
3717 // TODO: more accounting of which pid(s) turned it on, keep count,
3718 // only allow disables from pids which have count on, etc.
3720 public void showStrictModeViolation(boolean on) {
3721 final int pid = Binder.getCallingPid();
3723 // Show the visualization, and enqueue a second message to tear it
3724 // down if we don't hear back from the app.
3725 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 1, pid));
3726 mH.sendMessageDelayed(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid),
3727 DateUtils.SECOND_IN_MILLIS);
3729 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid));
3733 private void showStrictModeViolation(int arg, int pid) {
3734 final boolean on = arg != 0;
3735 synchronized(mWindowMap) {
3736 // Ignoring requests to enable the red border from clients which aren't on screen.
3737 // (e.g. Broadcast Receivers in the background..)
3738 if (on && !mRoot.canShowStrictModeViolation(pid)) {
3742 if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
3743 ">>> OPEN TRANSACTION showStrictModeViolation");
3744 // TODO: Modify this to use the surface trace once it is not going crazy.
3746 SurfaceControl.openTransaction();
3748 // TODO(multi-display): support multiple displays
3749 if (mStrictModeFlash == null) {
3750 mStrictModeFlash = new StrictModeFlash(
3751 getDefaultDisplayContentLocked().getDisplay(), mFxSession);
3753 mStrictModeFlash.setVisibility(on);
3755 SurfaceControl.closeTransaction();
3756 if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
3757 "<<< CLOSE TRANSACTION showStrictModeViolation");
3763 public void setStrictModeVisualIndicatorPreference(String value) {
3764 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
3768 public Bitmap screenshotWallpaper() {
3769 if (!checkCallingPermission(READ_FRAME_BUFFER,
3770 "screenshotWallpaper()")) {
3771 throw new SecurityException("Requires READ_FRAME_BUFFER permission");
3774 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper");
3775 return screenshotApplications(null /* appToken */, DEFAULT_DISPLAY, -1 /* width */,
3776 -1 /* height */, true /* includeFullDisplay */, 1f /* frameScale */,
3777 Bitmap.Config.ARGB_8888, true /* wallpaperOnly */, false /* includeDecor */);
3779 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
3784 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
3785 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
3786 * of the target image.
3789 public boolean requestAssistScreenshot(final IAssistScreenshotReceiver receiver) {
3790 if (!checkCallingPermission(READ_FRAME_BUFFER,
3791 "requestAssistScreenshot()")) {
3792 throw new SecurityException("Requires READ_FRAME_BUFFER permission");
3795 FgThread.getHandler().post(() -> {
3796 Bitmap bm = screenshotApplications(null /* appToken */, DEFAULT_DISPLAY,
3797 -1 /* width */, -1 /* height */, true /* includeFullDisplay */,
3798 1f /* frameScale */, Bitmap.Config.ARGB_8888, false /* wallpaperOnly */,
3799 false /* includeDecor */);
3802 } catch (RemoteException e) {
3809 public TaskSnapshot getTaskSnapshot(int taskId, int userId, boolean reducedResolution) {
3810 return mTaskSnapshotController.getSnapshot(taskId, userId, true /* restoreFromDisk */,
3815 * In case a task write/delete operation was lost because the system crashed, this makes sure to
3816 * clean up the directory to remove obsolete files.
3818 * @param persistentTaskIds A set of task ids that exist in our in-memory model.
3819 * @param runningUserIds The ids of the list of users that have tasks loaded in our in-memory
3822 public void removeObsoleteTaskFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds) {
3823 synchronized (mWindowMap) {
3824 mTaskSnapshotController.removeObsoleteTaskFiles(persistentTaskIds, runningUserIds);
3829 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
3830 * In portrait mode, it grabs the full screenshot.
3832 * @param displayId the Display to take a screenshot of.
3833 * @param width the width of the target bitmap
3834 * @param height the height of the target bitmap
3835 * @param includeFullDisplay true if the screen should not be cropped before capture
3836 * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
3837 * @param config of the output bitmap
3838 * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
3839 * @param includeDecor whether to include window decors, like the status or navigation bar
3840 * background of the window
3842 private Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
3843 int height, boolean includeFullDisplay, float frameScale, Bitmap.Config config,
3844 boolean wallpaperOnly, boolean includeDecor) {
3845 final DisplayContent displayContent;
3846 synchronized(mWindowMap) {
3847 displayContent = mRoot.getDisplayContentOrCreate(displayId);
3848 if (displayContent == null) {
3849 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
3850 + ": returning null. No Display for displayId=" + displayId);
3854 return displayContent.screenshotApplications(appToken, width, height,
3855 includeFullDisplay, frameScale, config, wallpaperOnly, includeDecor);
3859 * Freeze rotation changes. (Enable "rotation lock".)
3860 * Persists across reboots.
3861 * @param rotation The desired rotation to freeze to, or -1 to use the
3865 public void freezeRotation(int rotation) {
3866 // TODO(multi-display): Track which display is rotated.
3867 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
3868 "freezeRotation()")) {
3869 throw new SecurityException("Requires SET_ORIENTATION permission");
3871 if (rotation < -1 || rotation > Surface.ROTATION_270) {
3872 throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
3873 + "rotation constant.");
3876 final int defaultDisplayRotation = getDefaultDisplayRotation();
3877 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "freezeRotation: mRotation="
3878 + defaultDisplayRotation);
3880 long origId = Binder.clearCallingIdentity();
3882 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
3883 rotation == -1 ? defaultDisplayRotation : rotation);
3885 Binder.restoreCallingIdentity(origId);
3888 updateRotationUnchecked(false, false);
3892 * Thaw rotation changes. (Disable "rotation lock".)
3893 * Persists across reboots.
3896 public void thawRotation() {
3897 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
3898 "thawRotation()")) {
3899 throw new SecurityException("Requires SET_ORIENTATION permission");
3902 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "thawRotation: mRotation="
3903 + getDefaultDisplayRotation());
3905 long origId = Binder.clearCallingIdentity();
3907 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
3908 777); // rot not used
3910 Binder.restoreCallingIdentity(origId);
3913 updateRotationUnchecked(false, false);
3917 * Recalculate the current rotation.
3919 * Called by the window manager policy whenever the state of the system changes
3920 * such that the current rotation might need to be updated, such as when the
3921 * device is docked or rotated into a new posture.
3924 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
3925 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
3929 * Temporarily pauses rotation changes until resumed.
3931 * This can be used to prevent rotation changes from occurring while the user is
3932 * performing certain operations, such as drag and drop.
3934 * This call nests and must be matched by an equal number of calls to
3935 * {@link #resumeRotationLocked}.
3937 void pauseRotationLocked() {
3938 mDeferredRotationPauseCount += 1;
3942 * Resumes normal rotation changes after being paused.
3944 void resumeRotationLocked() {
3945 if (mDeferredRotationPauseCount > 0) {
3946 mDeferredRotationPauseCount -= 1;
3947 if (mDeferredRotationPauseCount == 0) {
3948 // TODO(multi-display): Update rotation for different displays separately.
3949 final DisplayContent displayContent = getDefaultDisplayContentLocked();
3950 final boolean changed = displayContent.updateRotationUnchecked(
3951 false /* inTransaction */);
3953 mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
3960 private void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
3961 if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked:"
3962 + " alwaysSendConfiguration=" + alwaysSendConfiguration
3963 + " forceRelayout=" + forceRelayout);
3965 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation");
3967 long origId = Binder.clearCallingIdentity();
3970 // TODO(multi-display): Update rotation for different displays separately.
3971 final boolean rotationChanged;
3972 final int displayId;
3973 synchronized (mWindowMap) {
3974 final DisplayContent displayContent = getDefaultDisplayContentLocked();
3975 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display");
3976 rotationChanged = displayContent.updateRotationUnchecked(
3977 false /* inTransaction */);
3978 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
3979 if (!rotationChanged || forceRelayout) {
3980 displayContent.setLayoutNeeded();
3981 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
3982 "updateRotation: performSurfacePlacement");
3983 mWindowPlacerLocked.performSurfacePlacement();
3984 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
3986 displayId = displayContent.getDisplayId();
3989 if (rotationChanged || alwaysSendConfiguration) {
3990 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: sendNewConfiguration");
3991 sendNewConfiguration(displayId);
3992 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
3995 Binder.restoreCallingIdentity(origId);
3996 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
4001 public int getDefaultDisplayRotation() {
4002 synchronized (mWindowMap) {
4003 return getDefaultDisplayContentLocked().getRotation();
4008 public boolean isRotationFrozen() {
4009 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
4013 public int watchRotation(IRotationWatcher watcher, int displayId) {
4014 final IBinder watcherBinder = watcher.asBinder();
4015 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
4017 public void binderDied() {
4018 synchronized (mWindowMap) {
4019 for (int i=0; i<mRotationWatchers.size(); i++) {
4020 if (watcherBinder == mRotationWatchers.get(i).mWatcher.asBinder()) {
4021 RotationWatcher removed = mRotationWatchers.remove(i);
4022 IBinder binder = removed.mWatcher.asBinder();
4023 if (binder != null) {
4024 binder.unlinkToDeath(this, 0);
4033 synchronized (mWindowMap) {
4035 watcher.asBinder().linkToDeath(dr, 0);
4036 mRotationWatchers.add(new RotationWatcher(watcher, dr, displayId));
4037 } catch (RemoteException e) {
4038 // Client died, no cleanup needed.
4041 return getDefaultDisplayRotation();
4046 public void removeRotationWatcher(IRotationWatcher watcher) {
4047 final IBinder watcherBinder = watcher.asBinder();
4048 synchronized (mWindowMap) {
4049 for (int i=0; i<mRotationWatchers.size(); i++) {
4050 RotationWatcher rotationWatcher = mRotationWatchers.get(i);
4051 if (watcherBinder == rotationWatcher.mWatcher.asBinder()) {
4052 RotationWatcher removed = mRotationWatchers.remove(i);
4053 IBinder binder = removed.mWatcher.asBinder();
4054 if (binder != null) {
4055 binder.unlinkToDeath(removed.mDeathRecipient, 0);
4064 public boolean registerWallpaperVisibilityListener(IWallpaperVisibilityListener listener,
4066 synchronized (mWindowMap) {
4067 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
4068 if (displayContent == null) {
4069 throw new IllegalArgumentException("Trying to register visibility event "
4070 + "for invalid display: " + displayId);
4072 mWallpaperVisibilityListeners.registerWallpaperVisibilityListener(listener, displayId);
4073 return displayContent.mWallpaperController.isWallpaperVisible();
4078 public void unregisterWallpaperVisibilityListener(IWallpaperVisibilityListener listener,
4080 synchronized (mWindowMap) {
4081 mWallpaperVisibilityListeners
4082 .unregisterWallpaperVisibilityListener(listener, displayId);
4087 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
4088 * theme attribute) on devices that feature a physical options menu key attempt to position
4089 * their menu panel window along the edge of the screen nearest the physical menu key.
4090 * This lowers the travel distance between invoking the menu panel and selecting
4093 * This method helps control where that menu is placed. Its current implementation makes
4094 * assumptions about the menu key and its relationship to the screen based on whether
4095 * the device's natural orientation is portrait (width < height) or landscape.
4097 * The menu key is assumed to be located along the bottom edge of natural-portrait
4098 * devices and along the right edge of natural-landscape devices. If these assumptions
4099 * do not hold for the target device, this method should be changed to reflect that.
4101 * @return A {@link Gravity} value for placing the options menu window
4104 public int getPreferredOptionsPanelGravity() {
4105 synchronized (mWindowMap) {
4106 // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
4107 final DisplayContent displayContent = getDefaultDisplayContentLocked();
4108 final int rotation = displayContent.getRotation();
4109 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
4110 // On devices with a natural orientation of portrait
4113 case Surface.ROTATION_0:
4114 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
4115 case Surface.ROTATION_90:
4116 return Gravity.RIGHT | Gravity.BOTTOM;
4117 case Surface.ROTATION_180:
4118 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
4119 case Surface.ROTATION_270:
4120 return Gravity.START | Gravity.BOTTOM;
4124 // On devices with a natural orientation of landscape
4127 case Surface.ROTATION_0:
4128 return Gravity.RIGHT | Gravity.BOTTOM;
4129 case Surface.ROTATION_90:
4130 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
4131 case Surface.ROTATION_180:
4132 return Gravity.START | Gravity.BOTTOM;
4133 case Surface.ROTATION_270:
4134 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
4140 * Starts the view server on the specified port.
4142 * @param port The port to listener to.
4144 * @return True if the server was successfully started, false otherwise.
4146 * @see com.android.server.wm.ViewServer
4147 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
4150 public boolean startViewServer(int port) {
4151 if (isSystemSecure()) {
4155 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
4163 if (mViewServer != null) {
4164 if (!mViewServer.isRunning()) {
4166 return mViewServer.start();
4167 } catch (IOException e) {
4168 Slog.w(TAG_WM, "View server did not start");
4175 mViewServer = new ViewServer(this, port);
4176 return mViewServer.start();
4177 } catch (IOException e) {
4178 Slog.w(TAG_WM, "View server did not start");
4183 private boolean isSystemSecure() {
4184 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
4185 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
4189 * Stops the view server if it exists.
4191 * @return True if the server stopped, false if it wasn't started or
4192 * couldn't be stopped.
4194 * @see com.android.server.wm.ViewServer
4197 public boolean stopViewServer() {
4198 if (isSystemSecure()) {
4202 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
4206 if (mViewServer != null) {
4207 return mViewServer.stop();
4213 * Indicates whether the view server is running.
4215 * @return True if the server is running, false otherwise.
4217 * @see com.android.server.wm.ViewServer
4220 public boolean isViewServerRunning() {
4221 if (isSystemSecure()) {
4225 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
4229 return mViewServer != null && mViewServer.isRunning();
4233 * Lists all available windows in the system. The listing is written in the specified Socket's
4234 * output stream with the following syntax: windowHashCodeInHexadecimal windowName
4235 * Each line of the output represents a different window.
4237 * @param client The remote client to send the listing to.
4238 * @return false if an error occurred, true otherwise.
4240 boolean viewServerListWindows(Socket client) {
4241 if (isSystemSecure()) {
4245 boolean result = true;
4247 final ArrayList<WindowState> windows = new ArrayList();
4248 synchronized (mWindowMap) {
4249 mRoot.forAllWindows(w -> {
4251 }, false /* traverseTopToBottom */);
4254 BufferedWriter out = null;
4256 // Any uncaught exception will crash the system process
4258 OutputStream clientStream = client.getOutputStream();
4259 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
4261 final int count = windows.size();
4262 for (int i = 0; i < count; i++) {
4263 final WindowState w = windows.get(i);
4264 out.write(Integer.toHexString(System.identityHashCode(w)));
4266 out.append(w.mAttrs.getTitle());
4270 out.write("DONE.\n");
4272 } catch (Exception e) {
4278 } catch (IOException e) {
4287 // TODO(multidisplay): Extend to multiple displays.
4289 * Returns the focused window in the following format:
4290 * windowHashCodeInHexadecimal windowName
4292 * @param client The remote client to send the listing to.
4293 * @return False if an error occurred, true otherwise.
4295 boolean viewServerGetFocusedWindow(Socket client) {
4296 if (isSystemSecure()) {
4300 boolean result = true;
4302 WindowState focusedWindow = getFocusedWindow();
4304 BufferedWriter out = null;
4306 // Any uncaught exception will crash the system process
4308 OutputStream clientStream = client.getOutputStream();
4309 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
4311 if(focusedWindow != null) {
4312 out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
4314 out.append(focusedWindow.mAttrs.getTitle());
4318 } catch (Exception e) {
4324 } catch (IOException e) {
4334 * Sends a command to a target window. The result of the command, if any, will be
4335 * written in the output stream of the specified socket.
4337 * The parameters must follow this syntax:
4338 * windowHashcode extra
4340 * Where XX is the length in characeters of the windowTitle.
4342 * The first parameter is the target window. The window with the specified hashcode
4343 * will be the target. If no target can be found, nothing happens. The extra parameters
4344 * will be delivered to the target window and as parameters to the command itself.
4346 * @param client The remote client to sent the result, if any, to.
4347 * @param command The command to execute.
4348 * @param parameters The command parameters.
4350 * @return True if the command was successfully delivered, false otherwise. This does
4351 * not indicate whether the command itself was successful.
4353 boolean viewServerWindowCommand(Socket client, String command, String parameters) {
4354 if (isSystemSecure()) {
4358 boolean success = true;
4360 Parcel reply = null;
4362 BufferedWriter out = null;
4364 // Any uncaught exception will crash the system process
4366 // Find the hashcode of the window
4367 int index = parameters.indexOf(' ');
4369 index = parameters.length();
4371 final String code = parameters.substring(0, index);
4372 int hashCode = (int) Long.parseLong(code, 16);
4374 // Extract the command's parameter after the window description
4375 if (index < parameters.length()) {
4376 parameters = parameters.substring(index + 1);
4381 final WindowState window = findWindow(hashCode);
4382 if (window == null) {
4386 data = Parcel.obtain();
4387 data.writeInterfaceToken("android.view.IWindow");
4388 data.writeString(command);
4389 data.writeString(parameters);
4391 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
4393 reply = Parcel.obtain();
4395 final IBinder binder = window.mClient.asBinder();
4396 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
4397 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
4399 reply.readException();
4401 if (!client.isOutputShutdown()) {
4402 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
4403 out.write("DONE\n");
4407 } catch (Exception e) {
4408 Slog.w(TAG_WM, "Could not send command " + command + " with parameters " + parameters, e);
4414 if (reply != null) {
4420 } catch (IOException e) {
4429 public void addWindowChangeListener(WindowChangeListener listener) {
4430 synchronized(mWindowMap) {
4431 mWindowChangeListeners.add(listener);
4435 public void removeWindowChangeListener(WindowChangeListener listener) {
4436 synchronized(mWindowMap) {
4437 mWindowChangeListeners.remove(listener);
4441 private void notifyWindowsChanged() {
4442 WindowChangeListener[] windowChangeListeners;
4443 synchronized(mWindowMap) {
4444 if(mWindowChangeListeners.isEmpty()) {
4447 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
4448 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
4450 int N = windowChangeListeners.length;
4451 for(int i = 0; i < N; i++) {
4452 windowChangeListeners[i].windowsChanged();
4456 private void notifyFocusChanged() {
4457 WindowChangeListener[] windowChangeListeners;
4458 synchronized(mWindowMap) {
4459 if(mWindowChangeListeners.isEmpty()) {
4462 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
4463 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
4465 int N = windowChangeListeners.length;
4466 for(int i = 0; i < N; i++) {
4467 windowChangeListeners[i].focusChanged();
4471 private WindowState findWindow(int hashCode) {
4472 if (hashCode == -1) {
4473 // TODO(multidisplay): Extend to multiple displays.
4474 return getFocusedWindow();
4477 synchronized (mWindowMap) {
4478 return mRoot.getWindow((w) -> System.identityHashCode(w) == hashCode);
4483 * Instruct the Activity Manager to fetch and update the current display's configuration and
4484 * broadcast them to config-changed listeners if appropriate.
4485 * NOTE: Can't be called with the window manager lock held since it call into activity manager.
4487 void sendNewConfiguration(int displayId) {
4489 final boolean configUpdated = mActivityManager.updateDisplayOverrideConfiguration(
4490 null /* values */, displayId);
4491 if (!configUpdated) {
4492 // Something changed (E.g. device rotation), but no configuration update is needed.
4493 // E.g. changing device rotation by 180 degrees. Go ahead and perform surface
4494 // placement to unfreeze the display since we froze it when the rotation was updated
4495 // in DisplayContent#updateRotationUnchecked.
4496 synchronized (mWindowMap) {
4497 if (mWaitingForConfig) {
4498 mWaitingForConfig = false;
4499 mLastFinishedFreezeSource = "config-unchanged";
4500 final DisplayContent dc = mRoot.getDisplayContent(displayId);
4502 dc.setLayoutNeeded();
4504 mWindowPlacerLocked.performSurfacePlacement();
4508 } catch (RemoteException e) {
4512 public Configuration computeNewConfiguration(int displayId) {
4513 synchronized (mWindowMap) {
4514 return computeNewConfigurationLocked(displayId);
4518 private Configuration computeNewConfigurationLocked(int displayId) {
4519 if (!mDisplayReady) {
4522 final Configuration config = new Configuration();
4523 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
4524 displayContent.computeScreenConfiguration(config);
4528 void notifyHardKeyboardStatusChange() {
4529 final boolean available;
4530 final WindowManagerInternal.OnHardKeyboardStatusChangeListener listener;
4531 synchronized (mWindowMap) {
4532 listener = mHardKeyboardStatusChangeListener;
4533 available = mHardKeyboardAvailable;
4535 if (listener != null) {
4536 listener.onHardKeyboardStatusChange(available);
4540 boolean startMovingTask(IWindow window, float startX, float startY) {
4541 WindowState win = null;
4542 synchronized (mWindowMap) {
4543 win = windowForClientLocked(null, window, false);
4544 // win shouldn't be null here, pass it down to startPositioningLocked
4545 // to get warning if it's null.
4546 if (!startPositioningLocked(
4547 win, false /*resize*/, false /*preserveOrientation*/, startX, startY)) {
4552 mActivityManager.setFocusedTask(win.getTask().mTaskId);
4553 } catch(RemoteException e) {}
4557 private void handleTapOutsideTask(DisplayContent displayContent, int x, int y) {
4559 synchronized (mWindowMap) {
4560 final Task task = displayContent.findTaskForResizePoint(x, y);
4562 if (!startPositioningLocked(task.getTopVisibleAppMainWindow(), true /*resize*/,
4563 task.preserveOrientationOnResize(), x, y)) {
4566 taskId = task.mTaskId;
4568 taskId = displayContent.taskIdFromPoint(x, y);
4573 mActivityManager.setFocusedTask(taskId);
4574 } catch(RemoteException e) {}
4578 private boolean startPositioningLocked(WindowState win, boolean resize,
4579 boolean preserveOrientation, float startX, float startY) {
4580 if (DEBUG_TASK_POSITIONING)
4581 Slog.d(TAG_WM, "startPositioningLocked: "
4582 + "win=" + win + ", resize=" + resize + ", preserveOrientation="
4583 + preserveOrientation + ", {" + startX + ", " + startY + "}");
4585 if (win == null || win.getAppToken() == null) {
4586 Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win);
4589 if (win.mInputChannel == null) {
4590 Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, "
4591 + " probably being removed");
4595 final DisplayContent displayContent = win.getDisplayContent();
4596 if (displayContent == null) {
4597 Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win);
4601 Display display = displayContent.getDisplay();
4602 mTaskPositioner = new TaskPositioner(this);
4603 mTaskPositioner.register(display);
4604 mInputMonitor.updateInputWindowsLw(true /*force*/);
4606 // We need to grab the touch focus so that the touch events during the
4607 // resizing/scrolling are not sent to the app. 'win' is the main window
4608 // of the app, it may not have focus since there might be other windows
4609 // on top (eg. a dialog window).
4610 WindowState transferFocusFromWin = win;
4611 if (mCurrentFocus != null && mCurrentFocus != win
4612 && mCurrentFocus.mAppToken == win.mAppToken) {
4613 transferFocusFromWin = mCurrentFocus;
4615 if (!mInputManager.transferTouchFocus(
4616 transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) {
4617 Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
4618 mTaskPositioner.unregister();
4619 mTaskPositioner = null;
4620 mInputMonitor.updateInputWindowsLw(true /*force*/);
4624 mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY);
4628 private void finishPositioning() {
4629 if (DEBUG_TASK_POSITIONING) {
4630 Slog.d(TAG_WM, "finishPositioning");
4632 synchronized (mWindowMap) {
4633 if (mTaskPositioner != null) {
4634 mTaskPositioner.unregister();
4635 mTaskPositioner = null;
4636 mInputMonitor.updateInputWindowsLw(true /*force*/);
4641 // -------------------------------------------------------------
4643 // -------------------------------------------------------------
4645 IBinder prepareDragSurface(IWindow window, SurfaceSession session,
4646 int flags, int width, int height, Surface outSurface) {
4648 Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height
4649 + " flags=" + Integer.toHexString(flags) + " win=" + window
4650 + " asbinder=" + window.asBinder());
4653 final int callerPid = Binder.getCallingPid();
4654 final int callerUid = Binder.getCallingUid();
4655 final long origId = Binder.clearCallingIdentity();
4656 IBinder token = null;
4659 synchronized (mWindowMap) {
4661 if (mDragState == null) {
4662 // TODO(multi-display): support other displays
4663 final DisplayContent displayContent = getDefaultDisplayContentLocked();
4664 final Display display = displayContent.getDisplay();
4666 SurfaceControl surface = new SurfaceControl(session, "drag surface",
4667 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
4668 surface.setLayerStack(display.getLayerStack());
4670 if ((flags & View.DRAG_FLAG_OPAQUE) == 0) {
4671 alpha = DRAG_SHADOW_ALPHA_TRANSPARENT;
4673 surface.setAlpha(alpha);
4675 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " DRAG "
4676 + surface + ": CREATE");
4677 outSurface.copyFrom(surface);
4678 final IBinder winBinder = window.asBinder();
4679 token = new Binder();
4680 mDragState = new DragState(this, token, surface, flags, winBinder);
4681 mDragState.mPid = callerPid;
4682 mDragState.mUid = callerUid;
4683 mDragState.mOriginalAlpha = alpha;
4684 token = mDragState.mToken = new Binder();
4686 // 5 second timeout for this window to actually begin the drag
4687 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
4688 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
4689 mH.sendMessageDelayed(msg, 5000);
4691 Slog.w(TAG_WM, "Drag already in progress");
4693 } catch (OutOfResourcesException e) {
4694 Slog.e(TAG_WM, "Can't allocate drag surface w=" + width + " h=" + height, e);
4695 if (mDragState != null) {
4702 Binder.restoreCallingIdentity(origId);
4708 // -------------------------------------------------------------
4709 // Input Events and Focus Management
4710 // -------------------------------------------------------------
4712 final InputMonitor mInputMonitor = new InputMonitor(this);
4713 private boolean mEventDispatchingEnabled;
4716 public void setEventDispatching(boolean enabled) {
4717 if (!checkCallingPermission(MANAGE_APP_TOKENS, "setEventDispatching()")) {
4718 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4721 synchronized (mWindowMap) {
4722 mEventDispatchingEnabled = enabled;
4723 if (mDisplayEnabled) {
4724 mInputMonitor.setEventDispatchingLw(enabled);
4729 private WindowState getFocusedWindow() {
4730 synchronized (mWindowMap) {
4731 return getFocusedWindowLocked();
4735 private WindowState getFocusedWindowLocked() {
4736 return mCurrentFocus;
4739 TaskStack getImeFocusStackLocked() {
4740 // Don't use mCurrentFocus.getStack() because it returns home stack for system windows.
4741 // Also don't use mInputMethodTarget's stack, because some window with FLAG_NOT_FOCUSABLE
4742 // and FLAG_ALT_FOCUSABLE_IM flags both set might be set to IME target so they're moved
4743 // to make room for IME, but the window is not the focused window that's taking input.
4744 return (mFocusedApp != null && mFocusedApp.getTask() != null) ?
4745 mFocusedApp.getTask().mStack : null;
4748 public boolean detectSafeMode() {
4749 if (!mInputMonitor.waitForInputDevicesReady(
4750 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
4751 Slog.w(TAG_WM, "Devices still not ready after waiting "
4752 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
4753 + " milliseconds before attempting to detect safe mode.");
4756 if (Settings.Global.getInt(
4757 mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) {
4761 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
4762 KeyEvent.KEYCODE_MENU);
4763 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
4764 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
4765 KeyEvent.KEYCODE_DPAD_CENTER);
4766 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
4767 InputManagerService.BTN_MOUSE);
4768 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
4769 KeyEvent.KEYCODE_VOLUME_DOWN);
4770 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
4771 || volumeDownState > 0;
4773 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0
4774 || SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) != 0) {
4776 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
4778 } catch (IllegalArgumentException e) {
4781 Log.i(TAG_WM, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
4782 + " dpad=" + dpadState + " trackball=" + trackballState + ")");
4783 SystemProperties.set(ShutdownThread.RO_SAFEMODE_PROPERTY, "1");
4785 Log.i(TAG_WM, "SAFE MODE not enabled");
4787 mPolicy.setSafeMode(mSafeMode);
4791 public void displayReady() {
4792 for (Display display : mDisplays) {
4793 displayReady(display.getDisplayId());
4796 synchronized(mWindowMap) {
4797 final DisplayContent displayContent = getDefaultDisplayContentLocked();
4798 if (mMaxUiWidth > 0) {
4799 displayContent.setMaxUiWidth(mMaxUiWidth);
4801 readForcedDisplayPropertiesLocked(displayContent);
4802 mDisplayReady = true;
4806 mActivityManager.updateConfiguration(null);
4807 } catch (RemoteException e) {
4810 synchronized(mWindowMap) {
4811 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
4812 PackageManager.FEATURE_TOUCHSCREEN);
4813 configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
4817 mActivityManager.updateConfiguration(null);
4818 } catch (RemoteException e) {
4821 updateCircularDisplayMaskIfNeeded();
4824 private void displayReady(int displayId) {
4825 synchronized(mWindowMap) {
4826 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
4827 if (displayContent != null) {
4828 mAnimator.addDisplayLocked(displayId);
4829 displayContent.initializeDisplayBaseInfo();
4834 public void systemReady() {
4835 mPolicy.systemReady();
4836 mTaskSnapshotController.systemReady();
4837 mHasWideColorGamutSupport = queryWideColorGamutSupport();
4840 private static boolean queryWideColorGamutSupport() {
4842 ISurfaceFlingerConfigs surfaceFlinger = ISurfaceFlingerConfigs.getService();
4843 OptionalBool hasWideColor = surfaceFlinger.hasWideColorDisplay();
4844 if (hasWideColor != null) {
4845 return hasWideColor.value;
4847 } catch (RemoteException e) {
4848 // Ignore, we're in big trouble if we can't talk to SurfaceFlinger's config store
4853 // -------------------------------------------------------------
4855 // -------------------------------------------------------------
4857 final class H extends android.os.Handler {
4858 public static final int REPORT_FOCUS_CHANGE = 2;
4859 public static final int REPORT_LOSING_FOCUS = 3;
4860 public static final int WINDOW_FREEZE_TIMEOUT = 11;
4862 public static final int APP_TRANSITION_TIMEOUT = 13;
4863 public static final int PERSIST_ANIMATION_SCALE = 14;
4864 public static final int FORCE_GC = 15;
4865 public static final int ENABLE_SCREEN = 16;
4866 public static final int APP_FREEZE_TIMEOUT = 17;
4867 public static final int SEND_NEW_CONFIGURATION = 18;
4868 public static final int REPORT_WINDOWS_CHANGE = 19;
4869 public static final int DRAG_START_TIMEOUT = 20;
4870 public static final int DRAG_END_TIMEOUT = 21;
4871 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
4872 public static final int BOOT_TIMEOUT = 23;
4873 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
4874 public static final int SHOW_STRICT_MODE_VIOLATION = 25;
4875 public static final int DO_ANIMATION_CALLBACK = 26;
4877 public static final int CLIENT_FREEZE_TIMEOUT = 30;
4878 public static final int TAP_OUTSIDE_TASK = 31;
4879 public static final int NOTIFY_ACTIVITY_DRAWN = 32;
4881 public static final int ALL_WINDOWS_DRAWN = 33;
4883 public static final int NEW_ANIMATOR_SCALE = 34;
4885 public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35;
4886 public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36;
4888 public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37;
4889 public static final int RESET_ANR_MESSAGE = 38;
4890 public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39;
4892 public static final int FINISH_TASK_POSITIONING = 40;
4894 public static final int UPDATE_DOCKED_STACK_DIVIDER = 41;
4896 public static final int TEAR_DOWN_DRAG_AND_DROP_INPUT = 44;
4898 public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
4900 public static final int NOTIFY_APP_TRANSITION_STARTING = 47;
4901 public static final int NOTIFY_APP_TRANSITION_CANCELLED = 48;
4902 public static final int NOTIFY_APP_TRANSITION_FINISHED = 49;
4903 public static final int UPDATE_ANIMATION_SCALE = 51;
4904 public static final int WINDOW_HIDE_TIMEOUT = 52;
4905 public static final int NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED = 53;
4906 public static final int SEAMLESS_ROTATION_TIMEOUT = 54;
4907 public static final int RESTORE_POINTER_ICON = 55;
4908 public static final int NOTIFY_KEYGUARD_FLAGS_CHANGED = 56;
4909 public static final int NOTIFY_KEYGUARD_TRUSTED_CHANGED = 57;
4910 public static final int SET_HAS_OVERLAY_UI = 58;
4911 public static final int RECOMPUTE_FOCUS = 61;
4914 * Used to denote that an integer field in a message will not be used.
4916 public static final int UNUSED = 0;
4919 public void handleMessage(Message msg) {
4920 if (DEBUG_WINDOW_TRACE) {
4921 Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what);
4924 case REPORT_FOCUS_CHANGE: {
4925 WindowState lastFocus;
4926 WindowState newFocus;
4928 AccessibilityController accessibilityController = null;
4930 synchronized(mWindowMap) {
4931 // TODO(multidisplay): Accessibility supported only of default desiplay.
4932 if (mAccessibilityController != null && getDefaultDisplayContentLocked()
4933 .getDisplayId() == DEFAULT_DISPLAY) {
4934 accessibilityController = mAccessibilityController;
4937 lastFocus = mLastFocus;
4938 newFocus = mCurrentFocus;
4939 if (lastFocus == newFocus) {
4940 // Focus is not changing, so nothing to do.
4943 mLastFocus = newFocus;
4944 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Focus moving from " + lastFocus +
4946 if (newFocus != null && lastFocus != null
4947 && !newFocus.isDisplayedLw()) {
4948 //Slog.i(TAG_WM, "Delaying loss of focus...");
4949 mLosingFocus.add(lastFocus);
4954 // First notify the accessibility manager for the change so it has
4955 // the windows before the newly focused one starts firing eventgs.
4956 if (accessibilityController != null) {
4957 accessibilityController.onWindowFocusChangedNotLocked();
4960 //System.out.println("Changing focus from " + lastFocus
4961 // + " to " + newFocus);
4962 if (newFocus != null) {
4963 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Gaining focus: " + newFocus);
4964 newFocus.reportFocusChangedSerialized(true, mInTouchMode);
4965 notifyFocusChanged();
4968 if (lastFocus != null) {
4969 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing focus: " + lastFocus);
4970 lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
4974 case REPORT_LOSING_FOCUS: {
4975 ArrayList<WindowState> losers;
4977 synchronized(mWindowMap) {
4978 losers = mLosingFocus;
4979 mLosingFocus = new ArrayList<WindowState>();
4982 final int N = losers.size();
4983 for (int i=0; i<N; i++) {
4984 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing delayed focus: " +
4986 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
4990 case WINDOW_FREEZE_TIMEOUT: {
4991 // TODO(multidisplay): Can non-default displays rotate?
4992 synchronized (mWindowMap) {
4993 getDefaultDisplayContentLocked().onWindowFreezeTimeout();
4998 case APP_TRANSITION_TIMEOUT: {
4999 synchronized (mWindowMap) {
5000 if (mAppTransition.isTransitionSet() || !mOpeningApps.isEmpty()
5001 || !mClosingApps.isEmpty()) {
5002 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "*** APP TRANSITION TIMEOUT."
5003 + " isTransitionSet()=" + mAppTransition.isTransitionSet()
5004 + " mOpeningApps.size()=" + mOpeningApps.size()
5005 + " mClosingApps.size()=" + mClosingApps.size());
5006 mAppTransition.setTimeout();
5007 mWindowPlacerLocked.performSurfacePlacement();
5013 case PERSIST_ANIMATION_SCALE: {
5014 Settings.Global.putFloat(mContext.getContentResolver(),
5015 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
5016 Settings.Global.putFloat(mContext.getContentResolver(),
5017 Settings.Global.TRANSITION_ANIMATION_SCALE,
5018 mTransitionAnimationScaleSetting);
5019 Settings.Global.putFloat(mContext.getContentResolver(),
5020 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting);
5024 case UPDATE_ANIMATION_SCALE: {
5025 @UpdateAnimationScaleMode
5026 final int mode = msg.arg1;
5028 case WINDOW_ANIMATION_SCALE: {
5029 mWindowAnimationScaleSetting = Settings.Global.getFloat(
5030 mContext.getContentResolver(),
5031 Settings.Global.WINDOW_ANIMATION_SCALE,
5032 mWindowAnimationScaleSetting);
5035 case TRANSITION_ANIMATION_SCALE: {
5036 mTransitionAnimationScaleSetting = Settings.Global.getFloat(
5037 mContext.getContentResolver(),
5038 Settings.Global.TRANSITION_ANIMATION_SCALE,
5039 mTransitionAnimationScaleSetting);
5042 case ANIMATION_DURATION_SCALE: {
5043 mAnimatorDurationScaleSetting = Settings.Global.getFloat(
5044 mContext.getContentResolver(),
5045 Settings.Global.ANIMATOR_DURATION_SCALE,
5046 mAnimatorDurationScaleSetting);
5047 dispatchNewAnimatorScaleLocked(null);
5055 synchronized (mWindowMap) {
5056 // Since we're holding both mWindowMap and mAnimator we don't need to
5057 // hold mAnimator.mLayoutToAnim.
5058 if (mAnimator.isAnimating() || mAnimator.isAnimationScheduled()) {
5059 // If we are animating, don't do the gc now but
5060 // delay a bit so we don't interrupt the animation.
5061 sendEmptyMessageDelayed(H.FORCE_GC, 2000);
5064 // If we are currently rotating the display, it will
5065 // schedule a new message when done.
5066 if (mDisplayFrozen) {
5070 Runtime.getRuntime().gc();
5074 case ENABLE_SCREEN: {
5075 performEnableScreen();
5079 case APP_FREEZE_TIMEOUT: {
5080 synchronized (mWindowMap) {
5081 Slog.w(TAG_WM, "App freeze timeout expired.");
5082 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
5083 for (int i = mAppFreezeListeners.size() - 1; i >=0 ; --i) {
5084 mAppFreezeListeners.get(i).onAppFreezeTimeout();
5090 case CLIENT_FREEZE_TIMEOUT: {
5091 synchronized (mWindowMap) {
5092 if (mClientFreezingScreen) {
5093 mClientFreezingScreen = false;
5094 mLastFinishedFreezeSource = "client-timeout";
5095 stopFreezingDisplayLocked();
5101 case SEND_NEW_CONFIGURATION: {
5102 removeMessages(SEND_NEW_CONFIGURATION, msg.obj);
5103 final int displayId = (Integer) msg.obj;
5104 if (mRoot.getDisplayContent(displayId) != null) {
5105 sendNewConfiguration(displayId);
5107 // Message could come after display has already been removed.
5108 if (DEBUG_CONFIGURATION) {
5109 Slog.w(TAG, "Trying to send configuration to non-existing displayId="
5116 case REPORT_WINDOWS_CHANGE: {
5117 if (mWindowsChanged) {
5118 synchronized (mWindowMap) {
5119 mWindowsChanged = false;
5121 notifyWindowsChanged();
5126 case DRAG_START_TIMEOUT: {
5127 IBinder win = (IBinder)msg.obj;
5129 Slog.w(TAG_WM, "Timeout starting drag by win " + win);
5131 synchronized (mWindowMap) {
5132 // !!! TODO: ANR the app that has failed to start the drag in time
5133 if (mDragState != null) {
5134 mDragState.unregister();
5142 case DRAG_END_TIMEOUT: {
5143 IBinder win = (IBinder)msg.obj;
5145 Slog.w(TAG_WM, "Timeout ending drag to win " + win);
5147 synchronized (mWindowMap) {
5148 // !!! TODO: ANR the drag-receiving app
5149 if (mDragState != null) {
5150 mDragState.mDragResult = false;
5151 mDragState.endDragLw();
5157 case TEAR_DOWN_DRAG_AND_DROP_INPUT: {
5158 if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ending; tearing down input channel");
5159 DragState.InputInterceptor interceptor = (DragState.InputInterceptor) msg.obj;
5160 if (interceptor != null) {
5161 synchronized (mWindowMap) {
5162 interceptor.tearDown();
5168 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
5169 notifyHardKeyboardStatusChange();
5173 case BOOT_TIMEOUT: {
5174 performBootTimeout();
5178 case WAITING_FOR_DRAWN_TIMEOUT: {
5179 Runnable callback = null;
5180 synchronized (mWindowMap) {
5181 Slog.w(TAG_WM, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
5182 mWaitingForDrawn.clear();
5183 callback = mWaitingForDrawnCallback;
5184 mWaitingForDrawnCallback = null;
5186 if (callback != null) {
5192 case SHOW_STRICT_MODE_VIOLATION: {
5193 showStrictModeViolation(msg.arg1, msg.arg2);
5197 case SHOW_CIRCULAR_DISPLAY_MASK: {
5198 showCircularMask(msg.arg1 == 1);
5202 case SHOW_EMULATOR_DISPLAY_OVERLAY: {
5203 showEmulatorDisplayOverlay();
5207 case DO_ANIMATION_CALLBACK: {
5209 ((IRemoteCallback)msg.obj).sendResult(null);
5210 } catch (RemoteException e) {
5215 case TAP_OUTSIDE_TASK: {
5216 handleTapOutsideTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
5220 case FINISH_TASK_POSITIONING: {
5221 finishPositioning();
5225 case NOTIFY_ACTIVITY_DRAWN:
5227 mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
5228 } catch (RemoteException e) {
5231 case ALL_WINDOWS_DRAWN: {
5233 synchronized (mWindowMap) {
5234 callback = mWaitingForDrawnCallback;
5235 mWaitingForDrawnCallback = null;
5237 if (callback != null) {
5242 case NEW_ANIMATOR_SCALE: {
5243 float scale = getCurrentAnimatorScale();
5244 ValueAnimator.setDurationScale(scale);
5245 Session session = (Session)msg.obj;
5246 if (session != null) {
5248 session.mCallback.onAnimatorScaleChanged(scale);
5249 } catch (RemoteException e) {
5252 ArrayList<IWindowSessionCallback> callbacks
5253 = new ArrayList<IWindowSessionCallback>();
5254 synchronized (mWindowMap) {
5255 for (int i=0; i<mSessions.size(); i++) {
5256 callbacks.add(mSessions.valueAt(i).mCallback);
5260 for (int i=0; i<callbacks.size(); i++) {
5262 callbacks.get(i).onAnimatorScaleChanged(scale);
5263 } catch (RemoteException e) {
5269 case CHECK_IF_BOOT_ANIMATION_FINISHED: {
5270 final boolean bootAnimationComplete;
5271 synchronized (mWindowMap) {
5272 if (DEBUG_BOOT) Slog.i(TAG_WM, "CHECK_IF_BOOT_ANIMATION_FINISHED:");
5273 bootAnimationComplete = checkBootAnimationCompleteLocked();
5275 if (bootAnimationComplete) {
5276 performEnableScreen();
5280 case RESET_ANR_MESSAGE: {
5281 synchronized (mWindowMap) {
5282 mLastANRState = null;
5284 mAmInternal.clearSavedANRState();
5287 case WALLPAPER_DRAW_PENDING_TIMEOUT: {
5288 synchronized (mWindowMap) {
5289 if (mRoot.mWallpaperController.processWallpaperDrawPendingTimeout()) {
5290 mWindowPlacerLocked.performSurfacePlacement();
5295 case UPDATE_DOCKED_STACK_DIVIDER: {
5296 synchronized (mWindowMap) {
5297 final DisplayContent displayContent = getDefaultDisplayContentLocked();
5298 displayContent.getDockedDividerController().reevaluateVisibility(false);
5299 displayContent.adjustForImeIfNeeded();
5303 case WINDOW_REPLACEMENT_TIMEOUT: {
5304 synchronized (mWindowMap) {
5305 for (int i = mWindowReplacementTimeouts.size() - 1; i >= 0; i--) {
5306 final AppWindowToken token = mWindowReplacementTimeouts.get(i);
5307 token.onWindowReplacementTimeout();
5309 mWindowReplacementTimeouts.clear();
5313 case NOTIFY_APP_TRANSITION_STARTING: {
5314 mAmInternal.notifyAppTransitionStarting((SparseIntArray) msg.obj,
5318 case NOTIFY_APP_TRANSITION_CANCELLED: {
5319 mAmInternal.notifyAppTransitionCancelled();
5322 case NOTIFY_APP_TRANSITION_FINISHED: {
5323 mAmInternal.notifyAppTransitionFinished();
5326 case WINDOW_HIDE_TIMEOUT: {
5327 final WindowState window = (WindowState) msg.obj;
5328 synchronized(mWindowMap) {
5329 // TODO: This is all about fixing b/21693547
5330 // where partially initialized Toasts get stuck
5331 // around and keep the screen on. We'd like
5332 // to just remove the toast...but this can cause clients
5333 // who miss the timeout due to normal circumstances (e.g.
5334 // running under debugger) to crash (b/29105388). The windows will
5335 // eventually be removed when the client process finishes.
5336 // The best we can do for now is remove the FLAG_KEEP_SCREEN_ON
5337 // and prevent the symptoms of b/21693547. Since apps don't
5338 // support windows being removed under them we hide the window
5339 // and it will be removed when the app dies.
5340 window.mAttrs.flags &= ~FLAG_KEEP_SCREEN_ON;
5341 window.hidePermanentlyLw();
5342 window.setDisplayLayoutNeeded();
5343 mWindowPlacerLocked.performSurfacePlacement();
5347 case NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED: {
5348 mAmInternal.notifyDockedStackMinimizedChanged(msg.arg1 == 1);
5351 case RESTORE_POINTER_ICON: {
5352 synchronized (mWindowMap) {
5353 restorePointerIconLocked((DisplayContent)msg.obj, msg.arg1, msg.arg2);
5357 case SEAMLESS_ROTATION_TIMEOUT: {
5358 // Rotation only supported on primary display.
5359 // TODO(multi-display)
5360 synchronized(mWindowMap) {
5361 final DisplayContent dc = getDefaultDisplayContentLocked();
5362 dc.onSeamlessRotationTimeout();
5366 case NOTIFY_KEYGUARD_FLAGS_CHANGED: {
5367 mAmInternal.notifyKeyguardFlagsChanged((Runnable) msg.obj);
5370 case NOTIFY_KEYGUARD_TRUSTED_CHANGED: {
5371 mAmInternal.notifyKeyguardTrustedChanged();
5374 case SET_HAS_OVERLAY_UI: {
5375 mAmInternal.setHasOverlayUi(msg.arg1, msg.arg2 == 1);
5378 case RECOMPUTE_FOCUS: {
5379 synchronized (mWindowMap) {
5380 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
5381 true /* updateInputWindows */);
5386 if (DEBUG_WINDOW_TRACE) {
5387 Slog.v(TAG_WM, "handleMessage: exit");
5392 void destroyPreservedSurfaceLocked() {
5393 for (int i = mDestroyPreservedSurface.size() - 1; i >= 0 ; i--) {
5394 final WindowState w = mDestroyPreservedSurface.get(i);
5395 w.mWinAnimator.destroyPreservedSurfaceLocked();
5397 mDestroyPreservedSurface.clear();
5400 void stopUsingSavedSurfaceLocked() {
5401 for (int i = mFinishedEarlyAnim.size() - 1; i >= 0 ; i--) {
5402 final AppWindowToken wtoken = mFinishedEarlyAnim.get(i);
5403 wtoken.stopUsingSavedSurfaceLocked();
5405 mFinishedEarlyAnim.clear();
5408 // -------------------------------------------------------------
5409 // IWindowManager API
5410 // -------------------------------------------------------------
5413 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
5414 IInputContext inputContext) {
5415 if (client == null) throw new IllegalArgumentException("null client");
5416 if (inputContext == null) throw new IllegalArgumentException("null inputContext");
5417 Session session = new Session(this, callback, client, inputContext);
5422 public boolean inputMethodClientHasFocus(IInputMethodClient client) {
5423 synchronized (mWindowMap) {
5424 // TODO: multi-display
5425 if (getDefaultDisplayContentLocked().inputMethodClientHasFocus(client)) {
5429 // Okay, how about this... what is the current focus?
5430 // It seems in some cases we may not have moved the IM
5431 // target window, such as when it was in a pop-up window,
5432 // so let's also look at the current focus. (An example:
5433 // go to Gmail, start searching so the keyboard goes up,
5434 // press home. Sometimes the IME won't go down.)
5435 // Would be nice to fix this more correctly, but it's
5436 // way at the end of a release, and this should be good enough.
5437 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
5438 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
5446 public void getInitialDisplaySize(int displayId, Point size) {
5447 synchronized (mWindowMap) {
5448 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5449 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
5450 size.x = displayContent.mInitialDisplayWidth;
5451 size.y = displayContent.mInitialDisplayHeight;
5457 public void getBaseDisplaySize(int displayId, Point size) {
5458 synchronized (mWindowMap) {
5459 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5460 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
5461 size.x = displayContent.mBaseDisplayWidth;
5462 size.y = displayContent.mBaseDisplayHeight;
5468 public void setForcedDisplaySize(int displayId, int width, int height) {
5469 if (mContext.checkCallingOrSelfPermission(
5470 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5471 PackageManager.PERMISSION_GRANTED) {
5472 throw new SecurityException("Must hold permission " +
5473 android.Manifest.permission.WRITE_SECURE_SETTINGS);
5475 if (displayId != DEFAULT_DISPLAY) {
5476 throw new IllegalArgumentException("Can only set the default display");
5478 final long ident = Binder.clearCallingIdentity();
5480 synchronized(mWindowMap) {
5481 // Set some sort of reasonable bounds on the size of the display that we
5482 // will try to emulate.
5483 final int MIN_WIDTH = 200;
5484 final int MIN_HEIGHT = 200;
5485 final int MAX_SCALE = 2;
5486 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5487 if (displayContent != null) {
5488 width = Math.min(Math.max(width, MIN_WIDTH),
5489 displayContent.mInitialDisplayWidth * MAX_SCALE);
5490 height = Math.min(Math.max(height, MIN_HEIGHT),
5491 displayContent.mInitialDisplayHeight * MAX_SCALE);
5492 setForcedDisplaySizeLocked(displayContent, width, height);
5493 Settings.Global.putString(mContext.getContentResolver(),
5494 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
5498 Binder.restoreCallingIdentity(ident);
5503 public void setForcedDisplayScalingMode(int displayId, int mode) {
5504 if (mContext.checkCallingOrSelfPermission(
5505 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5506 PackageManager.PERMISSION_GRANTED) {
5507 throw new SecurityException("Must hold permission " +
5508 android.Manifest.permission.WRITE_SECURE_SETTINGS);
5510 if (displayId != DEFAULT_DISPLAY) {
5511 throw new IllegalArgumentException("Can only set the default display");
5513 final long ident = Binder.clearCallingIdentity();
5515 synchronized(mWindowMap) {
5516 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5517 if (displayContent != null) {
5518 if (mode < 0 || mode > 1) {
5521 setForcedDisplayScalingModeLocked(displayContent, mode);
5522 Settings.Global.putInt(mContext.getContentResolver(),
5523 Settings.Global.DISPLAY_SCALING_FORCE, mode);
5527 Binder.restoreCallingIdentity(ident);
5531 private void setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode) {
5532 Slog.i(TAG_WM, "Using display scaling mode: " + (mode == 0 ? "auto" : "off"));
5533 displayContent.mDisplayScalingDisabled = (mode != 0);
5534 reconfigureDisplayLocked(displayContent);
5537 private void readForcedDisplayPropertiesLocked(final DisplayContent displayContent) {
5539 String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
5540 Settings.Global.DISPLAY_SIZE_FORCED);
5541 if (sizeStr == null || sizeStr.length() == 0) {
5542 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
5544 if (sizeStr != null && sizeStr.length() > 0) {
5545 final int pos = sizeStr.indexOf(',');
5546 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
5549 width = Integer.parseInt(sizeStr.substring(0, pos));
5550 height = Integer.parseInt(sizeStr.substring(pos+1));
5551 if (displayContent.mBaseDisplayWidth != width
5552 || displayContent.mBaseDisplayHeight != height) {
5553 Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
5554 displayContent.updateBaseDisplayMetrics(width, height,
5555 displayContent.mBaseDisplayDensity);
5557 } catch (NumberFormatException ex) {
5563 final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId);
5565 displayContent.mBaseDisplayDensity = density;
5568 // Display scaling mode.
5569 int mode = Settings.Global.getInt(mContext.getContentResolver(),
5570 Settings.Global.DISPLAY_SCALING_FORCE, 0);
5572 Slog.i(TAG_WM, "FORCED DISPLAY SCALING DISABLED");
5573 displayContent.mDisplayScalingDisabled = true;
5577 // displayContent must not be null
5578 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
5579 Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
5580 displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity);
5581 reconfigureDisplayLocked(displayContent);
5585 public void clearForcedDisplaySize(int displayId) {
5586 if (mContext.checkCallingOrSelfPermission(
5587 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5588 PackageManager.PERMISSION_GRANTED) {
5589 throw new SecurityException("Must hold permission " +
5590 android.Manifest.permission.WRITE_SECURE_SETTINGS);
5592 if (displayId != DEFAULT_DISPLAY) {
5593 throw new IllegalArgumentException("Can only set the default display");
5595 final long ident = Binder.clearCallingIdentity();
5597 synchronized(mWindowMap) {
5598 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5599 if (displayContent != null) {
5600 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
5601 displayContent.mInitialDisplayHeight);
5602 Settings.Global.putString(mContext.getContentResolver(),
5603 Settings.Global.DISPLAY_SIZE_FORCED, "");
5607 Binder.restoreCallingIdentity(ident);
5612 public int getInitialDisplayDensity(int displayId) {
5613 synchronized (mWindowMap) {
5614 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5615 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
5616 return displayContent.mInitialDisplayDensity;
5623 public int getBaseDisplayDensity(int displayId) {
5624 synchronized (mWindowMap) {
5625 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5626 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
5627 return displayContent.mBaseDisplayDensity;
5634 public void setForcedDisplayDensityForUser(int displayId, int density, int userId) {
5635 if (mContext.checkCallingOrSelfPermission(
5636 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5637 PackageManager.PERMISSION_GRANTED) {
5638 throw new SecurityException("Must hold permission " +
5639 android.Manifest.permission.WRITE_SECURE_SETTINGS);
5641 if (displayId != DEFAULT_DISPLAY) {
5642 throw new IllegalArgumentException("Can only set the default display");
5645 final int targetUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
5646 Binder.getCallingUid(), userId, false, true, "setForcedDisplayDensityForUser",
5648 final long ident = Binder.clearCallingIdentity();
5650 synchronized(mWindowMap) {
5651 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5652 if (displayContent != null && mCurrentUserId == targetUserId) {
5653 setForcedDisplayDensityLocked(displayContent, density);
5655 Settings.Secure.putStringForUser(mContext.getContentResolver(),
5656 Settings.Secure.DISPLAY_DENSITY_FORCED,
5657 Integer.toString(density), targetUserId);
5660 Binder.restoreCallingIdentity(ident);
5665 public void clearForcedDisplayDensityForUser(int displayId, int userId) {
5666 if (mContext.checkCallingOrSelfPermission(
5667 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5668 PackageManager.PERMISSION_GRANTED) {
5669 throw new SecurityException("Must hold permission " +
5670 android.Manifest.permission.WRITE_SECURE_SETTINGS);
5672 if (displayId != DEFAULT_DISPLAY) {
5673 throw new IllegalArgumentException("Can only set the default display");
5676 final int callingUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
5677 Binder.getCallingUid(), userId, false, true, "clearForcedDisplayDensityForUser",
5679 final long ident = Binder.clearCallingIdentity();
5681 synchronized(mWindowMap) {
5682 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5683 if (displayContent != null && mCurrentUserId == callingUserId) {
5684 setForcedDisplayDensityLocked(displayContent,
5685 displayContent.mInitialDisplayDensity);
5687 Settings.Secure.putStringForUser(mContext.getContentResolver(),
5688 Settings.Secure.DISPLAY_DENSITY_FORCED, "", callingUserId);
5691 Binder.restoreCallingIdentity(ident);
5696 * @param userId the ID of the user
5697 * @return the forced display density for the specified user, if set, or
5698 * {@code 0} if not set
5700 private int getForcedDisplayDensityForUserLocked(int userId) {
5701 String densityStr = Settings.Secure.getStringForUser(mContext.getContentResolver(),
5702 Settings.Secure.DISPLAY_DENSITY_FORCED, userId);
5703 if (densityStr == null || densityStr.length() == 0) {
5704 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
5706 if (densityStr != null && densityStr.length() > 0) {
5708 return Integer.parseInt(densityStr);
5709 } catch (NumberFormatException ex) {
5716 * Forces the given display to the use the specified density.
5718 * @param displayContent the display to modify
5719 * @param density the density in DPI to use
5721 private void setForcedDisplayDensityLocked(@NonNull DisplayContent displayContent,
5723 displayContent.mBaseDisplayDensity = density;
5724 reconfigureDisplayLocked(displayContent);
5727 void reconfigureDisplayLocked(@NonNull DisplayContent displayContent) {
5728 if (!mDisplayReady) {
5731 configureDisplayPolicyLocked(displayContent);
5732 displayContent.setLayoutNeeded();
5734 final int displayId = displayContent.getDisplayId();
5735 boolean configChanged = updateOrientationFromAppTokensLocked(false /* inTransaction */,
5737 final Configuration currentDisplayConfig = displayContent.getConfiguration();
5738 mTempConfiguration.setTo(currentDisplayConfig);
5739 displayContent.computeScreenConfiguration(mTempConfiguration);
5740 configChanged |= currentDisplayConfig.diff(mTempConfiguration) != 0;
5742 if (configChanged) {
5743 mWaitingForConfig = true;
5744 startFreezingDisplayLocked(false /* inTransaction */, 0 /* exitAnim */,
5745 0 /* enterAnim */, displayContent);
5746 mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
5749 mWindowPlacerLocked.performSurfacePlacement();
5752 void configureDisplayPolicyLocked(DisplayContent displayContent) {
5753 mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
5754 displayContent.mBaseDisplayWidth,
5755 displayContent.mBaseDisplayHeight,
5756 displayContent.mBaseDisplayDensity);
5758 DisplayInfo displayInfo = displayContent.getDisplayInfo();
5759 mPolicy.setDisplayOverscan(displayContent.getDisplay(),
5760 displayInfo.overscanLeft, displayInfo.overscanTop,
5761 displayInfo.overscanRight, displayInfo.overscanBottom);
5765 * Get an array with display ids ordered by focus priority - last items should be given
5766 * focus first. Sparse array just maps position to displayId.
5768 // TODO: Maintain display list in focus order in ActivityManager and remove this call.
5769 public void getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder) {
5770 synchronized(mWindowMap) {
5771 mRoot.getDisplaysInFocusOrder(displaysInFocusOrder);
5776 public void setOverscan(int displayId, int left, int top, int right, int bottom) {
5777 if (mContext.checkCallingOrSelfPermission(
5778 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5779 PackageManager.PERMISSION_GRANTED) {
5780 throw new SecurityException("Must hold permission " +
5781 android.Manifest.permission.WRITE_SECURE_SETTINGS);
5783 final long ident = Binder.clearCallingIdentity();
5785 synchronized(mWindowMap) {
5786 DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5787 if (displayContent != null) {
5788 setOverscanLocked(displayContent, left, top, right, bottom);
5792 Binder.restoreCallingIdentity(ident);
5796 private void setOverscanLocked(DisplayContent displayContent,
5797 int left, int top, int right, int bottom) {
5798 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5799 displayInfo.overscanLeft = left;
5800 displayInfo.overscanTop = top;
5801 displayInfo.overscanRight = right;
5802 displayInfo.overscanBottom = bottom;
5804 mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, displayInfo.name, left, top,
5806 mDisplaySettings.writeSettingsLocked();
5808 reconfigureDisplayLocked(displayContent);
5811 // -------------------------------------------------------------
5813 // -------------------------------------------------------------
5815 final WindowState windowForClientLocked(Session session, IWindow client, boolean throwOnError) {
5816 return windowForClientLocked(session, client.asBinder(), throwOnError);
5819 final WindowState windowForClientLocked(Session session, IBinder client, boolean throwOnError) {
5820 WindowState win = mWindowMap.get(client);
5821 if (localLOGV) Slog.v(TAG_WM, "Looking up client " + client + ": " + win);
5824 throw new IllegalArgumentException(
5825 "Requested window " + client + " does not exist");
5827 Slog.w(TAG_WM, "Failed looking up window callers=" + Debug.getCallers(3));
5830 if (session != null && win.mSession != session) {
5832 throw new IllegalArgumentException("Requested window " + client + " is in session "
5833 + win.mSession + ", not " + session);
5835 Slog.w(TAG_WM, "Failed looking up window callers=" + Debug.getCallers(3));
5842 void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
5843 // If the screen is currently frozen or off, then keep
5844 // it frozen/off until this window draws at its new
5846 if (!w.mToken.okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
5847 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w);
5848 w.setOrientationChanging(true);
5849 w.mLastFreezeDuration = 0;
5850 mRoot.mOrientationChangeComplete = false;
5851 if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) {
5852 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
5853 // XXX should probably keep timeout from
5854 // when we first froze the display.
5855 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
5856 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
5857 WINDOW_FREEZE_TIMEOUT_DURATION);
5863 * @return bitmap indicating if another pass through layout must be made.
5865 int handleAnimatingStoppedAndTransitionLocked() {
5868 mAppTransition.setIdle();
5870 for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) {
5871 final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i);
5872 mAppTransition.notifyAppTransitionFinishedLocked(token);
5874 mNoAnimationNotifyOnTransitionFinished.clear();
5876 // TODO: multi-display.
5877 final DisplayContent dc = getDefaultDisplayContentLocked();
5879 dc.mWallpaperController.hideDeferredWallpapersIfNeeded();
5881 dc.onAppTransitionDone();
5883 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5884 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM,
5885 "Wallpaper layer changed: assigning layers + relayout");
5886 dc.computeImeTarget(true /* updateImeTarget */);
5887 mRoot.mWallpaperMayChange = true;
5888 // Since the window list has been rebuilt, focus might have to be recomputed since the
5889 // actual order of windows might have changed again.
5890 mFocusMayChange = true;
5895 void checkDrawnWindowsLocked() {
5896 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
5899 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
5900 WindowState win = mWaitingForDrawn.get(j);
5901 if (DEBUG_SCREEN_ON) Slog.i(TAG_WM, "Waiting for drawn " + win +
5902 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
5903 " mHasSurface=" + win.mHasSurface +
5904 " drawState=" + win.mWinAnimator.mDrawState);
5905 if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) {
5906 // Window has been removed or hidden; no draw will now happen, so stop waiting.
5907 if (DEBUG_SCREEN_ON) Slog.w(TAG_WM, "Aborted waiting for drawn: " + win);
5908 mWaitingForDrawn.remove(win);
5909 } else if (win.hasDrawnLw()) {
5910 // Window is now drawn (and shown).
5911 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "Window drawn win=" + win);
5912 mWaitingForDrawn.remove(win);
5915 if (mWaitingForDrawn.isEmpty()) {
5916 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "All windows drawn!");
5917 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
5918 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
5922 void setHoldScreenLocked(final Session newHoldScreen) {
5923 final boolean hold = newHoldScreen != null;
5925 if (hold && mHoldingScreenOn != newHoldScreen) {
5926 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
5928 mHoldingScreenOn = newHoldScreen;
5930 final boolean state = mHoldingScreenWakeLock.isHeld();
5931 if (hold != state) {
5933 if (DEBUG_KEEP_SCREEN_ON) {
5934 Slog.d(TAG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to "
5935 + mRoot.mHoldScreenWindow);
5937 mLastWakeLockHoldingWindow = mRoot.mHoldScreenWindow;
5938 mLastWakeLockObscuringWindow = null;
5939 mHoldingScreenWakeLock.acquire();
5940 mPolicy.keepScreenOnStartedLw();
5942 if (DEBUG_KEEP_SCREEN_ON) {
5943 Slog.d(TAG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by "
5944 + mRoot.mObscuringWindow);
5946 mLastWakeLockHoldingWindow = null;
5947 mLastWakeLockObscuringWindow = mRoot.mObscuringWindow;
5948 mPolicy.keepScreenOnStoppedLw();
5949 mHoldingScreenWakeLock.release();
5954 void requestTraversal() {
5955 synchronized (mWindowMap) {
5956 mWindowPlacerLocked.requestTraversal();
5960 /** Note that Locked in this case is on mLayoutToAnim */
5961 void scheduleAnimationLocked() {
5962 mAnimator.scheduleAnimation();
5965 // TODO: Move to DisplayContent
5966 boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
5967 WindowState newFocus = mRoot.computeFocusedWindow();
5968 if (mCurrentFocus != newFocus) {
5969 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
5970 // This check makes sure that we don't already have the focus
5971 // change message pending.
5972 mH.removeMessages(H.REPORT_FOCUS_CHANGE);
5973 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
5974 // TODO(multidisplay): Focused windows on default display only.
5975 final DisplayContent displayContent = getDefaultDisplayContentLocked();
5976 boolean imWindowChanged = false;
5977 if (mInputMethodWindow != null) {
5978 final WindowState prevTarget = mInputMethodTarget;
5979 final WindowState newTarget =
5980 displayContent.computeImeTarget(true /* updateImeTarget*/);
5982 imWindowChanged = prevTarget != newTarget;
5984 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
5985 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) {
5986 final int prevImeAnimLayer = mInputMethodWindow.mWinAnimator.mAnimLayer;
5987 displayContent.assignWindowLayers(false /* setLayoutNeeded */);
5989 prevImeAnimLayer != mInputMethodWindow.mWinAnimator.mAnimLayer;
5993 if (imWindowChanged) {
5994 mWindowsChanged = true;
5995 displayContent.setLayoutNeeded();
5996 newFocus = mRoot.computeFocusedWindow();
5999 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG_WM, "Changing focus from " +
6000 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
6001 final WindowState oldFocus = mCurrentFocus;
6002 mCurrentFocus = newFocus;
6003 mLosingFocus.remove(newFocus);
6005 if (mCurrentFocus != null) {
6006 mWinAddedSinceNullFocus.clear();
6007 mWinRemovedSinceNullFocus.clear();
6010 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
6012 if (imWindowChanged && oldFocus != mInputMethodWindow) {
6013 // Focus of the input method window changed. Perform layout if needed.
6014 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
6015 displayContent.performLayout(true /*initial*/, updateInputWindows);
6016 focusChanged &= ~FINISH_LAYOUT_REDO_LAYOUT;
6017 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
6018 // Client will do the layout, but we need to assign layers
6019 // for handleNewWindowLocked() below.
6020 displayContent.assignWindowLayers(false /* setLayoutNeeded */);
6024 if ((focusChanged & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
6025 // The change in focus caused us to need to do a layout. Okay.
6026 displayContent.setLayoutNeeded();
6027 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
6028 displayContent.performLayout(true /*initial*/, updateInputWindows);
6032 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
6033 // If we defer assigning layers, then the caller is responsible for
6035 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
6038 displayContent.adjustForImeIfNeeded();
6040 // We may need to schedule some toast windows to be removed. The toasts for an app that
6041 // does not have input focus are removed within a timeout to prevent apps to redress
6043 displayContent.scheduleToastWindowsTimeoutIfNeededLocked(oldFocus, newFocus);
6045 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
6051 void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
6052 startFreezingDisplayLocked(inTransaction, exitAnim, enterAnim,
6053 getDefaultDisplayContentLocked());
6056 void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim,
6057 DisplayContent displayContent) {
6058 if (mDisplayFrozen) {
6062 if (!displayContent.isReady() || !mPolicy.isScreenOn() || !displayContent.okToAnimate()) {
6063 // No need to freeze the screen before the display is ready, if the screen is off,
6064 // or we can't currently animate.
6068 if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
6069 "startFreezingDisplayLocked: inTransaction=" + inTransaction
6070 + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim
6071 + " called by " + Debug.getCallers(8));
6072 mScreenFrozenLock.acquire();
6074 mDisplayFrozen = true;
6075 mDisplayFreezeTime = SystemClock.elapsedRealtime();
6076 mLastFinishedFreezeSource = null;
6078 // {@link mDisplayFrozen} prevents us from freezing on multiple displays at the same time.
6079 // As a result, we only track the display that has initially froze the screen.
6080 mFrozenDisplayId = displayContent.getDisplayId();
6082 mInputMonitor.freezeInputDispatchingLw();
6084 // Clear the last input window -- that is just used for
6085 // clean transitions between IMEs, and if we are freezing
6086 // the screen then the whole world is changing behind the scenes.
6087 mPolicy.setLastInputMethodWindowLw(null, null);
6089 if (mAppTransition.isTransitionSet()) {
6090 mAppTransition.freeze();
6093 if (PROFILE_ORIENTATION) {
6094 File file = new File("/data/system/frozen");
6095 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
6098 // TODO(multidisplay): rotation on non-default displays
6099 if (CUSTOM_SCREEN_ROTATION && displayContent.isDefaultDisplay) {
6100 mExitAnimId = exitAnim;
6101 mEnterAnimId = enterAnim;
6102 ScreenRotationAnimation screenRotationAnimation =
6103 mAnimator.getScreenRotationAnimationLocked(mFrozenDisplayId);
6104 if (screenRotationAnimation != null) {
6105 screenRotationAnimation.kill();
6108 // Check whether the current screen contains any secure content.
6109 boolean isSecure = displayContent.hasSecureWindowOnScreen();
6111 displayContent.updateDisplayInfo();
6112 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
6113 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure,
6115 mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
6116 screenRotationAnimation);
6120 void stopFreezingDisplayLocked() {
6121 if (!mDisplayFrozen) {
6125 if (mWaitingForConfig || mAppsFreezingScreen > 0
6126 || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE
6127 || mClientFreezingScreen || !mOpeningApps.isEmpty()) {
6128 if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
6129 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
6130 + ", mAppsFreezingScreen=" + mAppsFreezingScreen
6131 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
6132 + ", mClientFreezingScreen=" + mClientFreezingScreen
6133 + ", mOpeningApps.size()=" + mOpeningApps.size());
6137 if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
6138 "stopFreezingDisplayLocked: Unfreezing now");
6140 final DisplayContent displayContent = mRoot.getDisplayContent(mFrozenDisplayId);
6142 // We must make a local copy of the displayId as it can be potentially overwritten later on
6143 // in this method. For example, {@link startFreezingDisplayLocked} may be called as a result
6144 // of update rotation, but we reference the frozen display after that call in this method.
6145 final int displayId = mFrozenDisplayId;
6146 mFrozenDisplayId = INVALID_DISPLAY;
6147 mDisplayFrozen = false;
6148 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
6149 StringBuilder sb = new StringBuilder(128);
6150 sb.append("Screen frozen for ");
6151 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
6152 if (mLastFinishedFreezeSource != null) {
6153 sb.append(" due to ");
6154 sb.append(mLastFinishedFreezeSource);
6156 Slog.i(TAG_WM, sb.toString());
6157 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
6158 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
6159 if (PROFILE_ORIENTATION) {
6160 Debug.stopMethodTracing();
6163 boolean updateRotation = false;
6165 ScreenRotationAnimation screenRotationAnimation =
6166 mAnimator.getScreenRotationAnimationLocked(displayId);
6167 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
6168 && screenRotationAnimation.hasScreenshot()) {
6169 if (DEBUG_ORIENTATION) Slog.i(TAG_WM, "**** Dismissing screen rotation animation");
6170 // TODO(multidisplay): rotation on main screen only.
6171 DisplayInfo displayInfo = displayContent.getDisplayInfo();
6172 // Get rotation animation again, with new top window
6173 boolean isDimming = displayContent.isDimming();
6174 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
6175 mExitAnimId = mEnterAnimId = 0;
6177 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
6178 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth,
6179 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
6180 scheduleAnimationLocked();
6182 screenRotationAnimation.kill();
6183 mAnimator.setScreenRotationAnimationLocked(displayId, null);
6184 updateRotation = true;
6187 if (screenRotationAnimation != null) {
6188 screenRotationAnimation.kill();
6189 mAnimator.setScreenRotationAnimationLocked(displayId, null);
6191 updateRotation = true;
6194 mInputMonitor.thawInputDispatchingLw();
6196 boolean configChanged;
6198 // While the display is frozen we don't re-compute the orientation
6199 // to avoid inconsistent states. However, something interesting
6200 // could have actually changed during that time so re-evaluate it
6201 // now to catch that.
6202 configChanged = updateOrientationFromAppTokensLocked(false, displayId);
6204 // A little kludge: a lot could have happened while the
6205 // display was frozen, so now that we are coming back we
6206 // do a gc so that any remote references the system
6207 // processes holds on others can be released if they are
6208 // no longer needed.
6209 mH.removeMessages(H.FORCE_GC);
6210 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
6212 mScreenFrozenLock.release();
6214 if (updateRotation) {
6215 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation");
6216 configChanged |= displayContent.updateRotationUnchecked(
6217 false /* inTransaction */);
6220 if (configChanged) {
6221 mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
6225 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
6226 DisplayMetrics dm) {
6227 if (index < tokens.length) {
6228 String str = tokens[index];
6229 if (str != null && str.length() > 0) {
6231 int val = Integer.parseInt(str);
6233 } catch (Exception e) {
6237 if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
6240 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
6244 void createWatermarkInTransaction() {
6245 if (mWatermark != null) {
6249 File file = new File("/system/etc/setup.conf");
6250 FileInputStream in = null;
6251 DataInputStream ind = null;
6253 in = new FileInputStream(file);
6254 ind = new DataInputStream(in);
6255 String line = ind.readLine();
6257 String[] toks = line.split("%");
6258 if (toks != null && toks.length > 0) {
6259 // TODO(multi-display): Show watermarks on secondary displays.
6260 final DisplayContent displayContent = getDefaultDisplayContentLocked();
6261 mWatermark = new Watermark(displayContent.getDisplay(),
6262 displayContent.mRealDisplayMetrics, mFxSession, toks);
6265 } catch (FileNotFoundException e) {
6266 } catch (IOException e) {
6271 } catch (IOException e) {
6273 } else if (in != null) {
6276 } catch (IOException e) {
6283 public void setRecentsVisibility(boolean visible) {
6284 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
6285 != PackageManager.PERMISSION_GRANTED) {
6286 throw new SecurityException("Caller does not hold permission "
6287 + android.Manifest.permission.STATUS_BAR);
6290 synchronized (mWindowMap) {
6291 mPolicy.setRecentsVisibilityLw(visible);
6296 public void setPipVisibility(boolean visible) {
6297 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
6298 != PackageManager.PERMISSION_GRANTED) {
6299 throw new SecurityException("Caller does not hold permission "
6300 + android.Manifest.permission.STATUS_BAR);
6303 synchronized (mWindowMap) {
6304 mPolicy.setPipVisibilityLw(visible);
6309 public void statusBarVisibilityChanged(int visibility) {
6310 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
6311 != PackageManager.PERMISSION_GRANTED) {
6312 throw new SecurityException("Caller does not hold permission "
6313 + android.Manifest.permission.STATUS_BAR);
6316 synchronized (mWindowMap) {
6317 mLastStatusBarVisibility = visibility;
6318 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
6319 updateStatusBarVisibilityLocked(visibility);
6323 // TODO(multidisplay): StatusBar on multiple screens?
6324 private boolean updateStatusBarVisibilityLocked(int visibility) {
6325 if (mLastDispatchedSystemUiVisibility == visibility) {
6328 final int globalDiff = (visibility ^ mLastDispatchedSystemUiVisibility)
6329 // We are only interested in differences of one of the
6330 // clearable flags...
6331 & View.SYSTEM_UI_CLEARABLE_FLAGS
6332 // ...if it has actually been cleared.
6335 mLastDispatchedSystemUiVisibility = visibility;
6336 mInputManager.setSystemUiVisibility(visibility);
6337 getDefaultDisplayContentLocked().updateSystemUiVisibility(visibility, globalDiff);
6342 public void reevaluateStatusBarVisibility() {
6343 synchronized (mWindowMap) {
6344 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
6345 if (updateStatusBarVisibilityLocked(visibility)) {
6346 mWindowPlacerLocked.requestTraversal();
6352 * Used by ActivityManager to determine where to position an app with aspect ratio shorter then
6354 * @see WindowManagerPolicy#getNavBarPosition()
6356 public int getNavBarPosition() {
6357 synchronized (mWindowMap) {
6358 // Perform layout if it was scheduled before to make sure that we get correct nav bar
6359 // position when doing rotations.
6360 final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
6361 defaultDisplayContent.performLayout(false /* initial */,
6362 false /* updateInputWindows */);
6363 return mPolicy.getNavBarPosition();
6368 public WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name,
6369 InputEventReceiver.Factory inputEventReceiverFactory) {
6370 synchronized (mWindowMap) {
6371 return mInputMonitor.createInputConsumer(looper, name, inputEventReceiverFactory);
6376 public void createInputConsumer(String name, InputChannel inputChannel) {
6377 synchronized (mWindowMap) {
6378 mInputMonitor.createInputConsumer(name, inputChannel);
6383 public boolean destroyInputConsumer(String name) {
6384 synchronized (mWindowMap) {
6385 return mInputMonitor.destroyInputConsumer(name);
6390 public Region getCurrentImeTouchRegion() {
6391 if (mContext.checkCallingOrSelfPermission(RESTRICTED_VR_ACCESS) != PERMISSION_GRANTED) {
6392 throw new SecurityException("getCurrentImeTouchRegion is restricted to VR services");
6394 synchronized (mWindowMap) {
6395 final Region r = new Region();
6396 if (mInputMethodWindow != null) {
6397 mInputMethodWindow.getTouchableRegion(r);
6404 public boolean hasNavigationBar() {
6405 return mPolicy.hasNavigationBar();
6409 public void lockNow(Bundle options) {
6410 mPolicy.lockNow(options);
6413 public void showRecentApps(boolean fromHome) {
6414 mPolicy.showRecentApps(fromHome);
6418 public boolean isSafeModeEnabled() {
6423 public boolean clearWindowContentFrameStats(IBinder token) {
6424 if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
6425 "clearWindowContentFrameStats()")) {
6426 throw new SecurityException("Requires FRAME_STATS permission");
6428 synchronized (mWindowMap) {
6429 WindowState windowState = mWindowMap.get(token);
6430 if (windowState == null) {
6433 WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
6434 if (surfaceController == null) {
6437 return surfaceController.clearWindowContentFrameStats();
6442 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
6443 if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
6444 "getWindowContentFrameStats()")) {
6445 throw new SecurityException("Requires FRAME_STATS permission");
6447 synchronized (mWindowMap) {
6448 WindowState windowState = mWindowMap.get(token);
6449 if (windowState == null) {
6452 WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
6453 if (surfaceController == null) {
6456 if (mTempWindowRenderStats == null) {
6457 mTempWindowRenderStats = new WindowContentFrameStats();
6459 WindowContentFrameStats stats = mTempWindowRenderStats;
6460 if (!surfaceController.getWindowContentFrameStats(stats)) {
6467 public void notifyAppRelaunching(IBinder token) {
6468 synchronized (mWindowMap) {
6469 final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
6470 if (appWindow != null) {
6471 appWindow.startRelaunching();
6476 public void notifyAppRelaunchingFinished(IBinder token) {
6477 synchronized (mWindowMap) {
6478 final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
6479 if (appWindow != null) {
6480 appWindow.finishRelaunching();
6485 public void notifyAppRelaunchesCleared(IBinder token) {
6486 synchronized (mWindowMap) {
6487 final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
6488 if (appWindow != null) {
6489 appWindow.clearRelaunching();
6494 public void notifyAppResumedFinished(IBinder token) {
6495 synchronized (mWindowMap) {
6496 final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
6497 if (appWindow != null) {
6498 mUnknownAppVisibilityController.notifyAppResumedFinished(appWindow);
6504 * Called when a task has been removed from the recent tasks list.
6506 * Note: This doesn't go through {@link TaskWindowContainerController} yet as the window
6507 * container may not exist when this happens.
6509 public void notifyTaskRemovedFromRecents(int taskId, int userId) {
6510 synchronized (mWindowMap) {
6511 mTaskSnapshotController.notifyTaskRemovedFromRecents(taskId, userId);
6516 public int getDockedDividerInsetsLw() {
6517 return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets();
6520 private void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
6521 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
6522 mPolicy.dump(" ", pw, args);
6525 private void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
6526 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
6527 mAnimator.dumpLocked(pw, " ", dumpAll);
6530 private void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
6531 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
6532 mRoot.dumpTokens(pw, dumpAll);
6533 if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty()) {
6535 if (mOpeningApps.size() > 0) {
6536 pw.print(" mOpeningApps="); pw.println(mOpeningApps);
6538 if (mClosingApps.size() > 0) {
6539 pw.print(" mClosingApps="); pw.println(mClosingApps);
6544 private void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
6545 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
6546 for (int i=0; i<mSessions.size(); i++) {
6547 Session s = mSessions.valueAt(i);
6548 pw.print(" Session "); pw.print(s); pw.println(':');
6553 private void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
6554 ArrayList<WindowState> windows) {
6555 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
6556 dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
6559 private void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
6560 ArrayList<WindowState> windows) {
6561 mRoot.dumpWindowsNoHeader(pw, dumpAll, windows);
6563 if (!mHidingNonSystemOverlayWindows.isEmpty()) {
6565 pw.println(" Hiding System Alert Windows:");
6566 for (int i = mHidingNonSystemOverlayWindows.size() - 1; i >= 0; i--) {
6567 final WindowState w = mHidingNonSystemOverlayWindows.get(i);
6568 pw.print(" #"); pw.print(i); pw.print(' ');
6572 w.dump(pw, " ", true);
6578 if (mPendingRemove.size() > 0) {
6580 pw.println(" Remove pending for:");
6581 for (int i=mPendingRemove.size()-1; i>=0; i--) {
6582 WindowState w = mPendingRemove.get(i);
6583 if (windows == null || windows.contains(w)) {
6584 pw.print(" Remove #"); pw.print(i); pw.print(' ');
6588 w.dump(pw, " ", true);
6595 if (mForceRemoves != null && mForceRemoves.size() > 0) {
6597 pw.println(" Windows force removing:");
6598 for (int i=mForceRemoves.size()-1; i>=0; i--) {
6599 WindowState w = mForceRemoves.get(i);
6600 pw.print(" Removing #"); pw.print(i); pw.print(' ');
6604 w.dump(pw, " ", true);
6610 if (mDestroySurface.size() > 0) {
6612 pw.println(" Windows waiting to destroy their surface:");
6613 for (int i=mDestroySurface.size()-1; i>=0; i--) {
6614 WindowState w = mDestroySurface.get(i);
6615 if (windows == null || windows.contains(w)) {
6616 pw.print(" Destroy #"); pw.print(i); pw.print(' ');
6620 w.dump(pw, " ", true);
6627 if (mLosingFocus.size() > 0) {
6629 pw.println(" Windows losing focus:");
6630 for (int i=mLosingFocus.size()-1; i>=0; i--) {
6631 WindowState w = mLosingFocus.get(i);
6632 if (windows == null || windows.contains(w)) {
6633 pw.print(" Losing #"); pw.print(i); pw.print(' ');
6637 w.dump(pw, " ", true);
6644 if (mResizingWindows.size() > 0) {
6646 pw.println(" Windows waiting to resize:");
6647 for (int i=mResizingWindows.size()-1; i>=0; i--) {
6648 WindowState w = mResizingWindows.get(i);
6649 if (windows == null || windows.contains(w)) {
6650 pw.print(" Resizing #"); pw.print(i); pw.print(' ');
6654 w.dump(pw, " ", true);
6661 if (mWaitingForDrawn.size() > 0) {
6663 pw.println(" Clients waiting for these windows to be drawn:");
6664 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
6665 WindowState win = mWaitingForDrawn.get(i);
6666 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
6670 pw.print(" mGlobalConfiguration="); pw.println(mRoot.getConfiguration());
6671 pw.print(" mHasPermanentDpad="); pw.println(mHasPermanentDpad);
6672 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus);
6673 if (mLastFocus != mCurrentFocus) {
6674 pw.print(" mLastFocus="); pw.println(mLastFocus);
6676 pw.print(" mFocusedApp="); pw.println(mFocusedApp);
6677 if (mInputMethodTarget != null) {
6678 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
6680 pw.print(" mInTouchMode="); pw.print(mInTouchMode);
6681 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
6682 pw.print(" mLastDisplayFreezeDuration=");
6683 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
6684 if ( mLastFinishedFreezeSource != null) {
6685 pw.print(" due to ");
6686 pw.print(mLastFinishedFreezeSource);
6689 pw.print(" mLastWakeLockHoldingWindow=");pw.print(mLastWakeLockHoldingWindow);
6690 pw.print(" mLastWakeLockObscuringWindow="); pw.print(mLastWakeLockObscuringWindow);
6693 mInputMonitor.dump(pw, " ");
6694 mUnknownAppVisibilityController.dump(pw, " ");
6695 mTaskSnapshotController.dump(pw, " ");
6698 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer);
6699 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
6700 if (mLastStatusBarVisibility != 0) {
6701 pw.print(" mLastStatusBarVisibility=0x");
6702 pw.println(Integer.toHexString(mLastStatusBarVisibility));
6704 if (mInputMethodWindow != null) {
6705 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
6707 mWindowPlacerLocked.dump(pw, " ");
6708 mRoot.mWallpaperController.dump(pw, " ");
6709 pw.print(" mSystemBooted="); pw.print(mSystemBooted);
6710 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
6712 mRoot.dumpLayoutNeededDisplayIds(pw);
6714 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence);
6715 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen);
6716 pw.print(" windows="); pw.print(mWindowsFreezingScreen);
6717 pw.print(" client="); pw.print(mClientFreezingScreen);
6718 pw.print(" apps="); pw.print(mAppsFreezingScreen);
6719 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
6720 final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
6721 pw.print(" mRotation="); pw.print(defaultDisplayContent.getRotation());
6722 pw.print(" mAltOrientation=");
6723 pw.println(defaultDisplayContent.getAltOrientation());
6724 pw.print(" mLastWindowForcedOrientation=");
6725 pw.print(defaultDisplayContent.getLastWindowForcedOrientation());
6726 pw.print(" mLastOrientation=");
6727 pw.println(defaultDisplayContent.getLastOrientation());
6728 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
6729 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled);
6730 pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
6731 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
6732 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting);
6733 pw.print(" mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation);
6734 pw.println(" mLayoutToAnim:");
6735 mAppTransition.dump(pw, " ");
6739 private boolean dumpWindows(PrintWriter pw, String name, String[] args, int opti,
6741 final ArrayList<WindowState> windows = new ArrayList();
6742 if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
6743 final boolean appsOnly = name.contains("apps");
6744 final boolean visibleOnly = name.contains("visible");
6745 synchronized(mWindowMap) {
6747 mRoot.dumpDisplayContents(pw);
6750 mRoot.forAllWindows((w) -> {
6751 if ((!visibleOnly || w.mWinAnimator.getShown())
6752 && (!appsOnly || w.mAppToken != null)) {
6755 }, true /* traverseTopToBottom */);
6758 synchronized(mWindowMap) {
6759 mRoot.getWindowsByName(windows, name);
6763 if (windows.size() <= 0) {
6767 synchronized(mWindowMap) {
6768 dumpWindowsLocked(pw, dumpAll, windows);
6773 private void dumpLastANRLocked(PrintWriter pw) {
6774 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
6775 if (mLastANRState == null) {
6776 pw.println(" <no ANR has occurred since boot>");
6778 pw.println(mLastANRState);
6783 * Saves information about the state of the window manager at
6784 * the time an ANR occurred before anything else in the system changes
6787 * @param appWindowToken The application that ANR'd, may be null.
6788 * @param windowState The window that ANR'd, may be null.
6789 * @param reason The reason for the ANR, may be null.
6791 void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, String reason) {
6792 StringWriter sw = new StringWriter();
6793 PrintWriter pw = new FastPrintWriter(sw, false, 1024);
6794 pw.println(" ANR time: " + DateFormat.getDateTimeInstance().format(new Date()));
6795 if (appWindowToken != null) {
6796 pw.println(" Application at fault: " + appWindowToken.stringName);
6798 if (windowState != null) {
6799 pw.println(" Window at fault: " + windowState.mAttrs.getTitle());
6801 if (reason != null) {
6802 pw.println(" Reason: " + reason);
6804 if (!mWinAddedSinceNullFocus.isEmpty()) {
6805 pw.println(" Windows added since null focus: " + mWinAddedSinceNullFocus);
6807 if (!mWinRemovedSinceNullFocus.isEmpty()) {
6808 pw.println(" Windows removed since null focus: " + mWinRemovedSinceNullFocus);
6811 dumpWindowsNoHeaderLocked(pw, true, null);
6813 pw.println("Last ANR continued");
6814 mRoot.dumpDisplayContents(pw);
6816 mLastANRState = sw.toString();
6818 mH.removeMessages(H.RESET_ANR_MESSAGE);
6819 mH.sendEmptyMessageDelayed(H.RESET_ANR_MESSAGE, LAST_ANR_LIFETIME_DURATION_MSECS);
6823 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
6824 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
6826 boolean dumpAll = false;
6829 while (opti < args.length) {
6830 String opt = args[opti];
6831 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6835 if ("-a".equals(opt)) {
6837 } else if ("-h".equals(opt)) {
6838 pw.println("Window manager dump options:");
6839 pw.println(" [-a] [-h] [cmd] ...");
6840 pw.println(" cmd may be one of:");
6841 pw.println(" l[astanr]: last ANR information");
6842 pw.println(" p[policy]: policy state");
6843 pw.println(" a[animator]: animator state");
6844 pw.println(" s[essions]: active sessions");
6845 pw.println(" surfaces: active surfaces (debugging enabled only)");
6846 pw.println(" d[isplays]: active display contents");
6847 pw.println(" t[okens]: token list");
6848 pw.println(" w[indows]: window list");
6849 pw.println(" cmd may also be a NAME to dump windows. NAME may");
6850 pw.println(" be a partial substring in a window name, a");
6851 pw.println(" Window hex object identifier, or");
6852 pw.println(" \"all\" for all windows, or");
6853 pw.println(" \"visible\" for the visible windows.");
6854 pw.println(" \"visible-apps\" for the visible app windows.");
6855 pw.println(" -a: include all available server state.");
6858 pw.println("Unknown argument: " + opt + "; use -h for help");
6862 // Is the caller requesting to dump a particular piece of data?
6863 if (opti < args.length) {
6864 String cmd = args[opti];
6866 if ("lastanr".equals(cmd) || "l".equals(cmd)) {
6867 synchronized(mWindowMap) {
6868 dumpLastANRLocked(pw);
6871 } else if ("policy".equals(cmd) || "p".equals(cmd)) {
6872 synchronized(mWindowMap) {
6873 dumpPolicyLocked(pw, args, true);
6876 } else if ("animator".equals(cmd) || "a".equals(cmd)) {
6877 synchronized(mWindowMap) {
6878 dumpAnimatorLocked(pw, args, true);
6881 } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
6882 synchronized(mWindowMap) {
6883 dumpSessionsLocked(pw, true);
6886 } else if ("surfaces".equals(cmd)) {
6887 synchronized(mWindowMap) {
6888 WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, null);
6891 } else if ("displays".equals(cmd) || "d".equals(cmd)) {
6892 synchronized(mWindowMap) {
6893 mRoot.dumpDisplayContents(pw);
6896 } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
6897 synchronized(mWindowMap) {
6898 dumpTokensLocked(pw, true);
6901 } else if ("windows".equals(cmd) || "w".equals(cmd)) {
6902 synchronized(mWindowMap) {
6903 dumpWindowsLocked(pw, true, null);
6906 } else if ("all".equals(cmd) || "a".equals(cmd)) {
6907 synchronized(mWindowMap) {
6908 dumpWindowsLocked(pw, true, null);
6911 } else if ("containers".equals(cmd)) {
6912 synchronized(mWindowMap) {
6913 StringBuilder output = new StringBuilder();
6914 mRoot.dumpChildrenNames(output, " ");
6915 pw.println(output.toString());
6917 mRoot.forAllWindows(w -> {pw.println(w);}, true /* traverseTopToBottom */);
6921 // Dumping a single name?
6922 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
6923 pw.println("Bad window command, or no windows match: " + cmd);
6924 pw.println("Use -h for help.");
6930 synchronized(mWindowMap) {
6933 pw.println("-------------------------------------------------------------------------------");
6935 dumpLastANRLocked(pw);
6938 pw.println("-------------------------------------------------------------------------------");
6940 dumpPolicyLocked(pw, args, dumpAll);
6943 pw.println("-------------------------------------------------------------------------------");
6945 dumpAnimatorLocked(pw, args, dumpAll);
6948 pw.println("-------------------------------------------------------------------------------");
6950 dumpSessionsLocked(pw, dumpAll);
6953 pw.println("-------------------------------------------------------------------------------");
6955 WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ?
6956 "-------------------------------------------------------------------------------"
6960 pw.println("-------------------------------------------------------------------------------");
6962 mRoot.dumpDisplayContents(pw);
6965 pw.println("-------------------------------------------------------------------------------");
6967 dumpTokensLocked(pw, dumpAll);
6970 pw.println("-------------------------------------------------------------------------------");
6972 dumpWindowsLocked(pw, dumpAll, null);
6976 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
6978 public void monitor() {
6979 synchronized (mWindowMap) { }
6982 // TODO: All the display method below should probably be moved into the RootWindowContainer...
6983 private void createDisplayContentLocked(final Display display) {
6984 if (display == null) {
6985 throw new IllegalArgumentException("getDisplayContent: display must not be null");
6987 mRoot.getDisplayContentOrCreate(display.getDisplayId());
6990 // There is an inherent assumption that this will never return null.
6991 // TODO(multi-display): Inspect all the call-points of this method to see if they make sense to
6992 // support non-default display.
6993 DisplayContent getDefaultDisplayContentLocked() {
6994 return mRoot.getDisplayContentOrCreate(DEFAULT_DISPLAY);
6997 public void onDisplayAdded(int displayId) {
6998 synchronized (mWindowMap) {
6999 final Display display = mDisplayManager.getDisplay(displayId);
7000 if (display != null) {
7001 createDisplayContentLocked(display);
7002 displayReady(displayId);
7004 mWindowPlacerLocked.requestTraversal();
7008 public void onDisplayRemoved(int displayId) {
7009 synchronized (mWindowMap) {
7010 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
7011 if (displayContent != null) {
7012 displayContent.removeIfPossible();
7014 mAnimator.removeDisplayLocked(displayId);
7015 mWindowPlacerLocked.requestTraversal();
7019 public void onDisplayChanged(int displayId) {
7020 synchronized (mWindowMap) {
7021 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
7022 if (displayContent != null) {
7023 displayContent.updateDisplayInfo();
7025 mWindowPlacerLocked.requestTraversal();
7030 public Object getWindowManagerLock() {
7035 * Hint to a token that its activity will relaunch, which will trigger removal and addition of
7037 * @param token Application token for which the activity will be relaunched.
7039 public void setWillReplaceWindow(IBinder token, boolean animate) {
7040 synchronized (mWindowMap) {
7041 final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
7042 if (appWindowToken == null || !appWindowToken.hasContentToDisplay()) {
7043 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
7047 appWindowToken.setWillReplaceWindows(animate);
7052 * Hint to a token that its windows will be replaced across activity relaunch.
7053 * The windows would otherwise be removed shortly following this as the
7054 * activity is torn down.
7055 * @param token Application token for which the activity will be relaunched.
7056 * @param childrenOnly Whether to mark only child windows for replacement
7057 * (for the case where main windows are being preserved/
7058 * reused rather than replaced).
7061 // TODO: The s at the end of the method name is the only difference with the name of the method
7062 // above. We should combine them or find better names.
7063 void setWillReplaceWindows(IBinder token, boolean childrenOnly) {
7064 synchronized (mWindowMap) {
7065 final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
7066 if (appWindowToken == null || !appWindowToken.hasContentToDisplay()) {
7067 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
7073 appWindowToken.setWillReplaceChildWindows();
7075 appWindowToken.setWillReplaceWindows(false /* animate */);
7078 scheduleClearWillReplaceWindows(token, true /* replacing */);
7083 * If we're replacing the window, schedule a timer to clear the replaced window
7084 * after a timeout, in case the replacing window is not coming.
7086 * If we're not replacing the window, clear the replace window settings of the app.
7088 * @param token Application token for the activity whose window might be replaced.
7089 * @param replacing Whether the window is being replaced or not.
7091 public void scheduleClearWillReplaceWindows(IBinder token, boolean replacing) {
7092 synchronized (mWindowMap) {
7093 final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
7094 if (appWindowToken == null) {
7095 Slog.w(TAG_WM, "Attempted to reset replacing window on non-existing app token "
7100 scheduleWindowReplacementTimeouts(appWindowToken);
7102 appWindowToken.clearWillReplaceWindows();
7107 void scheduleWindowReplacementTimeouts(AppWindowToken appWindowToken) {
7108 if (!mWindowReplacementTimeouts.contains(appWindowToken)) {
7109 mWindowReplacementTimeouts.add(appWindowToken);
7111 mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
7112 mH.sendEmptyMessageDelayed(
7113 H.WINDOW_REPLACEMENT_TIMEOUT, WINDOW_REPLACEMENT_TIMEOUT_DURATION);
7117 public int getDockedStackSide() {
7118 synchronized (mWindowMap) {
7119 final TaskStack dockedStack = getDefaultDisplayContentLocked()
7120 .getDockedStackIgnoringVisibility();
7121 return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide();
7126 public void setDockedStackResizing(boolean resizing) {
7127 synchronized (mWindowMap) {
7128 getDefaultDisplayContentLocked().getDockedDividerController().setResizing(resizing);
7134 public void setDockedStackDividerTouchRegion(Rect touchRegion) {
7135 synchronized (mWindowMap) {
7136 getDefaultDisplayContentLocked().getDockedDividerController()
7137 .setTouchRegion(touchRegion);
7138 setFocusTaskRegionLocked(null);
7143 public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
7144 synchronized (mWindowMap) {
7145 getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer(
7146 visible, targetStackId, alpha);
7150 public void setForceResizableTasks(boolean forceResizableTasks) {
7151 synchronized (mWindowMap) {
7152 mForceResizableTasks = forceResizableTasks;
7156 public void setSupportsPictureInPicture(boolean supportsPictureInPicture) {
7157 synchronized (mWindowMap) {
7158 mSupportsPictureInPicture = supportsPictureInPicture;
7162 static int dipToPixel(int dip, DisplayMetrics displayMetrics) {
7163 return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics);
7167 public void registerDockedStackListener(IDockedStackListener listener) {
7168 if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS,
7169 "registerDockedStackListener()")) {
7172 synchronized (mWindowMap) {
7173 // TODO(multi-display): The listener is registered on the default display only.
7174 getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener(
7180 public void registerPinnedStackListener(int displayId, IPinnedStackListener listener) {
7181 if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS,
7182 "registerPinnedStackListener()")) {
7185 if (!mSupportsPictureInPicture) {
7188 synchronized (mWindowMap) {
7189 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
7190 displayContent.getPinnedStackController().registerPinnedStackListener(listener);
7195 public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
7197 WindowState focusedWindow = getFocusedWindow();
7198 if (focusedWindow != null && focusedWindow.mClient != null) {
7199 getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId);
7201 } catch (RemoteException e) {
7206 public void getStableInsets(int displayId, Rect outInsets) throws RemoteException {
7207 synchronized (mWindowMap) {
7208 getStableInsetsLocked(displayId, outInsets);
7212 void getStableInsetsLocked(int displayId, Rect outInsets) {
7213 outInsets.setEmpty();
7214 final DisplayContent dc = mRoot.getDisplayContent(displayId);
7216 final DisplayInfo di = dc.getDisplayInfo();
7217 mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
7221 void intersectDisplayInsetBounds(Rect display, Rect insets, Rect inOutBounds) {
7222 mTmpRect3.set(display);
7223 mTmpRect3.inset(insets);
7224 inOutBounds.intersect(mTmpRect3);
7227 MousePositionTracker mMousePositionTracker = new MousePositionTracker();
7229 private static class MousePositionTracker implements PointerEventListener {
7230 private boolean mLatestEventWasMouse;
7231 private float mLatestMouseX;
7232 private float mLatestMouseY;
7234 void updatePosition(float x, float y) {
7235 synchronized (this) {
7236 mLatestEventWasMouse = true;
7243 public void onPointerEvent(MotionEvent motionEvent) {
7244 if (motionEvent.isFromSource(InputDevice.SOURCE_MOUSE)) {
7245 updatePosition(motionEvent.getRawX(), motionEvent.getRawY());
7247 synchronized (this) {
7248 mLatestEventWasMouse = false;
7254 void updatePointerIcon(IWindow client) {
7255 float mouseX, mouseY;
7257 synchronized(mMousePositionTracker) {
7258 if (!mMousePositionTracker.mLatestEventWasMouse) {
7261 mouseX = mMousePositionTracker.mLatestMouseX;
7262 mouseY = mMousePositionTracker.mLatestMouseY;
7265 synchronized (mWindowMap) {
7266 if (mDragState != null) {
7267 // Drag cursor overrides the app cursor.
7270 WindowState callingWin = windowForClientLocked(null, client, false);
7271 if (callingWin == null) {
7272 Slog.w(TAG_WM, "Bad requesting window " + client);
7275 final DisplayContent displayContent = callingWin.getDisplayContent();
7276 if (displayContent == null) {
7279 WindowState windowUnderPointer =
7280 displayContent.getTouchableWinAtPointLocked(mouseX, mouseY);
7281 if (windowUnderPointer != callingWin) {
7285 windowUnderPointer.mClient.updatePointerIcon(
7286 windowUnderPointer.translateToWindowX(mouseX),
7287 windowUnderPointer.translateToWindowY(mouseY));
7288 } catch (RemoteException e) {
7289 Slog.w(TAG_WM, "unable to update pointer icon");
7294 void restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY) {
7295 // Mouse position tracker has not been getting updates while dragging, update it now.
7296 mMousePositionTracker.updatePosition(latestX, latestY);
7298 WindowState windowUnderPointer =
7299 displayContent.getTouchableWinAtPointLocked(latestX, latestY);
7300 if (windowUnderPointer != null) {
7302 windowUnderPointer.mClient.updatePointerIcon(
7303 windowUnderPointer.translateToWindowX(latestX),
7304 windowUnderPointer.translateToWindowY(latestY));
7305 } catch (RemoteException e) {
7306 Slog.w(TAG_WM, "unable to restore pointer icon");
7309 InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_DEFAULT);
7314 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
7315 throws RemoteException {
7316 if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS, "registerShortcutKey")) {
7317 throw new SecurityException(
7318 "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission");
7320 mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver);
7323 void markForSeamlessRotation(WindowState w, boolean seamlesslyRotated) {
7324 if (seamlesslyRotated == w.mSeamlesslyRotated) {
7327 w.mSeamlesslyRotated = seamlesslyRotated;
7328 if (seamlesslyRotated) {
7329 mSeamlessRotationCount++;
7331 mSeamlessRotationCount--;
7333 if (mSeamlessRotationCount == 0) {
7334 if (DEBUG_ORIENTATION) {
7335 Slog.i(TAG, "Performing post-rotate rotation after seamless rotation");
7337 final DisplayContent displayContent = w.getDisplayContent();
7338 if (displayContent.updateRotationUnchecked(false /* inTransaction */)) {
7339 mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
7345 private final class LocalService extends WindowManagerInternal {
7347 public void requestTraversalFromDisplayManager() {
7352 public void setMagnificationSpec(MagnificationSpec spec) {
7353 synchronized (mWindowMap) {
7354 if (mAccessibilityController != null) {
7355 mAccessibilityController.setMagnificationSpecLocked(spec);
7357 throw new IllegalStateException("Magnification callbacks not set!");
7360 if (Binder.getCallingPid() != myPid()) {
7366 public void setForceShowMagnifiableBounds(boolean show) {
7367 synchronized (mWindowMap) {
7368 if (mAccessibilityController != null) {
7369 mAccessibilityController.setForceShowMagnifiableBoundsLocked(show);
7371 throw new IllegalStateException("Magnification callbacks not set!");
7377 public void getMagnificationRegion(@NonNull Region magnificationRegion) {
7378 synchronized (mWindowMap) {
7379 if (mAccessibilityController != null) {
7380 mAccessibilityController.getMagnificationRegionLocked(magnificationRegion);
7382 throw new IllegalStateException("Magnification callbacks not set!");
7388 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
7389 synchronized (mWindowMap) {
7390 WindowState windowState = mWindowMap.get(windowToken);
7391 if (windowState == null) {
7394 MagnificationSpec spec = null;
7395 if (mAccessibilityController != null) {
7396 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState);
7398 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
7401 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
7402 spec.scale *= windowState.mGlobalScale;
7408 public void setMagnificationCallbacks(@Nullable MagnificationCallbacks callbacks) {
7409 synchronized (mWindowMap) {
7410 if (mAccessibilityController == null) {
7411 mAccessibilityController = new AccessibilityController(
7412 WindowManagerService.this);
7414 mAccessibilityController.setMagnificationCallbacksLocked(callbacks);
7415 if (!mAccessibilityController.hasCallbacksLocked()) {
7416 mAccessibilityController = null;
7422 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) {
7423 synchronized (mWindowMap) {
7424 if (mAccessibilityController == null) {
7425 mAccessibilityController = new AccessibilityController(
7426 WindowManagerService.this);
7428 mAccessibilityController.setWindowsForAccessibilityCallback(callback);
7429 if (!mAccessibilityController.hasCallbacksLocked()) {
7430 mAccessibilityController = null;
7436 public void setInputFilter(IInputFilter filter) {
7437 mInputManager.setInputFilter(filter);
7441 public IBinder getFocusedWindowToken() {
7442 synchronized (mWindowMap) {
7443 WindowState windowState = getFocusedWindowLocked();
7444 if (windowState != null) {
7445 return windowState.mClient.asBinder();
7452 public boolean isKeyguardLocked() {
7453 return WindowManagerService.this.isKeyguardLocked();
7457 public boolean isKeyguardShowingAndNotOccluded() {
7458 return WindowManagerService.this.isKeyguardShowingAndNotOccluded();
7462 public void showGlobalActions() {
7463 WindowManagerService.this.showGlobalActions();
7467 public void getWindowFrame(IBinder token, Rect outBounds) {
7468 synchronized (mWindowMap) {
7469 WindowState windowState = mWindowMap.get(token);
7470 if (windowState != null) {
7471 outBounds.set(windowState.mFrame);
7473 outBounds.setEmpty();
7479 public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
7480 boolean allWindowsDrawn = false;
7481 synchronized (mWindowMap) {
7482 mWaitingForDrawnCallback = callback;
7483 getDefaultDisplayContentLocked().waitForAllWindowsDrawn();
7484 mWindowPlacerLocked.requestTraversal();
7485 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
7486 if (mWaitingForDrawn.isEmpty()) {
7487 allWindowsDrawn = true;
7489 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
7490 checkDrawnWindowsLocked();
7493 if (allWindowsDrawn) {
7499 public void addWindowToken(IBinder token, int type, int displayId) {
7500 WindowManagerService.this.addWindowToken(token, type, displayId);
7504 public void removeWindowToken(IBinder binder, boolean removeWindows, int displayId) {
7505 synchronized(mWindowMap) {
7506 if (removeWindows) {
7507 final DisplayContent dc = mRoot.getDisplayContent(displayId);
7509 Slog.w(TAG_WM, "removeWindowToken: Attempted to remove token: " + binder
7510 + " for non-exiting displayId=" + displayId);
7514 final WindowToken token = dc.removeWindowToken(binder);
7515 if (token == null) {
7516 Slog.w(TAG_WM, "removeWindowToken: Attempted to remove non-existing token: "
7521 token.removeAllWindowsIfPossible();
7523 WindowManagerService.this.removeWindowToken(binder, displayId);
7528 public void registerAppTransitionListener(AppTransitionListener listener) {
7529 synchronized (mWindowMap) {
7530 mAppTransition.registerListenerLocked(listener);
7535 public int getInputMethodWindowVisibleHeight() {
7536 synchronized (mWindowMap) {
7537 return mPolicy.getInputMethodWindowVisibleHeightLw();
7542 public void saveLastInputMethodWindowForTransition() {
7543 synchronized (mWindowMap) {
7544 if (mInputMethodWindow != null) {
7545 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
7551 public void clearLastInputMethodWindowForTransition() {
7552 synchronized (mWindowMap) {
7553 mPolicy.setLastInputMethodWindowLw(null, null);
7558 public void updateInputMethodWindowStatus(@NonNull IBinder imeToken,
7559 boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed,
7560 @Nullable IBinder targetWindowToken) {
7561 // TODO (b/34628091): Use this method to address the window animation issue.
7562 if (DEBUG_INPUT_METHOD) {
7563 Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken=" + imeToken
7564 + " dismissImeOnBackKeyPressed=" + dismissImeOnBackKeyPressed
7565 + " imeWindowVisible=" + imeWindowVisible
7566 + " targetWindowToken=" + targetWindowToken);
7568 mPolicy.setDismissImeOnBackKeyPressed(dismissImeOnBackKeyPressed);
7572 public boolean isHardKeyboardAvailable() {
7573 synchronized (mWindowMap) {
7574 return mHardKeyboardAvailable;
7579 public void setOnHardKeyboardStatusChangeListener(
7580 OnHardKeyboardStatusChangeListener listener) {
7581 synchronized (mWindowMap) {
7582 mHardKeyboardStatusChangeListener = listener;
7587 public boolean isStackVisible(int stackId) {
7588 synchronized (mWindowMap) {
7589 final DisplayContent dc = getDefaultDisplayContentLocked();
7590 return dc.isStackVisible(stackId);
7595 public boolean isDockedDividerResizing() {
7596 synchronized (mWindowMap) {
7597 return getDefaultDisplayContentLocked().getDockedDividerController().isResizing();
7602 public void computeWindowsForAccessibility() {
7603 final AccessibilityController accessibilityController;
7604 synchronized (mWindowMap) {
7605 accessibilityController = mAccessibilityController;
7607 if (accessibilityController != null) {
7608 accessibilityController.performComputeChangedWindowsNotLocked();
7613 public void setVr2dDisplayId(int vr2dDisplayId) {
7614 if (DEBUG_DISPLAY) {
7615 Slog.d(TAG, "setVr2dDisplayId called for: " + vr2dDisplayId);
7617 synchronized (WindowManagerService.this) {
7618 mVr2dDisplayId = vr2dDisplayId;
7623 void registerAppFreezeListener(AppFreezeListener listener) {
7624 if (!mAppFreezeListeners.contains(listener)) {
7625 mAppFreezeListeners.add(listener);
7629 void unregisterAppFreezeListener(AppFreezeListener listener) {
7630 mAppFreezeListeners.remove(listener);
7634 * WARNING: This interrupts surface updates, be careful! Don't
7635 * execute within the transaction for longer than you would
7636 * execute on an animation thread.
7637 * WARNING: This holds the WindowManager lock, so if exec will acquire
7638 * the ActivityManager lock, you should hold it BEFORE calling this
7639 * otherwise there is a risk of deadlock if another thread holding the AM
7640 * lock waits on the WM lock.
7641 * WARNING: This method contains locks known to the State of California
7642 * to cause Deadlocks and other conditions.
7644 * Begins a surface transaction with which the AM can batch operations.
7645 * All Surface updates performed by the WindowManager following this
7646 * will not appear on screen until after the call to
7647 * closeSurfaceTransaction.
7649 * ActivityManager can use this to ensure multiple 'commands' will all
7650 * be reflected in a single frame. For example when reparenting a window
7651 * which was previously hidden due to it's parent properties, we may
7652 * need to ensure it is hidden in the same frame that the properties
7653 * from the new parent are inherited, otherwise it could be revealed
7656 * TODO(b/36393204): We can investigate totally replacing #deferSurfaceLayout
7657 * with something like this but it seems that some existing cases of
7658 * deferSurfaceLayout may be a little too broad, in particular the total
7659 * enclosure of startActivityUnchecked which could run for quite some time.
7661 public void inSurfaceTransaction(Runnable exec) {
7662 // We hold the WindowManger lock to ensure relayoutWindow
7663 // does not return while a Surface transaction is opening.
7664 // The client depends on us to have resized the surface
7665 // by that point (b/36462635)
7667 synchronized (mWindowMap) {
7668 SurfaceControl.openTransaction();
7672 SurfaceControl.closeTransaction();
7677 /** Called to inform window manager if non-Vr UI shoul be disabled or not. */
7678 public void disableNonVrUi(boolean disable) {
7679 synchronized (mWindowMap) {
7680 // Allow alert window notifications to be shown if non-vr UI is enabled.
7681 final boolean showAlertWindowNotifications = !disable;
7682 if (showAlertWindowNotifications == mShowAlertWindowNotifications) {
7685 mShowAlertWindowNotifications = showAlertWindowNotifications;
7687 for (int i = mSessions.size() - 1; i >= 0; --i) {
7688 final Session s = mSessions.valueAt(i);
7689 s.setShowingAlertWindowNotificationAllowed(mShowAlertWindowNotifications);
7694 boolean hasWideColorGamutSupport() {
7695 return mHasWideColorGamutSupport &&
7696 !SystemProperties.getBoolean("persist.sys.sf.native_mode", false);
7699 void updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown) {
7700 if (!win.hideNonSystemOverlayWindowsWhenVisible()
7701 && !mHidingNonSystemOverlayWindows.contains(win)) {
7704 final boolean systemAlertWindowsHidden = !mHidingNonSystemOverlayWindows.isEmpty();
7706 if (!mHidingNonSystemOverlayWindows.contains(win)) {
7707 mHidingNonSystemOverlayWindows.add(win);
7710 mHidingNonSystemOverlayWindows.remove(win);
7713 final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
7715 if (systemAlertWindowsHidden == hideSystemAlertWindows) {
7719 mRoot.forAllWindows((w) -> {
7720 w.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
7721 }, false /* traverseTopToBottom */);