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.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
23 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
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.os.Process.ROOT_UID;
30 import static android.os.Process.SHELL_UID;
31 import static android.os.Process.SYSTEM_UID;
32 import static android.os.Process.THREAD_PRIORITY_DISPLAY;
33 import static android.os.Process.myPid;
34 import static android.os.UserHandle.USER_NULL;
35 import static android.view.Display.DEFAULT_DISPLAY;
36 import static android.view.WindowManager.DOCKED_INVALID;
37 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
38 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
39 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
40 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
41 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
42 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
43 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
44 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
45 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
46 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
47 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
48 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
49 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
50 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT;
51 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
52 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
53 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
54 import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
55 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
56 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
57 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
58 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
59 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
60 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
61 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
62 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
63 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
64 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
65 import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
66 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
67 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
68 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
69 import static com.android.server.LockGuard.INDEX_WINDOW;
70 import static com.android.server.LockGuard.installLock;
71 import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
72 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END;
73 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
74 import static com.android.server.wm.KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED;
75 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
76 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
77 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
78 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
79 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
80 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
81 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
82 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
83 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
84 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
85 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
86 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
87 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
88 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
89 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
90 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
91 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
92 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
93 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
94 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
95 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
96 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
97 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
98 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
99 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSACTIONS;
100 import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
101 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
102 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
104 import android.Manifest;
105 import android.Manifest.permission;
106 import android.animation.ValueAnimator;
107 import android.annotation.IntDef;
108 import android.annotation.NonNull;
109 import android.annotation.Nullable;
110 import android.app.ActivityManager;
111 import android.app.ActivityManager.TaskSnapshot;
112 import android.app.ActivityManagerInternal;
113 import android.app.ActivityThread;
114 import android.app.AppOpsManager;
115 import android.app.IActivityManager;
116 import android.content.BroadcastReceiver;
117 import android.content.ContentResolver;
118 import android.content.Context;
119 import android.content.Intent;
120 import android.content.IntentFilter;
121 import android.content.pm.ApplicationInfo;
122 import android.content.pm.PackageManager;
123 import android.content.res.Configuration;
124 import android.database.ContentObserver;
125 import android.graphics.Bitmap;
126 import android.graphics.Matrix;
127 import android.graphics.PixelFormat;
128 import android.graphics.Point;
129 import android.graphics.Rect;
130 import android.graphics.RectF;
131 import android.graphics.Region;
132 import android.hardware.display.DisplayManager;
133 import android.hardware.display.DisplayManagerInternal;
134 import android.hardware.input.InputManager;
135 import android.net.Uri;
136 import android.os.Binder;
137 import android.os.Build;
138 import android.os.Bundle;
139 import android.os.Debug;
140 import android.os.Handler;
141 import android.os.IBinder;
142 import android.os.IRemoteCallback;
143 import android.os.Looper;
144 import android.os.Message;
145 import android.os.Parcel;
146 import android.os.ParcelFileDescriptor;
147 import android.os.PowerManager;
148 import android.os.PowerManagerInternal;
149 import android.os.PowerSaveState;
150 import android.os.RemoteException;
151 import android.os.ServiceManager;
152 import android.os.StrictMode;
153 import android.os.SystemClock;
154 import android.os.SystemProperties;
155 import android.os.SystemService;
156 import android.os.Trace;
157 import android.os.UserHandle;
158 import android.os.WorkSource;
159 import android.provider.Settings;
160 import android.util.ArraySet;
161 import android.util.DisplayMetrics;
162 import android.util.EventLog;
163 import android.util.Log;
164 import android.util.MergedConfiguration;
165 import android.util.Pair;
166 import android.util.Slog;
167 import android.util.SparseArray;
168 import android.util.SparseIntArray;
169 import android.util.TimeUtils;
170 import android.util.TypedValue;
171 import android.view.AppTransitionAnimationSpec;
172 import android.view.Display;
173 import android.view.DisplayInfo;
174 import android.view.Gravity;
175 import android.view.IAppTransitionAnimationSpecsFuture;
176 import android.view.IDockedStackListener;
177 import android.view.IInputFilter;
178 import android.view.IOnKeyguardExitResult;
179 import android.view.IPinnedStackListener;
180 import android.view.IRotationWatcher;
181 import android.view.IWindow;
182 import android.view.IWindowId;
183 import android.view.IWindowManager;
184 import android.view.IWindowSession;
185 import android.view.IWindowSessionCallback;
186 import android.view.InputChannel;
187 import android.view.InputDevice;
188 import android.view.InputEvent;
189 import android.view.InputEventReceiver;
190 import android.view.KeyEvent;
191 import android.view.MagnificationSpec;
192 import android.view.MotionEvent;
193 import android.view.PointerIcon;
194 import android.view.Surface;
195 import android.view.Surface.OutOfResourcesException;
196 import android.view.SurfaceControl;
197 import android.view.SurfaceSession;
198 import android.view.View;
199 import android.view.WindowContentFrameStats;
200 import android.view.WindowManager;
201 import android.view.WindowManager.LayoutParams;
202 import android.view.WindowManagerGlobal;
203 import android.view.WindowManagerInternal;
204 import android.view.WindowManagerPolicy;
205 import android.view.WindowManagerPolicy.PointerEventListener;
206 import android.view.animation.Animation;
207 import android.view.inputmethod.InputMethodManagerInternal;
209 import com.android.internal.R;
210 import com.android.internal.app.IAssistScreenshotReceiver;
211 import com.android.internal.os.IResultReceiver;
212 import com.android.internal.policy.IKeyguardDismissCallback;
213 import com.android.internal.policy.IShortcutService;
214 import com.android.internal.util.DumpUtils;
215 import com.android.internal.util.FastPrintWriter;
216 import com.android.internal.view.IInputContext;
217 import com.android.internal.view.IInputMethodClient;
218 import com.android.internal.view.IInputMethodManager;
219 import com.android.internal.view.WindowManagerPolicyThread;
220 import com.android.server.AnimationThread;
221 import com.android.server.DisplayThread;
222 import com.android.server.EventLogTags;
223 import com.android.server.FgThread;
224 import com.android.server.LocalServices;
225 import com.android.server.ThreadPriorityBooster;
226 import com.android.server.UiThread;
227 import com.android.server.Watchdog;
228 import com.android.server.input.InputManagerService;
229 import com.android.server.power.BatterySaverPolicy.ServiceType;
230 import com.android.server.power.ShutdownThread;
232 import java.io.BufferedWriter;
233 import java.io.DataInputStream;
235 import java.io.FileDescriptor;
236 import java.io.FileInputStream;
237 import java.io.FileNotFoundException;
238 import java.io.IOException;
239 import java.io.OutputStream;
240 import java.io.OutputStreamWriter;
241 import java.io.PrintWriter;
242 import java.io.StringWriter;
243 import java.lang.annotation.Retention;
244 import java.lang.annotation.RetentionPolicy;
245 import java.net.Socket;
246 import java.text.DateFormat;
247 import java.util.ArrayList;
248 import java.util.Date;
249 import java.util.List;
251 public class WindowManagerService extends IWindowManager.Stub
252 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
253 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowManagerService" : TAG_WM;
255 static final int LAYOUT_REPEAT_THRESHOLD = 4;
257 static final boolean PROFILE_ORIENTATION = false;
258 static final boolean localLOGV = DEBUG;
260 /** How much to multiply the policy's type layer, to reserve room
261 * for multiple windows of the same type and Z-ordering adjustment
262 * with TYPE_LAYER_OFFSET. */
263 static final int TYPE_LAYER_MULTIPLIER = 10000;
265 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
266 * or below others in the same layer. */
267 static final int TYPE_LAYER_OFFSET = 1000;
269 /** How much to increment the layer for each window, to reserve room
270 * for effect surfaces between them.
272 static final int WINDOW_LAYER_MULTIPLIER = 5;
275 * Dim surface layer is immediately below target window.
277 static final int LAYER_OFFSET_DIM = 1;
280 * Animation thumbnail is as far as possible below the window above
281 * the thumbnail (or in other words as far as possible above the window
284 static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER - 1;
286 /** The maximum length we will accept for a loaded animation duration:
287 * this is 10 seconds.
289 static final int MAX_ANIMATION_DURATION = 10 * 1000;
291 /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
292 static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
294 /** Amount of time (in milliseconds) to delay before declaring a seamless rotation timeout. */
295 static final int SEAMLESS_ROTATION_TIMEOUT_DURATION = 2000;
297 /** Amount of time (in milliseconds) to delay before declaring a window replacement timeout. */
298 static final int WINDOW_REPLACEMENT_TIMEOUT_DURATION = 2000;
300 /** Amount of time to allow a last ANR message to exist before freeing the memory. */
301 static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours
303 * If true, the window manager will do its own custom freezing and general
304 * management of the screen during rotation.
306 static final boolean CUSTOM_SCREEN_ROTATION = true;
308 // Maximum number of milliseconds to wait for input devices to be enumerated before
309 // proceding with safe mode detection.
310 private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
312 // Default input dispatching timeout in nanoseconds.
313 static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
315 // Poll interval in milliseconds for watching boot animation finished.
316 private static final int BOOT_ANIMATION_POLL_INTERVAL = 200;
318 // The name of the boot animation service in init.rc.
319 private static final String BOOT_ANIMATION_SERVICE = "bootanim";
321 static final int UPDATE_FOCUS_NORMAL = 0;
322 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
323 static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
324 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
326 private static final String SYSTEM_SECURE = "ro.secure";
327 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
329 private static final String DENSITY_OVERRIDE = "ro.config.density_override";
330 private static final String SIZE_OVERRIDE = "ro.config.size_override";
332 private static final int MAX_SCREENSHOT_RETRIES = 3;
334 private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
336 // Used to indicate that if there is already a transition set, it should be preserved when
337 // trying to apply a new one.
338 private static final boolean ALWAYS_KEEP_CURRENT = true;
340 private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f;
342 // Enums for animation scale update types.
343 @Retention(RetentionPolicy.SOURCE)
344 @IntDef({WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE, ANIMATION_DURATION_SCALE})
345 private @interface UpdateAnimationScaleMode {};
346 private static final int WINDOW_ANIMATION_SCALE = 0;
347 private static final int TRANSITION_ANIMATION_SCALE = 1;
348 private static final int ANIMATION_DURATION_SCALE = 2;
350 final private KeyguardDisableHandler mKeyguardDisableHandler;
352 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
354 public void onReceive(Context context, Intent intent) {
355 switch (intent.getAction()) {
356 case ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED:
357 mKeyguardDisableHandler.sendEmptyMessage(KEYGUARD_POLICY_CHANGED);
359 case ACTION_USER_REMOVED:
360 final int userId = intent.getIntExtra(EXTRA_USER_HANDLE, USER_NULL);
361 if (userId != USER_NULL) {
362 synchronized (mWindowMap) {
363 mScreenCaptureDisabled.remove(userId);
370 final WindowSurfacePlacer mWindowPlacerLocked;
373 * Current user when multi-user is enabled. Don't show windows of
374 * non-current user. Also see mCurrentProfileIds.
378 * Users that are profiles of the current user. These are also allowed to show windows
379 * on the current user.
381 int[] mCurrentProfileIds = new int[] {};
383 final Context mContext;
385 final boolean mHaveInputMethods;
387 final boolean mHasPermanentDpad;
388 final long mDrawLockTimeoutMillis;
389 final boolean mAllowAnimationsInLowPowerMode;
391 final boolean mAllowBootMessages;
393 final boolean mLimitedAlphaCompositing;
394 final int mMaxUiWidth;
396 final WindowManagerPolicy mPolicy;
398 final IActivityManager mActivityManager;
399 final ActivityManagerInternal mAmInternal;
401 final AppOpsManager mAppOps;
403 final DisplaySettings mDisplaySettings;
405 /** If the system should display notifications for apps displaying an alert window. */
406 boolean mShowAlertWindowNotifications = true;
409 * All currently active sessions with clients.
411 final ArraySet<Session> mSessions = new ArraySet<>();
414 * Mapping from an IWindow IBinder to the server's Window object.
415 * This is also used as the lock for all of our state.
416 * NOTE: Never call into methods that lock ActivityManagerService while holding this object.
418 final WindowHashMap mWindowMap = new WindowHashMap();
421 * List of window tokens that have finished starting their application,
422 * and now need to have the policy remove their windows.
424 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<>();
427 * List of window tokens that have finished drawing their own windows and
428 * no longer need to show any saved surfaces. Windows that's still showing
429 * saved surfaces will be cleaned up after next animation pass.
431 final ArrayList<AppWindowToken> mFinishedEarlyAnim = new ArrayList<>();
434 * List of app window tokens that are waiting for replacing windows. If the
435 * replacement doesn't come in time the stale windows needs to be disposed of.
437 final ArrayList<AppWindowToken> mWindowReplacementTimeouts = new ArrayList<>();
440 * Windows that are being resized. Used so we can tell the client about
441 * the resize after closing the transaction in which we resized the
442 * underlying surface.
444 final ArrayList<WindowState> mResizingWindows = new ArrayList<>();
447 * Windows whose animations have ended and now must be removed.
449 final ArrayList<WindowState> mPendingRemove = new ArrayList<>();
452 * Used when processing mPendingRemove to avoid working on the original array.
454 WindowState[] mPendingRemoveTmp = new WindowState[20];
457 * Windows whose surface should be destroyed.
459 final ArrayList<WindowState> mDestroySurface = new ArrayList<>();
462 * Windows with a preserved surface waiting to be destroyed. These windows
463 * are going through a surface change. We keep the old surface around until
464 * the first frame on the new surface finishes drawing.
466 final ArrayList<WindowState> mDestroyPreservedSurface = new ArrayList<>();
469 * Windows that have lost input focus and are waiting for the new
470 * focus window to be displayed before they are told about this.
472 ArrayList<WindowState> mLosingFocus = new ArrayList<>();
475 * This is set when we have run out of memory, and will either be an empty
476 * list or contain windows that need to be force removed.
478 final ArrayList<WindowState> mForceRemoves = new ArrayList<>();
481 * Windows that clients are waiting to have drawn.
483 ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>();
485 * And the callback to make when they've all been drawn.
487 Runnable mWaitingForDrawnCallback;
490 * Stores for each user whether screencapture is disabled
491 * This array is essentially a cache for all userId for
492 * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled}
494 SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>();
496 IInputMethodManager mInputMethodManager;
498 AccessibilityController mAccessibilityController;
500 final SurfaceSession mFxSession;
501 Watermark mWatermark;
502 StrictModeFlash mStrictModeFlash;
503 CircularDisplayMask mCircularDisplayMask;
504 EmulatorDisplayOverlay mEmulatorDisplayOverlay;
506 final float[] mTmpFloats = new float[9];
507 final Rect mTmpRect = new Rect();
508 final Rect mTmpRect2 = new Rect();
509 final Rect mTmpRect3 = new Rect();
510 final RectF mTmpRectF = new RectF();
512 final Matrix mTmpTransform = new Matrix();
514 boolean mDisplayReady;
516 boolean mDisplayEnabled = false;
517 boolean mSystemBooted = false;
518 boolean mForceDisplayEnabled = false;
519 boolean mShowingBootMessages = false;
520 boolean mBootAnimationStopped = false;
522 // Following variables are for debugging screen wakelock only.
523 WindowState mLastWakeLockHoldingWindow = null;
524 WindowState mLastWakeLockObscuringWindow = null;
526 /** Dump of the windows and app tokens at the time of the last ANR. Cleared after
527 * LAST_ANR_LIFETIME_DURATION_MSECS */
528 String mLastANRState;
530 // The root of the device window hierarchy.
531 RootWindowContainer mRoot;
533 int mDockedStackCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
534 Rect mDockedStackCreateBounds;
536 private final SparseIntArray mTmpTaskIds = new SparseIntArray();
538 boolean mForceResizableTasks = false;
539 boolean mSupportsPictureInPicture = false;
541 int getDragLayerLocked() {
542 return mPolicy.getWindowLayerFromTypeLw(TYPE_DRAG) * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
545 class RotationWatcher {
546 IRotationWatcher mWatcher;
547 IBinder.DeathRecipient mDeathRecipient;
549 RotationWatcher(IRotationWatcher watcher, IBinder.DeathRecipient deathRecipient,
552 mDeathRecipient = deathRecipient;
553 mDisplayId = displayId;
557 ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<>();
558 int mDeferredRotationPauseCount;
560 int mSystemDecorLayer = 0;
561 final Rect mScreenRect = new Rect();
563 boolean mDisplayFrozen = false;
564 long mDisplayFreezeTime = 0;
565 int mLastDisplayFreezeDuration = 0;
566 Object mLastFinishedFreezeSource = null;
567 boolean mWaitingForConfig = false;
568 boolean mSwitchingUser = false;
570 final static int WINDOWS_FREEZING_SCREENS_NONE = 0;
571 final static int WINDOWS_FREEZING_SCREENS_ACTIVE = 1;
572 final static int WINDOWS_FREEZING_SCREENS_TIMEOUT = 2;
573 int mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
575 boolean mClientFreezingScreen = false;
576 int mAppsFreezingScreen = 0;
580 // Last systemUiVisibility we received from status bar.
581 int mLastStatusBarVisibility = 0;
582 // Last systemUiVisibility we dispatched to windows.
583 int mLastDispatchedSystemUiVisibility = 0;
585 // State while inside of layoutAndPlaceSurfacesLocked().
586 boolean mFocusMayChange;
588 // This is held as long as we have the screen frozen, to give us time to
589 // perform a rotation animation when turning off shows the lock screen which
590 // changes the orientation.
591 private final PowerManager.WakeLock mScreenFrozenLock;
593 final AppTransition mAppTransition;
594 boolean mSkipAppTransitionAnimation = false;
596 final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<>();
597 final ArraySet<AppWindowToken> mClosingApps = new ArraySet<>();
599 final UnknownAppVisibilityController mUnknownAppVisibilityController =
600 new UnknownAppVisibilityController(this);
601 final TaskSnapshotController mTaskSnapshotController = new TaskSnapshotController(this);
603 boolean mIsTouchDevice;
605 final H mH = new H();
608 * Handler for things to run that have direct impact on an animation, i.e. animation tick,
609 * layout, starting window creation, whereas {@link H} runs things that are still important, but
612 final Handler mAnimationHandler = new Handler(AnimationThread.getHandler().getLooper());
614 WindowState mCurrentFocus = null;
615 WindowState mLastFocus = null;
617 /** This just indicates the window the input method is on top of, not
618 * necessarily the window its input is going to. */
619 WindowState mInputMethodTarget = null;
621 /** If true hold off on modifying the animation layer of mInputMethodTarget */
622 boolean mInputMethodTargetWaitingAnim;
624 WindowState mInputMethodWindow = null;
626 boolean mHardKeyboardAvailable;
627 WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
628 SettingsObserver mSettingsObserver;
630 // A count of the windows which are 'seamlessly rotated', e.g. a surface
631 // at an old orientation is being transformed. We freeze orientation updates
632 // while any windows are seamlessly rotated, so we need to track when this
633 // hits zero so we can apply deferred orientation updates.
634 int mSeamlessRotationCount = 0;
636 private final class SettingsObserver extends ContentObserver {
637 private final Uri mDisplayInversionEnabledUri =
638 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
639 private final Uri mWindowAnimationScaleUri =
640 Settings.Global.getUriFor(Settings.Global.WINDOW_ANIMATION_SCALE);
641 private final Uri mTransitionAnimationScaleUri =
642 Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE);
643 private final Uri mAnimationDurationScaleUri =
644 Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE);
646 public SettingsObserver() {
647 super(new Handler());
648 ContentResolver resolver = mContext.getContentResolver();
649 resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this,
650 UserHandle.USER_ALL);
651 resolver.registerContentObserver(mWindowAnimationScaleUri, false, this,
652 UserHandle.USER_ALL);
653 resolver.registerContentObserver(mTransitionAnimationScaleUri, false, this,
654 UserHandle.USER_ALL);
655 resolver.registerContentObserver(mAnimationDurationScaleUri, false, this,
656 UserHandle.USER_ALL);
660 public void onChange(boolean selfChange, Uri uri) {
665 if (mDisplayInversionEnabledUri.equals(uri)) {
666 updateCircularDisplayMaskIfNeeded();
668 @UpdateAnimationScaleMode
670 if (mWindowAnimationScaleUri.equals(uri)) {
671 mode = WINDOW_ANIMATION_SCALE;
672 } else if (mTransitionAnimationScaleUri.equals(uri)) {
673 mode = TRANSITION_ANIMATION_SCALE;
674 } else if (mAnimationDurationScaleUri.equals(uri)) {
675 mode = ANIMATION_DURATION_SCALE;
677 // Ignoring unrecognized content changes
680 Message m = mH.obtainMessage(H.UPDATE_ANIMATION_SCALE, mode, 0);
686 boolean mAnimateWallpaperWithTarget;
688 // TODO: Move to RootWindowContainer
689 AppWindowToken mFocusedApp = null;
691 PowerManager mPowerManager;
692 PowerManagerInternal mPowerManagerInternal;
694 private float mWindowAnimationScaleSetting = 1.0f;
695 private float mTransitionAnimationScaleSetting = 1.0f;
696 private float mAnimatorDurationScaleSetting = 1.0f;
697 private boolean mAnimationsDisabled = false;
699 final InputManagerService mInputManager;
700 final DisplayManagerInternal mDisplayManagerInternal;
701 final DisplayManager mDisplayManager;
702 private final Display[] mDisplays;
704 // Who is holding the screen on.
705 private Session mHoldingScreenOn;
706 private PowerManager.WakeLock mHoldingScreenWakeLock;
708 boolean mTurnOnScreen;
710 // Whether or not a layout can cause a wake up when theater mode is enabled.
711 boolean mAllowTheaterModeWakeFromLayout;
713 TaskPositioner mTaskPositioner;
714 DragState mDragState = null;
716 // For frozen screen animations.
717 private int mExitAnimId, mEnterAnimId;
719 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
720 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
721 int mTransactionSequence;
723 final WindowAnimator mAnimator;
725 final BoundsAnimationController mBoundsAnimationController;
727 private final PointerEventDispatcher mPointerEventDispatcher;
729 private WindowContentFrameStats mTempWindowRenderStats;
731 final class DragInputEventReceiver extends InputEventReceiver {
732 // Set, if stylus button was down at the start of the drag.
733 private boolean mStylusButtonDownAtStart;
734 // Indicates the first event to check for button state.
735 private boolean mIsStartEvent = true;
736 // Set to true to ignore input events after the drag gesture is complete but the drag events
737 // are still being dispatched.
738 private boolean mMuteInput = false;
740 public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
741 super(inputChannel, looper);
745 public void onInputEvent(InputEvent event) {
746 boolean handled = false;
748 if (mDragState == null) {
749 // The drag has ended but the clean-up message has not been processed by
750 // window manager. Drop events that occur after this until window manager
751 // has a chance to clean-up the input handle.
755 if (event instanceof MotionEvent
756 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0
758 final MotionEvent motionEvent = (MotionEvent)event;
759 boolean endDrag = false;
760 final float newX = motionEvent.getRawX();
761 final float newY = motionEvent.getRawY();
762 final boolean isStylusButtonDown =
763 (motionEvent.getButtonState() & MotionEvent.BUTTON_STYLUS_PRIMARY) != 0;
766 if (isStylusButtonDown) {
767 // First event and the button was down, check for the button being
768 // lifted in the future, if that happens we'll drop the item.
769 mStylusButtonDownAtStart = true;
771 mIsStartEvent = false;
774 switch (motionEvent.getAction()) {
775 case MotionEvent.ACTION_DOWN: {
777 Slog.w(TAG_WM, "Unexpected ACTION_DOWN in drag layer");
781 case MotionEvent.ACTION_MOVE: {
782 if (mStylusButtonDownAtStart && !isStylusButtonDown) {
783 if (DEBUG_DRAG) Slog.d(TAG_WM, "Button no longer pressed; dropping at "
784 + newX + "," + newY);
786 synchronized (mWindowMap) {
787 endDrag = mDragState.notifyDropLw(newX, newY);
790 synchronized (mWindowMap) {
791 // move the surface and tell the involved window(s) where we are
792 mDragState.notifyMoveLw(newX, newY);
797 case MotionEvent.ACTION_UP: {
798 if (DEBUG_DRAG) Slog.d(TAG_WM, "Got UP on move channel; dropping at "
799 + newX + "," + newY);
801 synchronized (mWindowMap) {
802 endDrag = mDragState.notifyDropLw(newX, newY);
806 case MotionEvent.ACTION_CANCEL: {
807 if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag cancelled!");
814 if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ended; tearing down state");
815 // tell all the windows that the drag has ended
816 synchronized (mWindowMap) {
817 // endDragLw will post back to looper to dispose the receiver
818 // since we still need the receiver for the last finishInputEvent.
819 mDragState.endDragLw();
821 mStylusButtonDownAtStart = false;
822 mIsStartEvent = true;
827 } catch (Exception e) {
828 Slog.e(TAG_WM, "Exception caught by drag handleMotion", e);
830 finishInputEvent(event, handled);
836 * Whether the UI is currently running in touch mode (not showing
837 * navigational focus because the user is directly pressing the screen).
839 boolean mInTouchMode;
841 private ViewServer mViewServer;
842 final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
843 boolean mWindowsChanged = false;
845 public interface WindowChangeListener {
846 public void windowsChanged();
847 public void focusChanged();
850 final Configuration mTempConfiguration = new Configuration();
852 // If true, only the core apps and services are being launched because the device
853 // is in a special boot mode, such as being encrypted or waiting for a decryption password.
854 // For example, when this flag is true, there will be no wallpaper service.
855 final boolean mOnlyCore;
857 // List of clients without a transtiton animation that we notify once we are done transitioning
858 // since they won't be notified through the app window animator.
859 final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
861 private static ThreadPriorityBooster sThreadPriorityBooster = new ThreadPriorityBooster(
862 THREAD_PRIORITY_DISPLAY, INDEX_WINDOW);
864 static void boostPriorityForLockedSection() {
865 sThreadPriorityBooster.boost();
868 static void resetPriorityAfterLockedSection() {
869 sThreadPriorityBooster.reset();
872 void openSurfaceTransaction() {
873 synchronized (mWindowMap) {
874 if (mRoot.mSurfaceTraceEnabled) {
875 mRoot.mRemoteEventTrace.openSurfaceTransaction();
877 SurfaceControl.openTransaction();
881 void closeSurfaceTransaction() {
882 synchronized (mWindowMap) {
883 if (mRoot.mSurfaceTraceEnabled) {
884 mRoot.mRemoteEventTrace.closeSurfaceTransaction();
886 SurfaceControl.closeTransaction();
890 /** Listener to notify activity manager about app transitions. */
891 final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier
892 = new WindowManagerInternal.AppTransitionListener() {
895 public void onAppTransitionCancelledLocked(int transit) {
896 mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_CANCELLED);
900 public void onAppTransitionFinishedLocked(IBinder token) {
901 mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_FINISHED);
902 final AppWindowToken atoken = mRoot.getAppWindowToken(token);
903 if (atoken == null) {
906 if (atoken.mLaunchTaskBehind) {
908 mActivityManager.notifyLaunchTaskBehindComplete(atoken.token);
909 } catch (RemoteException e) {
911 atoken.mLaunchTaskBehind = false;
913 atoken.updateReportedVisibilityLocked();
914 if (atoken.mEnteringAnimation) {
915 atoken.mEnteringAnimation = false;
917 mActivityManager.notifyEnterAnimationComplete(atoken.token);
918 } catch (RemoteException e) {
925 final ArrayList<AppFreezeListener> mAppFreezeListeners = new ArrayList<>();
927 interface AppFreezeListener {
928 void onAppFreezeTimeout();
931 private static WindowManagerService sInstance;
932 static WindowManagerService getInstance() {
936 public static WindowManagerService main(final Context context, final InputManagerService im,
937 final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
938 WindowManagerPolicy policy) {
939 DisplayThread.getHandler().runWithScissors(() ->
940 sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
941 onlyCore, policy), 0);
945 private void initPolicy() {
946 UiThread.getHandler().runWithScissors(new Runnable() {
949 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
951 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
956 private WindowManagerService(Context context, InputManagerService inputManager,
957 boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
958 WindowManagerPolicy policy) {
959 installLock(this, INDEX_WINDOW);
960 mRoot = new RootWindowContainer(this);
962 mHaveInputMethods = haveInputMethods;
963 mAllowBootMessages = showBootMsgs;
964 mOnlyCore = onlyCore;
965 mLimitedAlphaCompositing = context.getResources().getBoolean(
966 com.android.internal.R.bool.config_sf_limitedAlpha);
967 mHasPermanentDpad = context.getResources().getBoolean(
968 com.android.internal.R.bool.config_hasPermanentDpad);
969 mInTouchMode = context.getResources().getBoolean(
970 com.android.internal.R.bool.config_defaultInTouchMode);
971 mDrawLockTimeoutMillis = context.getResources().getInteger(
972 com.android.internal.R.integer.config_drawLockTimeoutMillis);
973 mAllowAnimationsInLowPowerMode = context.getResources().getBoolean(
974 com.android.internal.R.bool.config_allowAnimationsInLowPowerMode);
975 mMaxUiWidth = context.getResources().getInteger(
976 com.android.internal.R.integer.config_maxUiWidth);
977 mInputManager = inputManager; // Must be before createDisplayContentLocked.
978 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
979 mDisplaySettings = new DisplaySettings();
980 mDisplaySettings.readSettingsLocked();
982 mWindowPlacerLocked = new WindowSurfacePlacer(this);
985 LocalServices.addService(WindowManagerPolicy.class, mPolicy);
987 if(mInputManager != null) {
988 final InputChannel inputChannel = mInputManager.monitorInput(TAG_WM);
989 mPointerEventDispatcher = inputChannel != null
990 ? new PointerEventDispatcher(inputChannel) : null;
992 mPointerEventDispatcher = null;
995 mFxSession = new SurfaceSession();
996 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
997 mDisplays = mDisplayManager.getDisplays();
998 for (Display display : mDisplays) {
999 createDisplayContentLocked(display);
1002 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
1004 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1005 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
1007 if (mPowerManagerInternal != null) {
1008 mPowerManagerInternal.registerLowPowerModeObserver(
1009 new PowerManagerInternal.LowPowerModeListener() {
1011 public int getServiceType() {
1012 return ServiceType.ANIMATION;
1016 public void onLowPowerModeChanged(PowerSaveState result) {
1017 synchronized (mWindowMap) {
1018 final boolean enabled = result.batterySaverEnabled;
1019 if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
1020 mAnimationsDisabled = enabled;
1021 dispatchNewAnimatorScaleLocked(null);
1026 mAnimationsDisabled = mPowerManagerInternal
1027 .getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled;
1029 mScreenFrozenLock = mPowerManager.newWakeLock(
1030 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
1031 mScreenFrozenLock.setReferenceCounted(false);
1033 mAppTransition = new AppTransition(context, this);
1034 mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier);
1036 mBoundsAnimationController = new BoundsAnimationController(context, mAppTransition,
1037 UiThread.getHandler());
1039 mActivityManager = ActivityManager.getService();
1040 mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
1041 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
1042 AppOpsManager.OnOpChangedInternalListener opListener =
1043 new AppOpsManager.OnOpChangedInternalListener() {
1044 @Override public void onOpChanged(int op, String packageName) {
1045 updateAppOpsState();
1048 mAppOps.startWatchingMode(OP_SYSTEM_ALERT_WINDOW, null, opListener);
1049 mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener);
1051 // Get persisted window scale setting
1052 mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
1053 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
1054 mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
1055 Settings.Global.TRANSITION_ANIMATION_SCALE,
1056 context.getResources().getFloat(
1057 R.dimen.config_appTransitionAnimationDurationScaleDefault));
1059 setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
1060 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
1062 IntentFilter filter = new IntentFilter();
1063 // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
1064 filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
1065 // Listen to user removal broadcasts so that we can remove the user-specific data.
1066 filter.addAction(Intent.ACTION_USER_REMOVED);
1067 mContext.registerReceiver(mBroadcastReceiver, filter);
1069 mSettingsObserver = new SettingsObserver();
1071 mHoldingScreenWakeLock = mPowerManager.newWakeLock(
1072 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
1073 mHoldingScreenWakeLock.setReferenceCounted(false);
1075 mAnimator = new WindowAnimator(this);
1077 mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
1078 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
1081 LocalServices.addService(WindowManagerInternal.class, new LocalService());
1084 // Add ourself to the Watchdog monitors.
1085 Watchdog.getInstance().addMonitor(this);
1087 openSurfaceTransaction();
1089 createWatermarkInTransaction();
1091 closeSurfaceTransaction();
1094 showEmulatorDisplayOverlayIfNeeded();
1097 public InputMonitor getInputMonitor() {
1098 return mInputMonitor;
1102 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1103 throws RemoteException {
1105 return super.onTransact(code, data, reply, flags);
1106 } catch (RuntimeException e) {
1107 // The window manager only throws security exceptions, so let's
1109 if (!(e instanceof SecurityException)) {
1110 Slog.wtf(TAG_WM, "Window Manager Crash", e);
1116 static boolean excludeWindowTypeFromTapOutTask(int windowType) {
1117 switch (windowType) {
1118 case TYPE_STATUS_BAR:
1119 case TYPE_NAVIGATION_BAR:
1120 case TYPE_INPUT_METHOD_DIALOG:
1126 public int addWindow(Session session, IWindow client, int seq,
1127 WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
1128 Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
1129 InputChannel outInputChannel) {
1130 int[] appOp = new int[1];
1131 int res = mPolicy.checkAddPermission(attrs, appOp);
1132 if (res != WindowManagerGlobal.ADD_OKAY) {
1136 boolean reportNewConfig = false;
1137 WindowState parentWindow = null;
1139 final int callingUid = Binder.getCallingUid();
1140 final int type = attrs.type;
1142 synchronized(mWindowMap) {
1143 if (!mDisplayReady) {
1144 throw new IllegalStateException("Display has not been initialialized");
1147 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
1148 if (displayContent == null) {
1149 Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "
1150 + displayId + ". Aborting.");
1151 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1153 if (!displayContent.hasAccess(session.mUid)
1154 && !mDisplayManagerInternal.isUidPresentOnDisplay(session.mUid, displayId)) {
1155 Slog.w(TAG_WM, "Attempted to add window to a display for which the application "
1156 + "does not have access: " + displayId + ". Aborting.");
1157 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1160 if (mWindowMap.containsKey(client.asBinder())) {
1161 Slog.w(TAG_WM, "Window " + client + " is already added");
1162 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
1165 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
1166 parentWindow = windowForClientLocked(null, attrs.token, false);
1167 if (parentWindow == null) {
1168 Slog.w(TAG_WM, "Attempted to add window with token that is not a window: "
1169 + attrs.token + ". Aborting.");
1170 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
1172 if (parentWindow.mAttrs.type >= FIRST_SUB_WINDOW
1173 && parentWindow.mAttrs.type <= LAST_SUB_WINDOW) {
1174 Slog.w(TAG_WM, "Attempted to add window with token that is a sub-window: "
1175 + attrs.token + ". Aborting.");
1176 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
1180 if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
1181 Slog.w(TAG_WM, "Attempted to add private presentation window to a non-private display. Aborting.");
1182 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
1185 AppWindowToken atoken = null;
1186 final boolean hasParent = parentWindow != null;
1187 // Use existing parent window token for child windows since they go in the same token
1188 // as there parent window so we can apply the same policy on them.
1189 WindowToken token = displayContent.getWindowToken(
1190 hasParent ? parentWindow.mAttrs.token : attrs.token);
1191 // If this is a child window, we want to apply the same type checking rules as the
1192 // parent window type.
1193 final int rootType = hasParent ? parentWindow.mAttrs.type : type;
1195 boolean addToastWindowRequiresToken = false;
1197 if (token == null) {
1198 if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
1199 Slog.w(TAG_WM, "Attempted to add application window with unknown token "
1200 + attrs.token + ". Aborting.");
1201 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1203 if (rootType == TYPE_INPUT_METHOD) {
1204 Slog.w(TAG_WM, "Attempted to add input method window with unknown token "
1205 + attrs.token + ". Aborting.");
1206 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1208 if (rootType == TYPE_VOICE_INTERACTION) {
1209 Slog.w(TAG_WM, "Attempted to add voice interaction window with unknown token "
1210 + attrs.token + ". Aborting.");
1211 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1213 if (rootType == TYPE_WALLPAPER) {
1214 Slog.w(TAG_WM, "Attempted to add wallpaper window with unknown token "
1215 + attrs.token + ". Aborting.");
1216 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1218 if (rootType == TYPE_DREAM) {
1219 Slog.w(TAG_WM, "Attempted to add Dream window with unknown token "
1220 + attrs.token + ". Aborting.");
1221 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1223 if (rootType == TYPE_QS_DIALOG) {
1224 Slog.w(TAG_WM, "Attempted to add QS dialog window with unknown token "
1225 + attrs.token + ". Aborting.");
1226 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1228 if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
1229 Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with unknown token "
1230 + attrs.token + ". Aborting.");
1231 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1233 if (type == TYPE_TOAST) {
1234 // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
1235 if (doesAddToastWindowRequireToken(attrs.packageName, callingUid,
1237 Slog.w(TAG_WM, "Attempted to add a toast window with unknown token "
1238 + attrs.token + ". Aborting.");
1239 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1242 token = new WindowToken(this, attrs.token, type, false, displayContent,
1243 session.mCanAddInternalSystemWindow);
1244 } else if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
1245 atoken = token.asAppWindowToken();
1246 if (atoken == null) {
1247 Slog.w(TAG_WM, "Attempted to add window with non-application token "
1248 + token + ". Aborting.");
1249 return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
1250 } else if (atoken.removed) {
1251 Slog.w(TAG_WM, "Attempted to add window with exiting application token "
1252 + token + ". Aborting.");
1253 return WindowManagerGlobal.ADD_APP_EXITING;
1255 if (rootType == TYPE_APPLICATION_STARTING
1256 && (attrs.privateFlags & PRIVATE_FLAG_TASK_SNAPSHOT) == 0
1257 && atoken.firstWindowDrawn) {
1258 // No need for this guy!
1259 if (DEBUG_STARTING_WINDOW || localLOGV) Slog.v(
1260 TAG_WM, "**** NO NEED TO START: " + attrs.getTitle());
1261 return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
1263 } else if (rootType == TYPE_INPUT_METHOD) {
1264 if (token.windowType != TYPE_INPUT_METHOD) {
1265 Slog.w(TAG_WM, "Attempted to add input method window with bad token "
1266 + attrs.token + ". Aborting.");
1267 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1269 } else if (rootType == TYPE_VOICE_INTERACTION) {
1270 if (token.windowType != TYPE_VOICE_INTERACTION) {
1271 Slog.w(TAG_WM, "Attempted to add voice interaction window with bad token "
1272 + attrs.token + ". Aborting.");
1273 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1275 } else if (rootType == TYPE_WALLPAPER) {
1276 if (token.windowType != TYPE_WALLPAPER) {
1277 Slog.w(TAG_WM, "Attempted to add wallpaper window with bad token "
1278 + attrs.token + ". Aborting.");
1279 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1281 } else if (rootType == TYPE_DREAM) {
1282 if (token.windowType != TYPE_DREAM) {
1283 Slog.w(TAG_WM, "Attempted to add Dream window with bad token "
1284 + attrs.token + ". Aborting.");
1285 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1287 } else if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
1288 if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
1289 Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with bad token "
1290 + attrs.token + ". Aborting.");
1291 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1293 } else if (type == TYPE_TOAST) {
1294 // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
1295 addToastWindowRequiresToken = doesAddToastWindowRequireToken(attrs.packageName,
1296 callingUid, parentWindow);
1297 if (addToastWindowRequiresToken && token.windowType != TYPE_TOAST) {
1298 Slog.w(TAG_WM, "Attempted to add a toast window with bad token "
1299 + attrs.token + ". Aborting.");
1300 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1302 } else if (type == TYPE_QS_DIALOG) {
1303 if (token.windowType != TYPE_QS_DIALOG) {
1304 Slog.w(TAG_WM, "Attempted to add QS dialog window with bad token "
1305 + attrs.token + ". Aborting.");
1306 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1308 } else if (token.asAppWindowToken() != null) {
1309 Slog.w(TAG_WM, "Non-null appWindowToken for system window of rootType=" + rootType);
1310 // It is not valid to use an app token with other system types; we will
1311 // instead make a new token for it (as if null had been passed in for the token).
1313 token = new WindowToken(this, null, type, false, displayContent,
1314 session.mCanAddInternalSystemWindow);
1317 final WindowState win = new WindowState(this, session, client, token, parentWindow,
1318 appOp[0], seq, attrs, viewVisibility, session.mUid,
1319 session.mCanAddInternalSystemWindow);
1320 if (win.mDeathRecipient == null) {
1321 // Client has apparently died, so there is no reason to
1323 Slog.w(TAG_WM, "Adding window client " + client.asBinder()
1324 + " that is dead, aborting.");
1325 return WindowManagerGlobal.ADD_APP_EXITING;
1328 if (win.getDisplayContent() == null) {
1329 Slog.w(TAG_WM, "Adding window to Display that has been removed.");
1330 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1333 mPolicy.adjustWindowParamsLw(win.mAttrs);
1334 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
1336 res = mPolicy.prepareAddWindowLw(win, attrs);
1337 if (res != WindowManagerGlobal.ADD_OKAY) {
1341 final boolean openInputChannels = (outInputChannel != null
1342 && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
1343 if (openInputChannels) {
1344 win.openInputChannel(outInputChannel);
1347 // If adding a toast requires a token for this app we always schedule hiding
1348 // toast windows to make sure they don't stick around longer then necessary.
1349 // We hide instead of remove such windows as apps aren't prepared to handle
1350 // windows being removed under them.
1352 // If the app is older it can add toasts without a token and hence overlay
1353 // other apps. To be maximally compatible with these apps we will hide the
1354 // window after the toast timeout only if the focused window is from another
1355 // UID, otherwise we allow unlimited duration. When a UID looses focus we
1356 // schedule hiding all of its toast windows.
1357 if (type == TYPE_TOAST) {
1358 if (!getDefaultDisplayContentLocked().canAddToastWindowForUid(callingUid)) {
1359 Slog.w(TAG_WM, "Adding more than one toast window for UID at a time.");
1360 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
1362 // Make sure this happens before we moved focus as one can make the
1363 // toast focusable to force it not being hidden after the timeout.
1364 // Focusable toasts are always timed out to prevent a focused app to
1365 // show a focusable toasts while it has focus which will be kept on
1366 // the screen after the activity goes away.
1367 if (addToastWindowRequiresToken
1368 || (attrs.flags & LayoutParams.FLAG_NOT_FOCUSABLE) == 0
1369 || mCurrentFocus == null
1370 || mCurrentFocus.mOwnerUid != callingUid) {
1371 mH.sendMessageDelayed(
1372 mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, win),
1373 win.mAttrs.hideTimeoutMilliseconds);
1377 // From now on, no exceptions or errors allowed!
1379 res = WindowManagerGlobal.ADD_OKAY;
1381 if (excludeWindowTypeFromTapOutTask(type)) {
1382 displayContent.mTapExcludedWindows.add(win);
1385 origId = Binder.clearCallingIdentity();
1388 mWindowMap.put(client.asBinder(), win);
1389 if (win.mAppOp != AppOpsManager.OP_NONE) {
1390 int startOpResult = mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(),
1391 win.getOwningPackage());
1392 if ((startOpResult != AppOpsManager.MODE_ALLOWED) &&
1393 (startOpResult != AppOpsManager.MODE_DEFAULT)) {
1394 win.setAppOpVisibilityLw(false);
1398 final AppWindowToken aToken = token.asAppWindowToken();
1399 if (type == TYPE_APPLICATION_STARTING && aToken != null) {
1400 aToken.startingWindow = win;
1401 if (DEBUG_STARTING_WINDOW) Slog.v (TAG_WM, "addWindow: " + aToken
1402 + " startingWindow=" + win);
1405 boolean imMayMove = true;
1407 win.mToken.addWindow(win);
1408 if (type == TYPE_INPUT_METHOD) {
1409 win.mGivenInsetsPending = true;
1410 setInputMethodWindowLocked(win);
1412 } else if (type == TYPE_INPUT_METHOD_DIALOG) {
1413 displayContent.computeImeTarget(true /* updateImeTarget */);
1416 if (type == TYPE_WALLPAPER) {
1417 displayContent.mWallpaperController.clearLastWallpaperTimeoutTime();
1418 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1419 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
1420 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1421 } else if (displayContent.mWallpaperController.isBelowWallpaperTarget(win)) {
1422 // If there is currently a wallpaper being shown, and
1423 // the base layer of the new window is below the current
1424 // layer of the target window, then adjust the wallpaper.
1425 // This is to avoid a new window being placed between the
1426 // wallpaper and its target.
1427 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1431 // If the window is being added to a stack that's currently adjusted for IME,
1432 // make sure to apply the same adjust to this new window.
1433 win.applyAdjustForImeIfNeeded();
1435 if (type == TYPE_DOCK_DIVIDER) {
1436 mRoot.getDisplayContent(displayId).getDockedDividerController().setWindow(win);
1439 final WindowStateAnimator winAnimator = win.mWinAnimator;
1440 winAnimator.mEnterAnimationPending = true;
1441 winAnimator.mEnteringAnimation = true;
1442 // Check if we need to prepare a transition for replacing window first.
1443 if (atoken != null && atoken.isVisible()
1444 && !prepareWindowReplacementTransition(atoken)) {
1445 // If not, check if need to set up a dummy transition during display freeze
1446 // so that the unfreeze wait for the apps to draw. This might be needed if
1447 // the app is relaunching.
1448 prepareNoneTransitionForRelaunching(atoken);
1451 if (displayContent.isDefaultDisplay) {
1452 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
1453 final Rect taskBounds;
1454 if (atoken != null && atoken.getTask() != null) {
1455 taskBounds = mTmpRect;
1456 atoken.getTask().getBounds(mTmpRect);
1460 if (mPolicy.getInsetHintLw(win.mAttrs, taskBounds, displayInfo.rotation,
1461 displayInfo.logicalWidth, displayInfo.logicalHeight, outContentInsets,
1462 outStableInsets, outOutsets)) {
1463 res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR;
1466 outContentInsets.setEmpty();
1467 outStableInsets.setEmpty();
1471 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
1473 if (win.mAppToken == null || !win.mAppToken.clientHidden) {
1474 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
1477 mInputMonitor.setUpdateInputWindowsNeededLw();
1479 boolean focusChanged = false;
1480 if (win.canReceiveKeys()) {
1481 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
1482 false /*updateInputWindows*/);
1489 displayContent.computeImeTarget(true /* updateImeTarget */);
1492 // Don't do layout here, the window must call
1493 // relayout to be displayed, so we'll do it there.
1494 displayContent.assignWindowLayers(false /* setLayoutNeeded */);
1497 mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
1499 mInputMonitor.updateInputWindowsLw(false /*force*/);
1501 if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client "
1502 + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5));
1504 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false, displayId)) {
1505 reportNewConfig = true;
1509 if (reportNewConfig) {
1510 sendNewConfiguration(displayId);
1513 Binder.restoreCallingIdentity(origId);
1518 private boolean doesAddToastWindowRequireToken(String packageName, int callingUid,
1519 WindowState attachedWindow) {
1520 // Try using the target SDK of the root window
1521 if (attachedWindow != null) {
1522 return attachedWindow.mAppToken != null
1523 && attachedWindow.mAppToken.mTargetSdk > Build.VERSION_CODES.N_MR1;
1525 // Otherwise, look at the package
1527 ApplicationInfo appInfo = mContext.getPackageManager()
1528 .getApplicationInfoAsUser(packageName, 0,
1529 UserHandle.getUserId(callingUid));
1530 if (appInfo.uid != callingUid) {
1531 throw new SecurityException("Package " + packageName + " not in UID "
1534 if (appInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1) {
1537 } catch (PackageManager.NameNotFoundException e) {
1545 * Returns true if we're done setting up any transitions.
1547 private boolean prepareWindowReplacementTransition(AppWindowToken atoken) {
1548 atoken.clearAllDrawn();
1549 final WindowState replacedWindow = atoken.getReplacingWindow();
1550 if (replacedWindow == null) {
1551 // We expect to already receive a request to remove the old window. If it did not
1552 // happen, let's just simply add a window.
1555 // We use the visible frame, because we want the animation to morph the window from what
1556 // was visible to the user to the final destination of the new window.
1557 Rect frame = replacedWindow.mVisibleFrame;
1558 // We treat this as if this activity was opening, so we can trigger the app transition
1559 // animation and piggy-back on existing transition animation infrastructure.
1560 mOpeningApps.add(atoken);
1561 prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_RELAUNCH, ALWAYS_KEEP_CURRENT);
1562 mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top,
1563 frame.width(), frame.height());
1564 executeAppTransition();
1568 private void prepareNoneTransitionForRelaunching(AppWindowToken atoken) {
1569 // Set up a none-transition and add the app to opening apps, so that the display
1570 // unfreeze wait for the apps to be drawn.
1571 // Note that if the display unfroze already because app unfreeze timed out,
1572 // we don't set up the transition anymore and just let it go.
1573 if (mDisplayFrozen && !mOpeningApps.contains(atoken) && atoken.isRelaunching()) {
1574 mOpeningApps.add(atoken);
1575 prepareAppTransition(AppTransition.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT);
1576 executeAppTransition();
1581 * Returns whether screen capture is disabled for all windows of a specific user.
1583 boolean isScreenCaptureDisabledLocked(int userId) {
1584 Boolean disabled = mScreenCaptureDisabled.get(userId);
1585 if (disabled == null) {
1591 boolean isSecureLocked(WindowState w) {
1592 if ((w.mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
1595 if (isScreenCaptureDisabledLocked(UserHandle.getUserId(w.mOwnerUid))) {
1602 public void enableSurfaceTrace(ParcelFileDescriptor pfd) {
1603 final int callingUid = Binder.getCallingUid();
1604 if (callingUid != SHELL_UID && callingUid != ROOT_UID) {
1605 throw new SecurityException("Only shell can call enableSurfaceTrace");
1608 synchronized (mWindowMap) {
1609 mRoot.enableSurfaceTrace(pfd);
1614 public void disableSurfaceTrace() {
1615 final int callingUid = Binder.getCallingUid();
1616 if (callingUid != SHELL_UID && callingUid != ROOT_UID &&
1617 callingUid != SYSTEM_UID) {
1618 throw new SecurityException("Only shell can call disableSurfaceTrace");
1620 synchronized (mWindowMap) {
1621 mRoot.disableSurfaceTrace();
1626 * Set mScreenCaptureDisabled for specific user
1629 public void setScreenCaptureDisabled(int userId, boolean disabled) {
1630 int callingUid = Binder.getCallingUid();
1631 if (callingUid != SYSTEM_UID) {
1632 throw new SecurityException("Only system can call setScreenCaptureDisabled.");
1635 synchronized(mWindowMap) {
1636 mScreenCaptureDisabled.put(userId, disabled);
1637 // Update secure surface for all windows belonging to this user.
1638 mRoot.setSecureSurfaceState(userId, disabled);
1642 void removeWindow(Session session, IWindow client) {
1643 synchronized(mWindowMap) {
1644 WindowState win = windowForClientLocked(session, client, false);
1648 win.removeIfPossible();
1653 * Performs some centralized bookkeeping clean-up on the window that is being removed.
1654 * NOTE: Should only be called from {@link WindowState#removeImmediately()}
1655 * TODO: Maybe better handled with a method {@link WindowContainer#removeChild} if we can
1656 * figure-out a good way to have all parents of a WindowState doing the same thing without
1657 * forgetting to add the wiring when a new parent of WindowState is added.
1659 void postWindowRemoveCleanupLocked(WindowState win) {
1660 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "postWindowRemoveCleanupLocked: " + win);
1661 mWindowMap.remove(win.mClient.asBinder());
1662 if (win.mAppOp != AppOpsManager.OP_NONE) {
1663 mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
1666 mPendingRemove.remove(win);
1667 mResizingWindows.remove(win);
1668 mWindowsChanged = true;
1669 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Final remove of window: " + win);
1671 if (mInputMethodWindow == win) {
1672 setInputMethodWindowLocked(null);
1675 final WindowToken token = win.mToken;
1676 final AppWindowToken atoken = win.mAppToken;
1677 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Removing " + win + " from " + token);
1678 // Window will already be removed from token before this post clean-up method is called.
1679 if (token.isEmpty()) {
1680 if (!token.mPersistOnEmpty) {
1681 token.removeImmediately();
1682 } else if (atoken != null) {
1683 // TODO: Should this be moved into AppWindowToken.removeWindow? Might go away after
1685 atoken.firstWindowDrawn = false;
1686 atoken.clearAllDrawn();
1690 if (atoken != null) {
1691 atoken.postWindowRemoveStartingWindowCleanup(win);
1694 final DisplayContent dc = win.getDisplayContent();
1695 if (win.mAttrs.type == TYPE_WALLPAPER) {
1696 dc.mWallpaperController.clearLastWallpaperTimeoutTime();
1697 dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1698 } else if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
1699 dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1702 if (dc != null && !mWindowPlacerLocked.isInLayout()) {
1703 dc.assignWindowLayers(true /* setLayoutNeeded */);
1704 mWindowPlacerLocked.performSurfacePlacement();
1705 if (win.mAppToken != null) {
1706 win.mAppToken.updateReportedVisibilityLocked();
1710 mInputMonitor.updateInputWindowsLw(true /*force*/);
1713 void setInputMethodWindowLocked(WindowState win) {
1714 mInputMethodWindow = win;
1715 final DisplayContent dc = win != null
1716 ? win.getDisplayContent() : getDefaultDisplayContentLocked();
1717 dc.computeImeTarget(true /* updateImeTarget */);
1720 private void updateAppOpsState() {
1721 synchronized(mWindowMap) {
1722 mRoot.updateAppOpsState();
1726 static void logSurface(WindowState w, String msg, boolean withStackTrace) {
1727 String str = " SURFACE " + msg + ": " + w;
1728 if (withStackTrace) {
1729 logWithStack(TAG, str);
1731 Slog.i(TAG_WM, str);
1735 static void logSurface(SurfaceControl s, String title, String msg) {
1736 String str = " SURFACE " + s + ": " + msg + " / " + title;
1737 Slog.i(TAG_WM, str);
1740 static void logWithStack(String tag, String s) {
1741 RuntimeException e = null;
1742 if (SHOW_STACK_CRAWLS) {
1743 e = new RuntimeException();
1744 e.fillInStackTrace();
1749 void setTransparentRegionWindow(Session session, IWindow client, Region region) {
1750 long origId = Binder.clearCallingIdentity();
1752 synchronized (mWindowMap) {
1753 WindowState w = windowForClientLocked(session, client, false);
1754 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
1755 "transparentRegionHint=" + region, false);
1757 if ((w != null) && w.mHasSurface) {
1758 w.mWinAnimator.setTransparentRegionHintLocked(region);
1762 Binder.restoreCallingIdentity(origId);
1766 void setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets,
1767 Rect visibleInsets, Region touchableRegion) {
1768 long origId = Binder.clearCallingIdentity();
1770 synchronized (mWindowMap) {
1771 WindowState w = windowForClientLocked(session, client, false);
1772 if (DEBUG_LAYOUT) Slog.d(TAG, "setInsetsWindow " + w
1773 + ", contentInsets=" + w.mGivenContentInsets + " -> " + contentInsets
1774 + ", visibleInsets=" + w.mGivenVisibleInsets + " -> " + visibleInsets
1775 + ", touchableRegion=" + w.mGivenTouchableRegion + " -> " + touchableRegion
1776 + ", touchableInsets " + w.mTouchableInsets + " -> " + touchableInsets);
1778 w.mGivenInsetsPending = false;
1779 w.mGivenContentInsets.set(contentInsets);
1780 w.mGivenVisibleInsets.set(visibleInsets);
1781 w.mGivenTouchableRegion.set(touchableRegion);
1782 w.mTouchableInsets = touchableInsets;
1783 if (w.mGlobalScale != 1) {
1784 w.mGivenContentInsets.scale(w.mGlobalScale);
1785 w.mGivenVisibleInsets.scale(w.mGlobalScale);
1786 w.mGivenTouchableRegion.scale(w.mGlobalScale);
1788 w.setDisplayLayoutNeeded();
1789 mWindowPlacerLocked.performSurfacePlacement();
1793 Binder.restoreCallingIdentity(origId);
1797 public void getWindowDisplayFrame(Session session, IWindow client,
1798 Rect outDisplayFrame) {
1799 synchronized(mWindowMap) {
1800 WindowState win = windowForClientLocked(session, client, false);
1802 outDisplayFrame.setEmpty();
1805 outDisplayFrame.set(win.mDisplayFrame);
1809 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
1810 synchronized (mWindowMap) {
1811 if (mAccessibilityController != null) {
1812 WindowState window = mWindowMap.get(token);
1813 //TODO (multidisplay): Magnification is supported only for the default display.
1814 if (window != null && window.getDisplayId() == DEFAULT_DISPLAY) {
1815 mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle);
1821 public IWindowId getWindowId(IBinder token) {
1822 synchronized (mWindowMap) {
1823 WindowState window = mWindowMap.get(token);
1824 return window != null ? window.mWindowId : null;
1828 public void pokeDrawLock(Session session, IBinder token) {
1829 synchronized (mWindowMap) {
1830 WindowState window = windowForClientLocked(session, token, false);
1831 if (window != null) {
1832 window.pokeDrawLockLw(mDrawLockTimeoutMillis);
1837 public int relayoutWindow(Session session, IWindow client, int seq,
1838 WindowManager.LayoutParams attrs, int requestedWidth,
1839 int requestedHeight, int viewVisibility, int flags,
1840 Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
1841 Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
1842 MergedConfiguration mergedConfiguration, Surface outSurface) {
1844 boolean configChanged;
1845 boolean hasStatusBarPermission =
1846 mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
1847 == PackageManager.PERMISSION_GRANTED;
1849 long origId = Binder.clearCallingIdentity();
1850 final int displayId;
1851 synchronized(mWindowMap) {
1852 WindowState win = windowForClientLocked(session, client, false);
1856 displayId = win.getDisplayId();
1858 WindowStateAnimator winAnimator = win.mWinAnimator;
1859 if (viewVisibility != View.GONE) {
1860 win.setRequestedSize(requestedWidth, requestedHeight);
1863 int attrChanges = 0;
1864 int flagChanges = 0;
1865 if (attrs != null) {
1866 mPolicy.adjustWindowParamsLw(attrs);
1867 // if they don't have the permission, mask out the status bar bits
1868 if (seq == win.mSeq) {
1869 int systemUiVisibility = attrs.systemUiVisibility
1870 | attrs.subtreeSystemUiVisibility;
1871 if ((systemUiVisibility & DISABLE_MASK) != 0) {
1872 if (!hasStatusBarPermission) {
1873 systemUiVisibility &= ~DISABLE_MASK;
1876 win.mSystemUiVisibility = systemUiVisibility;
1878 if (win.mAttrs.type != attrs.type) {
1879 throw new IllegalArgumentException(
1880 "Window type can not be changed after the window is added.");
1883 // Odd choice but less odd than embedding in copyFrom()
1884 if ((attrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY)
1886 attrs.x = win.mAttrs.x;
1887 attrs.y = win.mAttrs.y;
1888 attrs.width = win.mAttrs.width;
1889 attrs.height = win.mAttrs.height;
1892 flagChanges = win.mAttrs.flags ^= attrs.flags;
1893 attrChanges = win.mAttrs.copyFrom(attrs);
1894 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
1895 | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
1896 win.mLayoutNeeded = true;
1898 if (win.mAppToken != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0
1899 || (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) {
1900 win.mAppToken.checkKeyguardFlagsChanged();
1902 if (((attrChanges & LayoutParams.ACCESSIBILITY_TITLE_CHANGED) != 0)
1903 && (mAccessibilityController != null)
1904 && (win.getDisplayId() == DEFAULT_DISPLAY)) {
1905 // No move or resize, but the controller checks for title changes as well
1906 mAccessibilityController.onSomeWindowResizedOrMovedLocked();
1910 if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility
1911 + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
1912 winAnimator.mSurfaceDestroyDeferred = (flags & RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
1913 win.mEnforceSizeCompat =
1914 (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
1915 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
1916 winAnimator.mAlpha = attrs.alpha;
1918 win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
1920 if (win.mAttrs.surfaceInsets.left != 0
1921 || win.mAttrs.surfaceInsets.top != 0
1922 || win.mAttrs.surfaceInsets.right != 0
1923 || win.mAttrs.surfaceInsets.bottom != 0) {
1924 winAnimator.setOpaqueLocked(false);
1927 boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
1928 final boolean isDefaultDisplay = win.isDefaultDisplay();
1929 boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
1930 || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
1931 || (!win.mRelayoutCalled));
1933 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
1934 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
1935 wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
1936 if ((flagChanges & FLAG_SECURE) != 0 && winAnimator.mSurfaceController != null) {
1937 winAnimator.mSurfaceController.setSecure(isSecureLocked(win));
1940 win.mRelayoutCalled = true;
1941 win.mInRelayout = true;
1943 final int oldVisibility = win.mViewVisibility;
1944 win.mViewVisibility = viewVisibility;
1945 if (DEBUG_SCREEN_ON) {
1946 RuntimeException stack = new RuntimeException();
1947 stack.fillInStackTrace();
1948 Slog.i(TAG_WM, "Relayout " + win + ": oldVis=" + oldVisibility
1949 + " newVis=" + viewVisibility, stack);
1951 if (viewVisibility == View.VISIBLE &&
1952 (win.mAppToken == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
1953 || !win.mAppToken.clientHidden)) {
1954 result = win.relayoutVisibleWindow(mergedConfiguration, result, attrChanges,
1957 result = createSurfaceControl(outSurface, result, win, winAnimator);
1958 } catch (Exception e) {
1959 mInputMonitor.updateInputWindowsLw(true /*force*/);
1961 Slog.w(TAG_WM, "Exception thrown when creating surface for client "
1962 + client + " (" + win.mAttrs.getTitle() + ")",
1964 Binder.restoreCallingIdentity(origId);
1967 if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
1968 focusMayChange = isDefaultDisplay;
1970 if (win.mAttrs.type == TYPE_INPUT_METHOD && mInputMethodWindow == null) {
1971 setInputMethodWindowLocked(win);
1974 win.adjustStartingWindowFlags();
1976 winAnimator.mEnterAnimationPending = false;
1977 winAnimator.mEnteringAnimation = false;
1978 final boolean usingSavedSurfaceBeforeVisible =
1979 oldVisibility != View.VISIBLE && win.isAnimatingWithSavedSurface();
1980 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
1981 if (winAnimator.hasSurface() && !win.mAnimatingExit
1982 && usingSavedSurfaceBeforeVisible) {
1983 Slog.d(TAG, "Ignoring layout to invisible when using saved surface " + win);
1987 if (winAnimator.hasSurface() && !win.mAnimatingExit
1988 && !usingSavedSurfaceBeforeVisible) {
1989 if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Relayout invis " + win
1990 + ": mAnimatingExit=" + win.mAnimatingExit);
1991 // If we are not currently running the exit animation, we
1992 // need to see about starting one.
1993 // We don't want to animate visibility of windows which are pending
1994 // replacement. In the case of activity relaunch child windows
1995 // could request visibility changes as they are detached from the main
1996 // application window during the tear down process. If we satisfied
1997 // these visibility changes though, we would cause a visual glitch
1998 // hiding the window before it's replacement was available.
1999 // So we just do nothing on our side.
2000 if (!win.mWillReplaceWindow) {
2001 focusMayChange = tryStartExitingAnimation(
2002 win, winAnimator, isDefaultDisplay, focusMayChange);
2004 result |= RELAYOUT_RES_SURFACE_CHANGED;
2006 if (viewVisibility == View.VISIBLE && winAnimator.hasSurface()) {
2007 // We already told the client to go invisible, but the message may not be
2008 // handled yet, or it might want to draw a last frame. If we already have a
2009 // surface, let the client use that, but don't create new surface at this point.
2010 winAnimator.mSurfaceController.getSurface(outSurface);
2012 if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win);
2015 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmReleaseOutSurface_"
2016 + win.mAttrs.getTitle());
2017 outSurface.release();
2019 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
2024 if (focusMayChange) {
2025 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
2026 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
2027 false /*updateInputWindows*/)) {
2030 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
2033 // updateFocusedWindowLocked() already assigned layers so we only need to
2034 // reassign them at this point if the IM window state gets shuffled
2035 boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
2036 final DisplayContent dc = win.getDisplayContent();
2038 dc.computeImeTarget(true /* updateImeTarget */);
2039 if (toBeDisplayed) {
2040 // Little hack here -- we -should- be able to rely on the function to return
2041 // true if the IME has moved and needs its layer recomputed. However, if the IME
2042 // was hidden and isn't actually moved in the list, its layer may be out of data
2043 // so we make sure to recompute it.
2044 dc.assignWindowLayers(false /* setLayoutNeeded */);
2048 if (wallpaperMayMove) {
2049 win.getDisplayContent().pendingLayoutChanges |=
2050 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2053 if (win.mAppToken != null) {
2054 mUnknownAppVisibilityController.notifyRelayouted(win.mAppToken);
2057 win.setDisplayLayoutNeeded();
2058 win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
2059 configChanged = updateOrientationFromAppTokensLocked(false, displayId);
2061 // We may be deferring layout passes at the moment, but since the client is interested
2062 // in the new out values right now we need to force a layout.
2063 mWindowPlacerLocked.performSurfacePlacement(true /* force */);
2064 if (toBeDisplayed && win.mIsWallpaper) {
2065 DisplayInfo displayInfo = win.getDisplayContent().getDisplayInfo();
2066 dc.mWallpaperController.updateWallpaperOffset(
2067 win, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
2069 if (win.mAppToken != null) {
2070 win.mAppToken.updateReportedVisibilityLocked();
2072 if (winAnimator.mReportSurfaceResized) {
2073 winAnimator.mReportSurfaceResized = false;
2074 result |= WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED;
2076 if (mPolicy.isNavBarForcedShownLw(win)) {
2077 result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR;
2079 if (!win.isGoneForLayoutLw()) {
2080 win.mResizedWhileGone = false;
2082 outFrame.set(win.mCompatFrame);
2083 outOverscanInsets.set(win.mOverscanInsets);
2084 outContentInsets.set(win.mContentInsets);
2085 outVisibleInsets.set(win.mVisibleInsets);
2086 outStableInsets.set(win.mStableInsets);
2087 outOutsets.set(win.mOutsets);
2088 outBackdropFrame.set(win.getBackdropFrame(win.mFrame));
2089 if (localLOGV) Slog.v(
2090 TAG_WM, "Relayout given client " + client.asBinder()
2091 + ", requestedWidth=" + requestedWidth
2092 + ", requestedHeight=" + requestedHeight
2093 + ", viewVisibility=" + viewVisibility
2094 + "\nRelayout returning frame=" + outFrame
2095 + ", surface=" + outSurface);
2097 if (localLOGV || DEBUG_FOCUS) Slog.v(
2098 TAG_WM, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
2100 result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0;
2102 mInputMonitor.updateInputWindowsLw(true /*force*/);
2105 Slog.v(TAG_WM, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
2107 win.mInRelayout = false;
2110 if (configChanged) {
2111 sendNewConfiguration(displayId);
2113 Binder.restoreCallingIdentity(origId);
2117 private boolean tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator,
2118 boolean isDefaultDisplay, boolean focusMayChange) {
2119 // Try starting an animation; if there isn't one, we
2120 // can destroy the surface right away.
2121 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2122 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2123 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2125 if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) {
2126 focusMayChange = isDefaultDisplay;
2127 win.mAnimatingExit = true;
2128 win.mWinAnimator.mAnimating = true;
2129 } else if (win.mWinAnimator.isAnimationSet()) {
2130 // Currently in a hide animation... turn this into
2132 win.mAnimatingExit = true;
2133 win.mWinAnimator.mAnimating = true;
2134 } else if (win.getDisplayContent().mWallpaperController.isWallpaperTarget(win)) {
2135 // If the wallpaper is currently behind this
2136 // window, we need to change both of them inside
2137 // of a transaction to avoid artifacts.
2138 win.mAnimatingExit = true;
2139 win.mWinAnimator.mAnimating = true;
2141 if (mInputMethodWindow == win) {
2142 setInputMethodWindowLocked(null);
2144 win.destroyOrSaveSurface();
2146 // TODO(multidisplay): Magnification is supported only for the default display.
2147 if (mAccessibilityController != null && win.getDisplayId() == DEFAULT_DISPLAY) {
2148 mAccessibilityController.onWindowTransitionLocked(win, transit);
2151 // When we start the exit animation we take the Surface from the client
2152 // so it will stop perturbing it. We need to likewise takeaway the SurfaceFlinger
2153 // side child surfaces, so they will remain preserved in their current state
2154 // (rather than be cleaned up immediately by the app code).
2155 SurfaceControl.openTransaction();
2156 winAnimator.detachChildren();
2157 SurfaceControl.closeTransaction();
2159 return focusMayChange;
2162 private int createSurfaceControl(Surface outSurface, int result, WindowState win,
2163 WindowStateAnimator winAnimator) {
2164 if (!win.mHasSurface) {
2165 result |= RELAYOUT_RES_SURFACE_CHANGED;
2167 WindowSurfaceController surfaceController = winAnimator.createSurfaceLocked(
2168 win.mAttrs.type, win.mOwnerUid);
2169 if (surfaceController != null) {
2170 surfaceController.getSurface(outSurface);
2171 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " OUT SURFACE " + outSurface + ": copied");
2173 // For some reason there isn't a surface. Clear the
2174 // caller's object so they see the same state.
2175 Slog.w(TAG_WM, "Failed to create surface control for " + win);
2176 outSurface.release();
2181 public boolean outOfMemoryWindow(Session session, IWindow client) {
2182 final long origId = Binder.clearCallingIdentity();
2185 synchronized (mWindowMap) {
2186 WindowState win = windowForClientLocked(session, client, false);
2190 return mRoot.reclaimSomeSurfaceMemory(win.mWinAnimator, "from-client", false);
2193 Binder.restoreCallingIdentity(origId);
2197 void finishDrawingWindow(Session session, IWindow client) {
2198 final long origId = Binder.clearCallingIdentity();
2200 synchronized (mWindowMap) {
2201 WindowState win = windowForClientLocked(session, client, false);
2202 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "finishDrawingWindow: " + win + " mDrawState="
2203 + (win != null ? win.mWinAnimator.drawStateToString() : "null"));
2204 if (win != null && win.mWinAnimator.finishDrawingLocked()) {
2205 if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
2206 win.getDisplayContent().pendingLayoutChanges |=
2207 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2209 win.setDisplayLayoutNeeded();
2210 mWindowPlacerLocked.requestTraversal();
2214 Binder.restoreCallingIdentity(origId);
2218 boolean applyAnimationLocked(AppWindowToken atoken, WindowManager.LayoutParams lp,
2219 int transit, boolean enter, boolean isVoiceInteraction) {
2220 // Only apply an animation if the display isn't frozen. If it is
2221 // frozen, there is no reason to animate and it can cause strange
2222 // artifacts when we unfreeze the display if some different animation
2224 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked");
2225 if (okToDisplay()) {
2226 final DisplayContent displayContent = atoken.getTask().getDisplayContent();
2227 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2228 final int width = displayInfo.appWidth;
2229 final int height = displayInfo.appHeight;
2230 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2231 "applyAnimation: atoken=" + atoken);
2233 // Determine the visible rect to calculate the thumbnail clip
2234 final WindowState win = atoken.findMainWindow();
2235 final Rect frame = new Rect(0, 0, width, height);
2236 final Rect displayFrame = new Rect(0, 0,
2237 displayInfo.logicalWidth, displayInfo.logicalHeight);
2238 final Rect insets = new Rect();
2239 Rect surfaceInsets = null;
2240 final boolean freeform = win != null && win.inFreeformWorkspace();
2242 // Containing frame will usually cover the whole screen, including dialog windows.
2243 // For freeform workspace windows it will not cover the whole screen and it also
2244 // won't exactly match the final freeform window frame (e.g. when overlapping with
2245 // the status bar). In that case we need to use the final frame.
2247 frame.set(win.mFrame);
2249 frame.set(win.mContainingFrame);
2251 surfaceInsets = win.getAttrs().surfaceInsets;
2252 insets.set(win.mContentInsets);
2255 if (atoken.mLaunchTaskBehind) {
2256 // Differentiate the two animations. This one which is briefly on the screen
2257 // gets the !enter animation, and the other activity which remains on the
2258 // screen gets the enter animation. Both appear in the mOpeningApps set.
2261 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2262 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2263 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2264 final Configuration displayConfig = displayContent.getConfiguration();
2265 Animation a = mAppTransition.loadAnimation(lp, transit, enter, displayConfig.uiMode,
2266 displayConfig.orientation, frame, displayFrame, insets, surfaceInsets,
2267 isVoiceInteraction, freeform, atoken.getTask().mTaskId);
2269 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken);
2270 final int containingWidth = frame.width();
2271 final int containingHeight = frame.height();
2272 atoken.mAppAnimator.setAnimation(a, containingWidth, containingHeight, width,
2273 height, mAppTransition.canSkipFirstFrame(),
2274 mAppTransition.getAppStackClipMode(),
2275 transit, mAppTransition.getTransitFlags());
2278 atoken.mAppAnimator.clearAnimation();
2280 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
2282 return atoken.mAppAnimator.animation != null;
2285 boolean checkCallingPermission(String permission, String func) {
2286 // Quick check: if the calling permission is me, it's all okay.
2287 if (Binder.getCallingPid() == myPid()) {
2291 if (mContext.checkCallingPermission(permission)
2292 == PackageManager.PERMISSION_GRANTED) {
2295 final String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid()
2296 + ", uid=" + Binder.getCallingUid() + " requires " + permission;
2297 Slog.w(TAG_WM, msg);
2301 boolean okToDisplay() {
2302 return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn();
2306 public void addWindowToken(IBinder binder, int type, int displayId) {
2307 if (!checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()")) {
2308 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2311 synchronized(mWindowMap) {
2312 final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId);
2313 WindowToken token = dc.getWindowToken(binder);
2314 if (token != null) {
2315 Slog.w(TAG_WM, "addWindowToken: Attempted to add binder token: " + binder
2316 + " for already created window token: " + token
2317 + " displayId=" + displayId);
2320 if (type == TYPE_WALLPAPER) {
2321 new WallpaperWindowToken(this, binder, true, dc,
2322 true /* ownerCanManageAppTokens */);
2324 new WindowToken(this, binder, type, true, dc, true /* ownerCanManageAppTokens */);
2330 public void removeWindowToken(IBinder binder, int displayId) {
2331 if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeWindowToken()")) {
2332 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2335 final long origId = Binder.clearCallingIdentity();
2337 synchronized (mWindowMap) {
2338 final DisplayContent dc = mRoot.getDisplayContent(displayId);
2340 Slog.w(TAG_WM, "removeWindowToken: Attempted to remove token: " + binder
2341 + " for non-exiting displayId=" + displayId);
2345 final WindowToken token = dc.removeWindowToken(binder);
2346 if (token == null) {
2348 "removeWindowToken: Attempted to remove non-existing token: " + binder);
2352 mInputMonitor.updateInputWindowsLw(true /*force*/);
2355 Binder.restoreCallingIdentity(origId);
2360 public Configuration updateOrientationFromAppTokens(Configuration currentConfig,
2361 IBinder freezeThisOneIfNeeded, int displayId) {
2362 if (!checkCallingPermission(MANAGE_APP_TOKENS, "updateOrientationFromAppTokens()")) {
2363 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2366 final Configuration config;
2367 final long ident = Binder.clearCallingIdentity();
2369 synchronized(mWindowMap) {
2370 config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded,
2374 Binder.restoreCallingIdentity(ident);
2380 private Configuration updateOrientationFromAppTokensLocked(Configuration currentConfig,
2381 IBinder freezeThisOneIfNeeded, int displayId) {
2382 if (!mDisplayReady) {
2385 Configuration config = null;
2387 if (updateOrientationFromAppTokensLocked(false, displayId)) {
2388 // If we changed the orientation but mOrientationChangeComplete is already true,
2389 // we used seamless rotation, and we don't need to freeze the screen.
2390 if (freezeThisOneIfNeeded != null && !mRoot.mOrientationChangeComplete) {
2391 final AppWindowToken atoken = mRoot.getAppWindowToken(freezeThisOneIfNeeded);
2392 if (atoken != null) {
2393 atoken.startFreezingScreen();
2396 config = computeNewConfigurationLocked(displayId);
2398 } else if (currentConfig != null) {
2399 // No obvious action we need to take, but if our current state mismatches the activity
2400 // manager's, update it, disregarding font scale, which should remain set to the value
2401 // of the previous configuration.
2402 // Here we're calling Configuration#unset() instead of setToDefaults() because we need
2403 // to keep override configs clear of non-empty values (e.g. fontSize).
2404 mTempConfiguration.unset();
2405 mTempConfiguration.updateFrom(currentConfig);
2406 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
2407 displayContent.computeScreenConfiguration(mTempConfiguration);
2408 if (currentConfig.diff(mTempConfiguration) != 0) {
2409 mWaitingForConfig = true;
2410 displayContent.setLayoutNeeded();
2411 int anim[] = new int[2];
2412 if (displayContent.isDimming()) {
2413 anim[0] = anim[1] = 0;
2415 mPolicy.selectRotationAnimationLw(anim);
2417 startFreezingDisplayLocked(false, anim[0], anim[1]);
2418 config = new Configuration(mTempConfiguration);
2426 * Determine the new desired orientation of the display, returning a non-null new Configuration
2427 * if it has changed from the current orientation. IF TRUE IS RETURNED SOMEONE MUST CALL
2428 * {@link #setNewDisplayOverrideConfiguration(Configuration, int)} TO TELL THE WINDOW MANAGER IT
2429 * CAN UNFREEZE THE SCREEN. This will typically be done for you if you call
2430 * {@link #sendNewConfiguration(int)}.
2432 * The orientation is computed from non-application windows first. If none of the
2433 * non-application windows specify orientation, the orientation is computed from application
2435 * @see android.view.IWindowManager#updateOrientationFromAppTokens(Configuration, IBinder, int)
2437 boolean updateOrientationFromAppTokensLocked(boolean inTransaction, int displayId) {
2438 long ident = Binder.clearCallingIdentity();
2440 final DisplayContent dc = mRoot.getDisplayContent(displayId);
2441 final int req = dc.getOrientation();
2442 if (req != dc.getLastOrientation()) {
2443 dc.setLastOrientation(req);
2444 //send a message to Policy indicating orientation change to take
2445 //action like disabling/enabling sensors etc.,
2446 // TODO(multi-display): Implement policy for secondary displays.
2447 if (dc.isDefaultDisplay) {
2448 mPolicy.setCurrentOrientationLw(req);
2450 if (dc.updateRotationUnchecked(inTransaction)) {
2458 Binder.restoreCallingIdentity(ident);
2462 // If this is true we have updated our desired orientation, but not yet
2463 // changed the real orientation our applied our screen rotation animation.
2464 // For example, because a previous screen rotation was in progress.
2465 boolean rotationNeedsUpdateLocked() {
2466 // TODO(multi-display): Check for updates on all displays. Need to have per-display policy
2467 // to implement WindowManagerPolicy#rotationForOrientationLw() correctly.
2468 final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
2469 final int lastOrientation = defaultDisplayContent.getLastOrientation();
2470 final int oldRotation = defaultDisplayContent.getRotation();
2471 final boolean oldAltOrientation = defaultDisplayContent.getAltOrientation();
2473 final int rotation = mPolicy.rotationForOrientationLw(lastOrientation,
2475 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
2476 lastOrientation, rotation);
2477 if (oldRotation == rotation && oldAltOrientation == altOrientation) {
2484 public int[] setNewDisplayOverrideConfiguration(Configuration overrideConfig, int displayId) {
2485 if (!checkCallingPermission(MANAGE_APP_TOKENS, "setNewDisplayOverrideConfiguration()")) {
2486 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2489 synchronized(mWindowMap) {
2490 if (mWaitingForConfig) {
2491 mWaitingForConfig = false;
2492 mLastFinishedFreezeSource = "new-config";
2494 return mRoot.setDisplayOverrideConfigurationIfNeeded(overrideConfig, displayId);
2498 void setFocusTaskRegionLocked(AppWindowToken previousFocus) {
2499 final Task focusedTask = mFocusedApp != null ? mFocusedApp.getTask() : null;
2500 final Task previousTask = previousFocus != null ? previousFocus.getTask() : null;
2501 final DisplayContent focusedDisplayContent =
2502 focusedTask != null ? focusedTask.getDisplayContent() : null;
2503 final DisplayContent previousDisplayContent =
2504 previousTask != null ? previousTask.getDisplayContent() : null;
2505 if (previousDisplayContent != null && previousDisplayContent != focusedDisplayContent) {
2506 previousDisplayContent.setTouchExcludeRegion(null);
2508 if (focusedDisplayContent != null) {
2509 focusedDisplayContent.setTouchExcludeRegion(focusedTask);
2514 public void setFocusedApp(IBinder token, boolean moveFocusNow) {
2515 if (!checkCallingPermission(MANAGE_APP_TOKENS, "setFocusedApp()")) {
2516 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2519 synchronized(mWindowMap) {
2520 final AppWindowToken newFocus;
2521 if (token == null) {
2522 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Clearing focused app, was " + mFocusedApp);
2525 newFocus = mRoot.getAppWindowToken(token);
2526 if (newFocus == null) {
2527 Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token);
2529 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Set focused app to: " + newFocus
2530 + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow);
2533 final boolean changed = mFocusedApp != newFocus;
2535 AppWindowToken prev = mFocusedApp;
2536 mFocusedApp = newFocus;
2537 mInputMonitor.setFocusedAppLw(newFocus);
2538 setFocusTaskRegionLocked(prev);
2541 if (moveFocusNow && changed) {
2542 final long origId = Binder.clearCallingIdentity();
2543 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
2544 Binder.restoreCallingIdentity(origId);
2550 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
2551 prepareAppTransition(transit, alwaysKeepCurrent, 0 /* flags */, false /* forceOverride */);
2555 * @param transit What kind of transition is happening. Use one of the constants
2556 * AppTransition.TRANSIT_*.
2557 * @param alwaysKeepCurrent If true and a transition is already set, new transition will NOT
2559 * @param flags Additional flags for the app transition, Use a combination of the constants
2560 * AppTransition.TRANSIT_FLAG_*.
2561 * @param forceOverride Always override the transit, not matter what was set previously.
2563 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent, int flags,
2564 boolean forceOverride) {
2565 if (!checkCallingPermission(MANAGE_APP_TOKENS, "prepareAppTransition()")) {
2566 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2568 synchronized(mWindowMap) {
2569 boolean prepared = mAppTransition.prepareAppTransitionLocked(transit, alwaysKeepCurrent,
2570 flags, forceOverride);
2571 if (prepared && okToDisplay()) {
2572 mSkipAppTransitionAnimation = false;
2578 public int getPendingAppTransition() {
2579 return mAppTransition.getAppTransition();
2583 public void overridePendingAppTransition(String packageName,
2584 int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
2585 synchronized(mWindowMap) {
2586 mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim,
2592 public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
2594 synchronized(mWindowMap) {
2595 mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth,
2601 public void overridePendingAppTransitionClipReveal(int startX, int startY,
2602 int startWidth, int startHeight) {
2603 synchronized(mWindowMap) {
2604 mAppTransition.overridePendingAppTransitionClipReveal(startX, startY, startWidth,
2610 public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
2611 int startY, IRemoteCallback startedCallback, boolean scaleUp) {
2612 synchronized(mWindowMap) {
2613 mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY,
2614 startedCallback, scaleUp);
2619 public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
2620 int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
2622 synchronized(mWindowMap) {
2623 mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX, startY,
2624 targetWidth, targetHeight, startedCallback, scaleUp);
2629 public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
2630 IRemoteCallback onAnimationStartedCallback, IRemoteCallback onAnimationFinishedCallback,
2632 synchronized (mWindowMap) {
2633 mAppTransition.overridePendingAppTransitionMultiThumb(specs, onAnimationStartedCallback,
2634 onAnimationFinishedCallback, scaleUp);
2635 prolongAnimationsFromSpecs(specs, scaleUp);
2640 void prolongAnimationsFromSpecs(@NonNull AppTransitionAnimationSpec[] specs, boolean scaleUp) {
2641 // This is used by freeform <-> recents windows transition. We need to synchronize
2642 // the animation with the appearance of the content of recents, so we will make
2643 // animation stay on the first or last frame a little longer.
2644 mTmpTaskIds.clear();
2645 for (int i = specs.length - 1; i >= 0; i--) {
2646 mTmpTaskIds.put(specs[i].taskId, 0);
2648 for (final WindowState win : mWindowMap.values()) {
2649 final Task task = win.getTask();
2650 if (task != null && mTmpTaskIds.get(task.mTaskId, -1) != -1
2651 && task.inFreeformWorkspace()) {
2652 final AppWindowToken appToken = win.mAppToken;
2653 if (appToken != null && appToken.mAppAnimator != null) {
2654 appToken.mAppAnimator.startProlongAnimation(scaleUp ?
2655 PROLONG_ANIMATION_AT_START : PROLONG_ANIMATION_AT_END);
2662 public void overridePendingAppTransitionInPlace(String packageName, int anim) {
2663 synchronized(mWindowMap) {
2664 mAppTransition.overrideInPlaceAppTransition(packageName, anim);
2669 public void overridePendingAppTransitionMultiThumbFuture(
2670 IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback,
2672 synchronized(mWindowMap) {
2673 mAppTransition.overridePendingAppTransitionMultiThumbFuture(specsFuture, callback,
2679 public void endProlongedAnimations() {
2680 synchronized (mWindowMap) {
2681 for (final WindowState win : mWindowMap.values()) {
2682 final AppWindowToken appToken = win.mAppToken;
2683 if (appToken != null && appToken.mAppAnimator != null) {
2684 appToken.mAppAnimator.endProlongedAnimation();
2687 mAppTransition.notifyProlongedAnimationsEnded();
2692 public void executeAppTransition() {
2693 if (!checkCallingPermission(MANAGE_APP_TOKENS, "executeAppTransition()")) {
2694 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2697 synchronized(mWindowMap) {
2698 if (DEBUG_APP_TRANSITIONS) Slog.w(TAG_WM, "Execute app transition: " + mAppTransition
2699 + " Callers=" + Debug.getCallers(5));
2700 if (mAppTransition.isTransitionSet()) {
2701 mAppTransition.setReady();
2702 final long origId = Binder.clearCallingIdentity();
2704 mWindowPlacerLocked.performSurfacePlacement();
2706 Binder.restoreCallingIdentity(origId);
2712 public void setAppFullscreen(IBinder token, boolean toOpaque) {
2713 synchronized (mWindowMap) {
2714 final AppWindowToken atoken = mRoot.getAppWindowToken(token);
2715 if (atoken != null) {
2716 atoken.setFillsParent(toOpaque);
2717 setWindowOpaqueLocked(token, toOpaque);
2718 mWindowPlacerLocked.requestTraversal();
2723 public void setWindowOpaque(IBinder token, boolean isOpaque) {
2724 synchronized (mWindowMap) {
2725 setWindowOpaqueLocked(token, isOpaque);
2729 private void setWindowOpaqueLocked(IBinder token, boolean isOpaque) {
2730 final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
2731 if (wtoken != null) {
2732 final WindowState win = wtoken.findMainWindow();
2734 win.mWinAnimator.setOpaqueLocked(isOpaque);
2739 void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) {
2740 if (transit != TRANSIT_UNSET) {
2741 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
2742 wtoken.mAppAnimator.setNullAnimation();
2744 applyAnimationLocked(wtoken, null, transit, false, false);
2748 public void setDockedStackCreateState(int mode, Rect bounds) {
2749 synchronized (mWindowMap) {
2750 setDockedStackCreateStateLocked(mode, bounds);
2754 void setDockedStackCreateStateLocked(int mode, Rect bounds) {
2755 mDockedStackCreateMode = mode;
2756 mDockedStackCreateBounds = bounds;
2760 * @param useExistingStackBounds Apply {@param aspectRatio} to the existing target stack bounds
2763 public Rect getPictureInPictureBounds(int displayId, float aspectRatio,
2764 boolean useExistingStackBounds) {
2765 synchronized (mWindowMap) {
2766 if (!mSupportsPictureInPicture) {
2770 final Rect stackBounds;
2771 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
2772 if (displayContent == null) {
2776 final PinnedStackController pinnedStackController =
2777 displayContent.getPinnedStackController();
2778 final TaskStack stack = displayContent.getStackById(PINNED_STACK_ID);
2779 if (stack != null && useExistingStackBounds) {
2780 // If the stack exists, then use its final bounds to calculate the new aspect ratio
2782 stackBounds = new Rect();
2783 stack.getAnimationOrCurrentBounds(stackBounds);
2785 // Otherwise, just calculate the aspect ratio bounds from the default bounds
2786 stackBounds = pinnedStackController.getDefaultBounds();
2789 if (pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)) {
2790 return pinnedStackController.transformBoundsToAspectRatio(stackBounds, aspectRatio);
2797 public boolean isValidPictureInPictureAspectRatio(int displayId, float aspectRatio) {
2798 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
2799 return displayContent.getPinnedStackController().isValidPictureInPictureAspectRatio(
2804 public void getStackBounds(int stackId, Rect bounds) {
2805 synchronized (mWindowMap) {
2806 final TaskStack stack = mRoot.getStackById(stackId);
2807 if (stack != null) {
2808 stack.getBounds(bounds);
2816 public void notifyShowingDreamChanged() {
2817 notifyKeyguardFlagsChanged(null /* callback */);
2821 public WindowManagerPolicy.WindowState getInputMethodWindowLw() {
2822 return mInputMethodWindow;
2826 public void notifyKeyguardTrustedChanged() {
2827 mH.sendEmptyMessage(H.NOTIFY_KEYGUARD_TRUSTED_CHANGED);
2831 * Starts deferring layout passes. Useful when doing multiple changes but to optimize
2832 * performance, only one layout pass should be done. This can be called multiple times, and
2833 * layouting will be resumed once the last caller has called {@link #continueSurfaceLayout}
2835 public void deferSurfaceLayout() {
2836 synchronized (mWindowMap) {
2837 mWindowPlacerLocked.deferLayout();
2842 * Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()}
2844 public void continueSurfaceLayout() {
2845 synchronized (mWindowMap) {
2846 mWindowPlacerLocked.continueLayout();
2851 * @return true if the activity contains windows that have
2852 * {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set
2854 public boolean containsShowWhenLockedWindow(IBinder token) {
2855 synchronized (mWindowMap) {
2856 final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
2857 return wtoken != null && wtoken.containsShowWhenLockedWindow();
2862 * @return true if the activity contains windows that have
2863 * {@link LayoutParams#FLAG_DISMISS_KEYGUARD} set
2865 public boolean containsDismissKeyguardWindow(IBinder token) {
2866 synchronized (mWindowMap) {
2867 final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
2868 return wtoken != null && wtoken.containsDismissKeyguardWindow();
2873 * Notifies activity manager that some Keyguard flags have changed and that it needs to
2874 * reevaluate the visibilities of the activities.
2875 * @param callback Runnable to be called when activity manager is done reevaluating visibilities
2877 void notifyKeyguardFlagsChanged(@Nullable Runnable callback) {
2878 final Runnable wrappedCallback = callback != null
2879 ? () -> { synchronized (mWindowMap) { callback.run(); } }
2881 mH.obtainMessage(H.NOTIFY_KEYGUARD_FLAGS_CHANGED, wrappedCallback).sendToTarget();
2884 public boolean isKeyguardTrusted() {
2885 synchronized (mWindowMap) {
2886 return mPolicy.isKeyguardTrustedLw();
2890 // -------------------------------------------------------------
2891 // Misc IWindowSession methods
2892 // -------------------------------------------------------------
2895 public void startFreezingScreen(int exitAnim, int enterAnim) {
2896 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
2897 "startFreezingScreen()")) {
2898 throw new SecurityException("Requires FREEZE_SCREEN permission");
2901 synchronized(mWindowMap) {
2902 if (!mClientFreezingScreen) {
2903 mClientFreezingScreen = true;
2904 final long origId = Binder.clearCallingIdentity();
2906 startFreezingDisplayLocked(false, exitAnim, enterAnim);
2907 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
2908 mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
2910 Binder.restoreCallingIdentity(origId);
2917 public void stopFreezingScreen() {
2918 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
2919 "stopFreezingScreen()")) {
2920 throw new SecurityException("Requires FREEZE_SCREEN permission");
2923 synchronized(mWindowMap) {
2924 if (mClientFreezingScreen) {
2925 mClientFreezingScreen = false;
2926 mLastFinishedFreezeSource = "client";
2927 final long origId = Binder.clearCallingIdentity();
2929 stopFreezingDisplayLocked();
2931 Binder.restoreCallingIdentity(origId);
2938 public void disableKeyguard(IBinder token, String tag) {
2939 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
2940 != PackageManager.PERMISSION_GRANTED) {
2941 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
2943 // If this isn't coming from the system then don't allow disabling the lockscreen
2944 // to bypass security.
2945 if (Binder.getCallingUid() != SYSTEM_UID && isKeyguardSecure()) {
2946 Log.d(TAG_WM, "current mode is SecurityMode, ignore disableKeyguard");
2950 // If this isn't coming from the current profiles, ignore it.
2951 if (!isCurrentProfileLocked(UserHandle.getCallingUserId())) {
2952 Log.d(TAG_WM, "non-current profiles, ignore disableKeyguard");
2956 if (token == null) {
2957 throw new IllegalArgumentException("token == null");
2960 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
2961 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
2965 public void reenableKeyguard(IBinder token) {
2966 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
2967 != PackageManager.PERMISSION_GRANTED) {
2968 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
2971 if (token == null) {
2972 throw new IllegalArgumentException("token == null");
2975 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
2976 KeyguardDisableHandler.KEYGUARD_REENABLE, token));
2980 * @see android.app.KeyguardManager#exitKeyguardSecurely
2983 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
2984 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
2985 != PackageManager.PERMISSION_GRANTED) {
2986 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
2989 if (callback == null) {
2990 throw new IllegalArgumentException("callback == null");
2993 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
2995 public void onKeyguardExitResult(boolean success) {
2997 callback.onKeyguardExitResult(success);
2998 } catch (RemoteException e) {
2999 // Client has died, we don't care.
3006 public boolean inKeyguardRestrictedInputMode() {
3007 return mPolicy.inKeyguardRestrictedKeyInputMode();
3011 public boolean isKeyguardLocked() {
3012 return mPolicy.isKeyguardLocked();
3016 public boolean isKeyguardSecure() {
3017 int userId = UserHandle.getCallingUserId();
3018 long origId = Binder.clearCallingIdentity();
3020 return mPolicy.isKeyguardSecure(userId);
3022 Binder.restoreCallingIdentity(origId);
3026 public boolean isShowingDream() {
3027 synchronized (mWindowMap) {
3028 return mPolicy.isShowingDreamLw();
3033 public void dismissKeyguard(IKeyguardDismissCallback callback) {
3034 checkCallingPermission(permission.CONTROL_KEYGUARD, "dismissKeyguard");
3035 synchronized(mWindowMap) {
3036 mPolicy.dismissKeyguardLw(callback);
3040 public void onKeyguardOccludedChanged(boolean occluded) {
3041 synchronized (mWindowMap) {
3042 mPolicy.onKeyguardOccludedChangedLw(occluded);
3047 public void setSwitchingUser(boolean switching) {
3048 if (!checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
3049 "setSwitchingUser()")) {
3050 throw new SecurityException("Requires INTERACT_ACROSS_USERS_FULL permission");
3052 mPolicy.setSwitchingUser(switching);
3053 synchronized (mWindowMap) {
3054 mSwitchingUser = switching;
3058 void showGlobalActions() {
3059 mPolicy.showGlobalActions();
3063 public void closeSystemDialogs(String reason) {
3064 synchronized(mWindowMap) {
3065 mRoot.closeSystemDialogs(reason);
3069 static float fixScale(float scale) {
3070 if (scale < 0) scale = 0;
3071 else if (scale > 20) scale = 20;
3072 return Math.abs(scale);
3076 public void setAnimationScale(int which, float scale) {
3077 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
3078 "setAnimationScale()")) {
3079 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
3082 scale = fixScale(scale);
3084 case 0: mWindowAnimationScaleSetting = scale; break;
3085 case 1: mTransitionAnimationScaleSetting = scale; break;
3086 case 2: mAnimatorDurationScaleSetting = scale; break;
3090 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
3094 public void setAnimationScales(float[] scales) {
3095 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
3096 "setAnimationScale()")) {
3097 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
3100 if (scales != null) {
3101 if (scales.length >= 1) {
3102 mWindowAnimationScaleSetting = fixScale(scales[0]);
3104 if (scales.length >= 2) {
3105 mTransitionAnimationScaleSetting = fixScale(scales[1]);
3107 if (scales.length >= 3) {
3108 mAnimatorDurationScaleSetting = fixScale(scales[2]);
3109 dispatchNewAnimatorScaleLocked(null);
3114 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
3117 private void setAnimatorDurationScale(float scale) {
3118 mAnimatorDurationScaleSetting = scale;
3119 ValueAnimator.setDurationScale(scale);
3122 public float getWindowAnimationScaleLocked() {
3123 return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting;
3126 public float getTransitionAnimationScaleLocked() {
3127 return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting;
3131 public float getAnimationScale(int which) {
3133 case 0: return mWindowAnimationScaleSetting;
3134 case 1: return mTransitionAnimationScaleSetting;
3135 case 2: return mAnimatorDurationScaleSetting;
3141 public float[] getAnimationScales() {
3142 return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting,
3143 mAnimatorDurationScaleSetting };
3147 public float getCurrentAnimatorScale() {
3148 synchronized(mWindowMap) {
3149 return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting;
3153 void dispatchNewAnimatorScaleLocked(Session session) {
3154 mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget();
3158 public void registerPointerEventListener(PointerEventListener listener) {
3159 mPointerEventDispatcher.registerInputEventListener(listener);
3163 public void unregisterPointerEventListener(PointerEventListener listener) {
3164 mPointerEventDispatcher.unregisterInputEventListener(listener);
3167 /** Check if the service is set to dispatch pointer events. */
3168 boolean canDispatchPointerEvents() {
3169 return mPointerEventDispatcher != null;
3172 // Called by window manager policy. Not exposed externally.
3174 public int getLidState() {
3175 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
3176 InputManagerService.SW_LID);
3178 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
3180 } else if (sw == 0) {
3181 // Switch state: AKEY_STATE_UP.
3184 // Switch state: AKEY_STATE_UNKNOWN.
3189 // Called by window manager policy. Not exposed externally.
3191 public void lockDeviceNow() {
3195 // Called by window manager policy. Not exposed externally.
3197 public int getCameraLensCoverState() {
3198 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
3199 InputManagerService.SW_CAMERA_LENS_COVER);
3201 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
3202 return CAMERA_LENS_COVERED;
3203 } else if (sw == 0) {
3204 // Switch state: AKEY_STATE_UP.
3205 return CAMERA_LENS_UNCOVERED;
3207 // Switch state: AKEY_STATE_UNKNOWN.
3208 return CAMERA_LENS_COVER_ABSENT;
3212 // Called by window manager policy. Not exposed externally.
3214 public void switchInputMethod(boolean forwardDirection) {
3215 final InputMethodManagerInternal inputMethodManagerInternal =
3216 LocalServices.getService(InputMethodManagerInternal.class);
3217 if (inputMethodManagerInternal != null) {
3218 inputMethodManagerInternal.switchInputMethod(forwardDirection);
3222 // Called by window manager policy. Not exposed externally.
3224 public void shutdown(boolean confirm) {
3225 // Pass in the UI context, since ShutdownThread requires it (to show UI).
3226 ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(),
3227 PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
3230 // Called by window manager policy. Not exposed externally.
3232 public void reboot(boolean confirm) {
3233 // Pass in the UI context, since ShutdownThread requires it (to show UI).
3234 ShutdownThread.reboot(ActivityThread.currentActivityThread().getSystemUiContext(),
3235 PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
3238 // Called by window manager policy. Not exposed externally.
3240 public void rebootSafeMode(boolean confirm) {
3241 // Pass in the UI context, since ShutdownThread requires it (to show UI).
3242 ShutdownThread.rebootSafeMode(ActivityThread.currentActivityThread().getSystemUiContext(),
3246 public void setCurrentProfileIds(final int[] currentProfileIds) {
3247 synchronized (mWindowMap) {
3248 mCurrentProfileIds = currentProfileIds;
3252 public void setCurrentUser(final int newUserId, final int[] currentProfileIds) {
3253 synchronized (mWindowMap) {
3254 mCurrentUserId = newUserId;
3255 mCurrentProfileIds = currentProfileIds;
3256 mAppTransition.setCurrentUser(newUserId);
3257 mPolicy.setCurrentUserLw(newUserId);
3259 // If keyguard was disabled, re-enable it
3260 // TODO: Keep track of keyguardEnabled state per user and use here...
3261 // e.g. enabled = mKeyguardDisableHandler.getEnabledStateForUser(newUserId);
3262 mPolicy.enableKeyguard(true);
3264 // Hide windows that should not be seen by the new user.
3266 mWindowPlacerLocked.performSurfacePlacement();
3268 // Notify whether the docked stack exists for the current user
3269 final DisplayContent displayContent = getDefaultDisplayContentLocked();
3270 final TaskStack stack = displayContent.getDockedStackIgnoringVisibility();
3271 displayContent.mDividerControllerLocked.notifyDockedStackExistsChanged(
3272 stack != null && stack.hasTaskForUser(newUserId));
3274 // If the display is already prepared, update the density.
3275 // Otherwise, we'll update it when it's prepared.
3276 if (mDisplayReady) {
3277 final int forcedDensity = getForcedDisplayDensityForUserLocked(newUserId);
3278 final int targetDensity = forcedDensity != 0 ? forcedDensity
3279 : displayContent.mInitialDisplayDensity;
3280 setForcedDisplayDensityLocked(displayContent, targetDensity);
3285 /* Called by WindowState */
3286 boolean isCurrentProfileLocked(int userId) {
3287 if (userId == mCurrentUserId) return true;
3288 for (int i = 0; i < mCurrentProfileIds.length; i++) {
3289 if (mCurrentProfileIds[i] == userId) return true;
3294 public void enableScreenAfterBoot() {
3295 synchronized(mWindowMap) {
3297 RuntimeException here = new RuntimeException("here");
3298 here.fillInStackTrace();
3299 Slog.i(TAG_WM, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
3300 + " mForceDisplayEnabled=" + mForceDisplayEnabled
3301 + " mShowingBootMessages=" + mShowingBootMessages
3302 + " mSystemBooted=" + mSystemBooted, here);
3304 if (mSystemBooted) {
3307 mSystemBooted = true;
3308 hideBootMessagesLocked();
3309 // If the screen still doesn't come up after 30 seconds, give
3310 // up and turn it on.
3311 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30 * 1000);
3314 mPolicy.systemBooted();
3316 performEnableScreen();
3320 public void enableScreenIfNeeded() {
3321 synchronized (mWindowMap) {
3322 enableScreenIfNeededLocked();
3326 void enableScreenIfNeededLocked() {
3328 RuntimeException here = new RuntimeException("here");
3329 here.fillInStackTrace();
3330 Slog.i(TAG_WM, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
3331 + " mForceDisplayEnabled=" + mForceDisplayEnabled
3332 + " mShowingBootMessages=" + mShowingBootMessages
3333 + " mSystemBooted=" + mSystemBooted, here);
3335 if (mDisplayEnabled) {
3338 if (!mSystemBooted && !mShowingBootMessages) {
3341 mH.sendEmptyMessage(H.ENABLE_SCREEN);
3344 public void performBootTimeout() {
3345 synchronized(mWindowMap) {
3346 if (mDisplayEnabled) {
3349 Slog.w(TAG_WM, "***** BOOT TIMEOUT: forcing display enabled");
3350 mForceDisplayEnabled = true;
3352 performEnableScreen();
3355 private void performEnableScreen() {
3356 synchronized(mWindowMap) {
3357 if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
3358 + " mForceDisplayEnabled=" + mForceDisplayEnabled
3359 + " mShowingBootMessages=" + mShowingBootMessages
3360 + " mSystemBooted=" + mSystemBooted
3361 + " mOnlyCore=" + mOnlyCore,
3362 new RuntimeException("here").fillInStackTrace());
3363 if (mDisplayEnabled) {
3366 if (!mSystemBooted && !mShowingBootMessages) {
3370 // Don't enable the screen until all existing windows have been drawn.
3371 if (!mForceDisplayEnabled
3372 // TODO(multidisplay): Expand to all displays?
3373 && getDefaultDisplayContentLocked().checkWaitingForWindows()) {
3377 if (!mBootAnimationStopped) {
3378 // Do this one time.
3379 Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
3381 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
3382 if (surfaceFlinger != null) {
3383 //Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
3384 Parcel data = Parcel.obtain();
3385 data.writeInterfaceToken("android.ui.ISurfaceComposer");
3386 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
3390 } catch (RemoteException ex) {
3391 Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!");
3393 mBootAnimationStopped = true;
3396 if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {
3397 if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: Waiting for anim complete");
3401 EventLog.writeEvent(EventLogTags.WM_BOOT_ANIMATION_DONE, SystemClock.uptimeMillis());
3402 Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
3403 mDisplayEnabled = true;
3404 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, "******************** ENABLING SCREEN!");
3406 // Enable input dispatch.
3407 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
3411 mActivityManager.bootAnimationComplete();
3412 } catch (RemoteException e) {
3415 mPolicy.enableScreenAfterBoot();
3417 // Make sure the last requested orientation has been applied.
3418 updateRotationUnchecked(false, false);
3421 private boolean checkBootAnimationCompleteLocked() {
3422 if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) {
3423 mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED);
3424 mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED,
3425 BOOT_ANIMATION_POLL_INTERVAL);
3426 if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Waiting for anim complete");
3429 if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Animation complete!");
3433 public void showBootMessage(final CharSequence msg, final boolean always) {
3434 boolean first = false;
3435 synchronized(mWindowMap) {
3437 RuntimeException here = new RuntimeException("here");
3438 here.fillInStackTrace();
3439 Slog.i(TAG_WM, "showBootMessage: msg=" + msg + " always=" + always
3440 + " mAllowBootMessages=" + mAllowBootMessages
3441 + " mShowingBootMessages=" + mShowingBootMessages
3442 + " mSystemBooted=" + mSystemBooted, here);
3444 if (!mAllowBootMessages) {
3447 if (!mShowingBootMessages) {
3453 if (mSystemBooted) {
3456 mShowingBootMessages = true;
3457 mPolicy.showBootMessage(msg, always);
3460 performEnableScreen();
3464 public void hideBootMessagesLocked() {
3466 RuntimeException here = new RuntimeException("here");
3467 here.fillInStackTrace();
3468 Slog.i(TAG_WM, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
3469 + " mForceDisplayEnabled=" + mForceDisplayEnabled
3470 + " mShowingBootMessages=" + mShowingBootMessages
3471 + " mSystemBooted=" + mSystemBooted, here);
3473 if (mShowingBootMessages) {
3474 mShowingBootMessages = false;
3475 mPolicy.hideBootMessages();
3480 public void setInTouchMode(boolean mode) {
3481 synchronized(mWindowMap) {
3482 mInTouchMode = mode;
3486 private void updateCircularDisplayMaskIfNeeded() {
3487 // we're fullscreen and not hosted in an ActivityView
3488 if (mContext.getResources().getConfiguration().isScreenRound()
3489 && mContext.getResources().getBoolean(
3490 com.android.internal.R.bool.config_windowShowCircularMask)) {
3491 final int currentUserId;
3492 synchronized(mWindowMap) {
3493 currentUserId = mCurrentUserId;
3495 // Device configuration calls for a circular display mask, but we only enable the mask
3496 // if the accessibility color inversion feature is disabled, as the inverted mask
3497 // causes artifacts.
3498 int inversionState = Settings.Secure.getIntForUser(mContext.getContentResolver(),
3499 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, currentUserId);
3500 int showMask = (inversionState == 1) ? 0 : 1;
3501 Message m = mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK);
3507 public void showEmulatorDisplayOverlayIfNeeded() {
3508 if (mContext.getResources().getBoolean(
3509 com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay)
3510 && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false)
3511 && Build.IS_EMULATOR) {
3512 mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY));
3516 public void showCircularMask(boolean visible) {
3517 synchronized(mWindowMap) {
3519 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
3520 ">>> OPEN TRANSACTION showCircularMask(visible=" + visible + ")");
3521 openSurfaceTransaction();
3524 // TODO(multi-display): support multiple displays
3525 if (mCircularDisplayMask == null) {
3526 int screenOffset = mContext.getResources().getInteger(
3527 com.android.internal.R.integer.config_windowOutsetBottom);
3528 int maskThickness = mContext.getResources().getDimensionPixelSize(
3529 com.android.internal.R.dimen.circular_display_mask_thickness);
3531 mCircularDisplayMask = new CircularDisplayMask(
3532 getDefaultDisplayContentLocked().getDisplay(),
3534 mPolicy.getWindowLayerFromTypeLw(
3535 WindowManager.LayoutParams.TYPE_POINTER)
3536 * TYPE_LAYER_MULTIPLIER + 10, screenOffset, maskThickness);
3538 mCircularDisplayMask.setVisibility(true);
3539 } else if (mCircularDisplayMask != null) {
3540 mCircularDisplayMask.setVisibility(false);
3541 mCircularDisplayMask = null;
3544 closeSurfaceTransaction();
3545 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
3546 "<<< CLOSE TRANSACTION showCircularMask(visible=" + visible + ")");
3551 public void showEmulatorDisplayOverlay() {
3552 synchronized(mWindowMap) {
3554 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
3555 ">>> OPEN TRANSACTION showEmulatorDisplayOverlay");
3556 openSurfaceTransaction();
3558 if (mEmulatorDisplayOverlay == null) {
3559 mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(
3561 getDefaultDisplayContentLocked().getDisplay(),
3563 mPolicy.getWindowLayerFromTypeLw(
3564 WindowManager.LayoutParams.TYPE_POINTER)
3565 * TYPE_LAYER_MULTIPLIER + 10);
3567 mEmulatorDisplayOverlay.setVisibility(true);
3569 closeSurfaceTransaction();
3570 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
3571 "<<< CLOSE TRANSACTION showEmulatorDisplayOverlay");
3576 // TODO: more accounting of which pid(s) turned it on, keep count,
3577 // only allow disables from pids which have count on, etc.
3579 public void showStrictModeViolation(boolean on) {
3580 int pid = Binder.getCallingPid();
3581 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
3584 private void showStrictModeViolation(int arg, int pid) {
3585 final boolean on = arg != 0;
3586 synchronized(mWindowMap) {
3587 // Ignoring requests to enable the red border from clients which aren't on screen.
3588 // (e.g. Broadcast Receivers in the background..)
3589 if (on && !mRoot.canShowStrictModeViolation(pid)) {
3593 if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
3594 ">>> OPEN TRANSACTION showStrictModeViolation");
3595 // TODO: Modify this to use the surface trace once it is not going crazy.
3597 SurfaceControl.openTransaction();
3599 // TODO(multi-display): support multiple displays
3600 if (mStrictModeFlash == null) {
3601 mStrictModeFlash = new StrictModeFlash(
3602 getDefaultDisplayContentLocked().getDisplay(), mFxSession);
3604 mStrictModeFlash.setVisibility(on);
3606 SurfaceControl.closeTransaction();
3607 if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
3608 "<<< CLOSE TRANSACTION showStrictModeViolation");
3614 public void setStrictModeVisualIndicatorPreference(String value) {
3615 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
3619 public Bitmap screenshotWallpaper() {
3620 if (!checkCallingPermission(READ_FRAME_BUFFER,
3621 "screenshotWallpaper()")) {
3622 throw new SecurityException("Requires READ_FRAME_BUFFER permission");
3625 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper");
3626 return screenshotApplications(null /* appToken */, DEFAULT_DISPLAY, -1 /* width */,
3627 -1 /* height */, true /* includeFullDisplay */, 1f /* frameScale */,
3628 Bitmap.Config.ARGB_8888, true /* wallpaperOnly */, false /* includeDecor */);
3630 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
3635 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
3636 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
3637 * of the target image.
3640 public boolean requestAssistScreenshot(final IAssistScreenshotReceiver receiver) {
3641 if (!checkCallingPermission(READ_FRAME_BUFFER,
3642 "requestAssistScreenshot()")) {
3643 throw new SecurityException("Requires READ_FRAME_BUFFER permission");
3646 FgThread.getHandler().post(() -> {
3647 Bitmap bm = screenshotApplications(null /* appToken */, DEFAULT_DISPLAY,
3648 -1 /* width */, -1 /* height */, true /* includeFullDisplay */,
3649 1f /* frameScale */, Bitmap.Config.ARGB_8888, false /* wallpaperOnly */,
3650 false /* includeDecor */);
3653 } catch (RemoteException e) {
3660 public TaskSnapshot getTaskSnapshot(int taskId, int userId, boolean reducedResolution) {
3661 return mTaskSnapshotController.getSnapshot(taskId, userId, true /* restoreFromDisk */,
3666 * In case a task write/delete operation was lost because the system crashed, this makes sure to
3667 * clean up the directory to remove obsolete files.
3669 * @param persistentTaskIds A set of task ids that exist in our in-memory model.
3670 * @param runningUserIds The ids of the list of users that have tasks loaded in our in-memory
3673 public void removeObsoleteTaskFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds) {
3674 synchronized (mWindowMap) {
3675 mTaskSnapshotController.removeObsoleteTaskFiles(persistentTaskIds, runningUserIds);
3680 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
3681 * In portrait mode, it grabs the full screenshot.
3683 * @param displayId the Display to take a screenshot of.
3684 * @param width the width of the target bitmap
3685 * @param height the height of the target bitmap
3686 * @param includeFullDisplay true if the screen should not be cropped before capture
3687 * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
3688 * @param config of the output bitmap
3689 * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
3690 * @param includeDecor whether to include window decors, like the status or navigation bar
3691 * background of the window
3693 private Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
3694 int height, boolean includeFullDisplay, float frameScale, Bitmap.Config config,
3695 boolean wallpaperOnly, boolean includeDecor) {
3696 final DisplayContent displayContent;
3697 synchronized(mWindowMap) {
3698 displayContent = mRoot.getDisplayContentOrCreate(displayId);
3699 if (displayContent == null) {
3700 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
3701 + ": returning null. No Display for displayId=" + displayId);
3705 return displayContent.screenshotApplications(appToken, width, height,
3706 includeFullDisplay, frameScale, config, wallpaperOnly, includeDecor);
3710 * Freeze rotation changes. (Enable "rotation lock".)
3711 * Persists across reboots.
3712 * @param rotation The desired rotation to freeze to, or -1 to use the
3716 public void freezeRotation(int rotation) {
3717 // TODO(multi-display): Track which display is rotated.
3718 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
3719 "freezeRotation()")) {
3720 throw new SecurityException("Requires SET_ORIENTATION permission");
3722 if (rotation < -1 || rotation > Surface.ROTATION_270) {
3723 throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
3724 + "rotation constant.");
3727 final int defaultDisplayRotation = getDefaultDisplayRotation();
3728 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "freezeRotation: mRotation="
3729 + defaultDisplayRotation);
3731 long origId = Binder.clearCallingIdentity();
3733 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
3734 rotation == -1 ? defaultDisplayRotation : rotation);
3736 Binder.restoreCallingIdentity(origId);
3739 updateRotationUnchecked(false, false);
3743 * Thaw rotation changes. (Disable "rotation lock".)
3744 * Persists across reboots.
3747 public void thawRotation() {
3748 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
3749 "thawRotation()")) {
3750 throw new SecurityException("Requires SET_ORIENTATION permission");
3753 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "thawRotation: mRotation="
3754 + getDefaultDisplayRotation());
3756 long origId = Binder.clearCallingIdentity();
3758 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
3759 777); // rot not used
3761 Binder.restoreCallingIdentity(origId);
3764 updateRotationUnchecked(false, false);
3768 * Recalculate the current rotation.
3770 * Called by the window manager policy whenever the state of the system changes
3771 * such that the current rotation might need to be updated, such as when the
3772 * device is docked or rotated into a new posture.
3775 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
3776 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
3780 * Temporarily pauses rotation changes until resumed.
3782 * This can be used to prevent rotation changes from occurring while the user is
3783 * performing certain operations, such as drag and drop.
3785 * This call nests and must be matched by an equal number of calls to
3786 * {@link #resumeRotationLocked}.
3788 void pauseRotationLocked() {
3789 mDeferredRotationPauseCount += 1;
3793 * Resumes normal rotation changes after being paused.
3795 void resumeRotationLocked() {
3796 if (mDeferredRotationPauseCount > 0) {
3797 mDeferredRotationPauseCount -= 1;
3798 if (mDeferredRotationPauseCount == 0) {
3799 // TODO(multi-display): Update rotation for different displays separately.
3800 final DisplayContent displayContent = getDefaultDisplayContentLocked();
3801 final boolean changed = displayContent.updateRotationUnchecked(
3802 false /* inTransaction */);
3804 mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
3811 private void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
3812 if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked:"
3813 + " alwaysSendConfiguration=" + alwaysSendConfiguration
3814 + " forceRelayout=" + forceRelayout);
3816 long origId = Binder.clearCallingIdentity();
3819 final boolean rotationChanged;
3820 // TODO(multi-display): Update rotation for different displays separately.
3821 final DisplayContent displayContent = getDefaultDisplayContentLocked();
3822 synchronized (mWindowMap) {
3823 rotationChanged = displayContent.updateRotationUnchecked(
3824 false /* inTransaction */);
3825 if (!rotationChanged || forceRelayout) {
3826 getDefaultDisplayContentLocked().setLayoutNeeded();
3827 mWindowPlacerLocked.performSurfacePlacement();
3831 if (rotationChanged || alwaysSendConfiguration) {
3832 sendNewConfiguration(displayContent.getDisplayId());
3835 Binder.restoreCallingIdentity(origId);
3840 public int getDefaultDisplayRotation() {
3841 synchronized (mWindowMap) {
3842 return getDefaultDisplayContentLocked().getRotation();
3847 public boolean isRotationFrozen() {
3848 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
3852 public int watchRotation(IRotationWatcher watcher, int displayId) {
3853 final IBinder watcherBinder = watcher.asBinder();
3854 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
3856 public void binderDied() {
3857 synchronized (mWindowMap) {
3858 for (int i=0; i<mRotationWatchers.size(); i++) {
3859 if (watcherBinder == mRotationWatchers.get(i).mWatcher.asBinder()) {
3860 RotationWatcher removed = mRotationWatchers.remove(i);
3861 IBinder binder = removed.mWatcher.asBinder();
3862 if (binder != null) {
3863 binder.unlinkToDeath(this, 0);
3872 synchronized (mWindowMap) {
3874 watcher.asBinder().linkToDeath(dr, 0);
3875 mRotationWatchers.add(new RotationWatcher(watcher, dr, displayId));
3876 } catch (RemoteException e) {
3877 // Client died, no cleanup needed.
3880 return getDefaultDisplayRotation();
3885 public void removeRotationWatcher(IRotationWatcher watcher) {
3886 final IBinder watcherBinder = watcher.asBinder();
3887 synchronized (mWindowMap) {
3888 for (int i=0; i<mRotationWatchers.size(); i++) {
3889 RotationWatcher rotationWatcher = mRotationWatchers.get(i);
3890 if (watcherBinder == rotationWatcher.mWatcher.asBinder()) {
3891 RotationWatcher removed = mRotationWatchers.remove(i);
3892 IBinder binder = removed.mWatcher.asBinder();
3893 if (binder != null) {
3894 binder.unlinkToDeath(removed.mDeathRecipient, 0);
3903 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
3904 * theme attribute) on devices that feature a physical options menu key attempt to position
3905 * their menu panel window along the edge of the screen nearest the physical menu key.
3906 * This lowers the travel distance between invoking the menu panel and selecting
3909 * This method helps control where that menu is placed. Its current implementation makes
3910 * assumptions about the menu key and its relationship to the screen based on whether
3911 * the device's natural orientation is portrait (width < height) or landscape.
3913 * The menu key is assumed to be located along the bottom edge of natural-portrait
3914 * devices and along the right edge of natural-landscape devices. If these assumptions
3915 * do not hold for the target device, this method should be changed to reflect that.
3917 * @return A {@link Gravity} value for placing the options menu window
3920 public int getPreferredOptionsPanelGravity() {
3921 synchronized (mWindowMap) {
3922 // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
3923 final DisplayContent displayContent = getDefaultDisplayContentLocked();
3924 final int rotation = displayContent.getRotation();
3925 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
3926 // On devices with a natural orientation of portrait
3929 case Surface.ROTATION_0:
3930 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
3931 case Surface.ROTATION_90:
3932 return Gravity.RIGHT | Gravity.BOTTOM;
3933 case Surface.ROTATION_180:
3934 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
3935 case Surface.ROTATION_270:
3936 return Gravity.START | Gravity.BOTTOM;
3940 // On devices with a natural orientation of landscape
3943 case Surface.ROTATION_0:
3944 return Gravity.RIGHT | Gravity.BOTTOM;
3945 case Surface.ROTATION_90:
3946 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
3947 case Surface.ROTATION_180:
3948 return Gravity.START | Gravity.BOTTOM;
3949 case Surface.ROTATION_270:
3950 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
3956 * Starts the view server on the specified port.
3958 * @param port The port to listener to.
3960 * @return True if the server was successfully started, false otherwise.
3962 * @see com.android.server.wm.ViewServer
3963 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
3966 public boolean startViewServer(int port) {
3967 if (isSystemSecure()) {
3971 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
3979 if (mViewServer != null) {
3980 if (!mViewServer.isRunning()) {
3982 return mViewServer.start();
3983 } catch (IOException e) {
3984 Slog.w(TAG_WM, "View server did not start");
3991 mViewServer = new ViewServer(this, port);
3992 return mViewServer.start();
3993 } catch (IOException e) {
3994 Slog.w(TAG_WM, "View server did not start");
3999 private boolean isSystemSecure() {
4000 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
4001 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
4005 * Stops the view server if it exists.
4007 * @return True if the server stopped, false if it wasn't started or
4008 * couldn't be stopped.
4010 * @see com.android.server.wm.ViewServer
4013 public boolean stopViewServer() {
4014 if (isSystemSecure()) {
4018 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
4022 if (mViewServer != null) {
4023 return mViewServer.stop();
4029 * Indicates whether the view server is running.
4031 * @return True if the server is running, false otherwise.
4033 * @see com.android.server.wm.ViewServer
4036 public boolean isViewServerRunning() {
4037 if (isSystemSecure()) {
4041 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
4045 return mViewServer != null && mViewServer.isRunning();
4049 * Lists all available windows in the system. The listing is written in the specified Socket's
4050 * output stream with the following syntax: windowHashCodeInHexadecimal windowName
4051 * Each line of the output represents a different window.
4053 * @param client The remote client to send the listing to.
4054 * @return false if an error occurred, true otherwise.
4056 boolean viewServerListWindows(Socket client) {
4057 if (isSystemSecure()) {
4061 boolean result = true;
4063 final ArrayList<WindowState> windows = new ArrayList();
4064 synchronized (mWindowMap) {
4065 mRoot.forAllWindows(w -> {
4067 }, false /* traverseTopToBottom */);
4070 BufferedWriter out = null;
4072 // Any uncaught exception will crash the system process
4074 OutputStream clientStream = client.getOutputStream();
4075 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
4077 final int count = windows.size();
4078 for (int i = 0; i < count; i++) {
4079 final WindowState w = windows.get(i);
4080 out.write(Integer.toHexString(System.identityHashCode(w)));
4082 out.append(w.mAttrs.getTitle());
4086 out.write("DONE.\n");
4088 } catch (Exception e) {
4094 } catch (IOException e) {
4103 // TODO(multidisplay): Extend to multiple displays.
4105 * Returns the focused window in the following format:
4106 * windowHashCodeInHexadecimal windowName
4108 * @param client The remote client to send the listing to.
4109 * @return False if an error occurred, true otherwise.
4111 boolean viewServerGetFocusedWindow(Socket client) {
4112 if (isSystemSecure()) {
4116 boolean result = true;
4118 WindowState focusedWindow = getFocusedWindow();
4120 BufferedWriter out = null;
4122 // Any uncaught exception will crash the system process
4124 OutputStream clientStream = client.getOutputStream();
4125 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
4127 if(focusedWindow != null) {
4128 out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
4130 out.append(focusedWindow.mAttrs.getTitle());
4134 } catch (Exception e) {
4140 } catch (IOException e) {
4150 * Sends a command to a target window. The result of the command, if any, will be
4151 * written in the output stream of the specified socket.
4153 * The parameters must follow this syntax:
4154 * windowHashcode extra
4156 * Where XX is the length in characeters of the windowTitle.
4158 * The first parameter is the target window. The window with the specified hashcode
4159 * will be the target. If no target can be found, nothing happens. The extra parameters
4160 * will be delivered to the target window and as parameters to the command itself.
4162 * @param client The remote client to sent the result, if any, to.
4163 * @param command The command to execute.
4164 * @param parameters The command parameters.
4166 * @return True if the command was successfully delivered, false otherwise. This does
4167 * not indicate whether the command itself was successful.
4169 boolean viewServerWindowCommand(Socket client, String command, String parameters) {
4170 if (isSystemSecure()) {
4174 boolean success = true;
4176 Parcel reply = null;
4178 BufferedWriter out = null;
4180 // Any uncaught exception will crash the system process
4182 // Find the hashcode of the window
4183 int index = parameters.indexOf(' ');
4185 index = parameters.length();
4187 final String code = parameters.substring(0, index);
4188 int hashCode = (int) Long.parseLong(code, 16);
4190 // Extract the command's parameter after the window description
4191 if (index < parameters.length()) {
4192 parameters = parameters.substring(index + 1);
4197 final WindowState window = findWindow(hashCode);
4198 if (window == null) {
4202 data = Parcel.obtain();
4203 data.writeInterfaceToken("android.view.IWindow");
4204 data.writeString(command);
4205 data.writeString(parameters);
4207 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
4209 reply = Parcel.obtain();
4211 final IBinder binder = window.mClient.asBinder();
4212 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
4213 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
4215 reply.readException();
4217 if (!client.isOutputShutdown()) {
4218 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
4219 out.write("DONE\n");
4223 } catch (Exception e) {
4224 Slog.w(TAG_WM, "Could not send command " + command + " with parameters " + parameters, e);
4230 if (reply != null) {
4236 } catch (IOException e) {
4245 public void addWindowChangeListener(WindowChangeListener listener) {
4246 synchronized(mWindowMap) {
4247 mWindowChangeListeners.add(listener);
4251 public void removeWindowChangeListener(WindowChangeListener listener) {
4252 synchronized(mWindowMap) {
4253 mWindowChangeListeners.remove(listener);
4257 private void notifyWindowsChanged() {
4258 WindowChangeListener[] windowChangeListeners;
4259 synchronized(mWindowMap) {
4260 if(mWindowChangeListeners.isEmpty()) {
4263 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
4264 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
4266 int N = windowChangeListeners.length;
4267 for(int i = 0; i < N; i++) {
4268 windowChangeListeners[i].windowsChanged();
4272 private void notifyFocusChanged() {
4273 WindowChangeListener[] windowChangeListeners;
4274 synchronized(mWindowMap) {
4275 if(mWindowChangeListeners.isEmpty()) {
4278 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
4279 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
4281 int N = windowChangeListeners.length;
4282 for(int i = 0; i < N; i++) {
4283 windowChangeListeners[i].focusChanged();
4287 private WindowState findWindow(int hashCode) {
4288 if (hashCode == -1) {
4289 // TODO(multidisplay): Extend to multiple displays.
4290 return getFocusedWindow();
4293 synchronized (mWindowMap) {
4294 return mRoot.getWindow((w) -> System.identityHashCode(w) == hashCode);
4299 * Instruct the Activity Manager to fetch and update the current display's configuration and
4300 * broadcast them to config-changed listeners if appropriate.
4301 * NOTE: Can't be called with the window manager lock held since it call into activity manager.
4303 void sendNewConfiguration(int displayId) {
4305 final boolean configUpdated = mActivityManager.updateDisplayOverrideConfiguration(
4306 null /* values */, displayId);
4307 if (!configUpdated) {
4308 // Something changed (E.g. device rotation), but no configuration update is needed.
4309 // E.g. changing device rotation by 180 degrees. Go ahead and perform surface
4310 // placement to unfreeze the display since we froze it when the rotation was updated
4311 // in DisplayContent#updateRotationUnchecked.
4312 synchronized (mWindowMap) {
4313 if (mWaitingForConfig) {
4314 mWaitingForConfig = false;
4315 mLastFinishedFreezeSource = "config-unchanged";
4316 mRoot.getDisplayContent(displayId).setLayoutNeeded();
4317 mWindowPlacerLocked.performSurfacePlacement();
4321 } catch (RemoteException e) {
4325 public Configuration computeNewConfiguration(int displayId) {
4326 synchronized (mWindowMap) {
4327 return computeNewConfigurationLocked(displayId);
4331 private Configuration computeNewConfigurationLocked(int displayId) {
4332 if (!mDisplayReady) {
4335 final Configuration config = new Configuration();
4336 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
4337 displayContent.computeScreenConfiguration(config);
4341 void notifyHardKeyboardStatusChange() {
4342 final boolean available;
4343 final WindowManagerInternal.OnHardKeyboardStatusChangeListener listener;
4344 synchronized (mWindowMap) {
4345 listener = mHardKeyboardStatusChangeListener;
4346 available = mHardKeyboardAvailable;
4348 if (listener != null) {
4349 listener.onHardKeyboardStatusChange(available);
4353 boolean startMovingTask(IWindow window, float startX, float startY) {
4354 WindowState win = null;
4355 synchronized (mWindowMap) {
4356 win = windowForClientLocked(null, window, false);
4357 // win shouldn't be null here, pass it down to startPositioningLocked
4358 // to get warning if it's null.
4359 if (!startPositioningLocked(
4360 win, false /*resize*/, false /*preserveOrientation*/, startX, startY)) {
4365 mActivityManager.setFocusedTask(win.getTask().mTaskId);
4366 } catch(RemoteException e) {}
4370 private void handleTapOutsideTask(DisplayContent displayContent, int x, int y) {
4372 synchronized (mWindowMap) {
4373 final Task task = displayContent.findTaskForResizePoint(x, y);
4375 if (!startPositioningLocked(task.getTopVisibleAppMainWindow(), true /*resize*/,
4376 task.preserveOrientationOnResize(), x, y)) {
4379 taskId = task.mTaskId;
4381 taskId = displayContent.taskIdFromPoint(x, y);
4386 mActivityManager.setFocusedTask(taskId);
4387 } catch(RemoteException e) {}
4391 private boolean startPositioningLocked(WindowState win, boolean resize,
4392 boolean preserveOrientation, float startX, float startY) {
4393 if (DEBUG_TASK_POSITIONING)
4394 Slog.d(TAG_WM, "startPositioningLocked: "
4395 + "win=" + win + ", resize=" + resize + ", preserveOrientation="
4396 + preserveOrientation + ", {" + startX + ", " + startY + "}");
4398 if (win == null || win.getAppToken() == null) {
4399 Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win);
4402 if (win.mInputChannel == null) {
4403 Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, "
4404 + " probably being removed");
4408 final DisplayContent displayContent = win.getDisplayContent();
4409 if (displayContent == null) {
4410 Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win);
4414 Display display = displayContent.getDisplay();
4415 mTaskPositioner = new TaskPositioner(this);
4416 mTaskPositioner.register(display);
4417 mInputMonitor.updateInputWindowsLw(true /*force*/);
4419 // We need to grab the touch focus so that the touch events during the
4420 // resizing/scrolling are not sent to the app. 'win' is the main window
4421 // of the app, it may not have focus since there might be other windows
4422 // on top (eg. a dialog window).
4423 WindowState transferFocusFromWin = win;
4424 if (mCurrentFocus != null && mCurrentFocus != win
4425 && mCurrentFocus.mAppToken == win.mAppToken) {
4426 transferFocusFromWin = mCurrentFocus;
4428 if (!mInputManager.transferTouchFocus(
4429 transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) {
4430 Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
4431 mTaskPositioner.unregister();
4432 mTaskPositioner = null;
4433 mInputMonitor.updateInputWindowsLw(true /*force*/);
4437 mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY);
4441 private void finishPositioning() {
4442 if (DEBUG_TASK_POSITIONING) {
4443 Slog.d(TAG_WM, "finishPositioning");
4445 synchronized (mWindowMap) {
4446 if (mTaskPositioner != null) {
4447 mTaskPositioner.unregister();
4448 mTaskPositioner = null;
4449 mInputMonitor.updateInputWindowsLw(true /*force*/);
4454 // -------------------------------------------------------------
4456 // -------------------------------------------------------------
4458 IBinder prepareDragSurface(IWindow window, SurfaceSession session,
4459 int flags, int width, int height, Surface outSurface) {
4461 Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height
4462 + " flags=" + Integer.toHexString(flags) + " win=" + window
4463 + " asbinder=" + window.asBinder());
4466 final int callerPid = Binder.getCallingPid();
4467 final int callerUid = Binder.getCallingUid();
4468 final long origId = Binder.clearCallingIdentity();
4469 IBinder token = null;
4472 synchronized (mWindowMap) {
4474 if (mDragState == null) {
4475 // TODO(multi-display): support other displays
4476 final DisplayContent displayContent = getDefaultDisplayContentLocked();
4477 final Display display = displayContent.getDisplay();
4479 SurfaceControl surface = new SurfaceControl(session, "drag surface",
4480 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
4481 surface.setLayerStack(display.getLayerStack());
4483 if ((flags & View.DRAG_FLAG_OPAQUE) == 0) {
4484 alpha = DRAG_SHADOW_ALPHA_TRANSPARENT;
4486 surface.setAlpha(alpha);
4488 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " DRAG "
4489 + surface + ": CREATE");
4490 outSurface.copyFrom(surface);
4491 final IBinder winBinder = window.asBinder();
4492 token = new Binder();
4493 mDragState = new DragState(this, token, surface, flags, winBinder);
4494 mDragState.mPid = callerPid;
4495 mDragState.mUid = callerUid;
4496 mDragState.mOriginalAlpha = alpha;
4497 token = mDragState.mToken = new Binder();
4499 // 5 second timeout for this window to actually begin the drag
4500 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
4501 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
4502 mH.sendMessageDelayed(msg, 5000);
4504 Slog.w(TAG_WM, "Drag already in progress");
4506 } catch (OutOfResourcesException e) {
4507 Slog.e(TAG_WM, "Can't allocate drag surface w=" + width + " h=" + height, e);
4508 if (mDragState != null) {
4515 Binder.restoreCallingIdentity(origId);
4521 // -------------------------------------------------------------
4522 // Input Events and Focus Management
4523 // -------------------------------------------------------------
4525 final InputMonitor mInputMonitor = new InputMonitor(this);
4526 private boolean mEventDispatchingEnabled;
4529 public void setEventDispatching(boolean enabled) {
4530 if (!checkCallingPermission(MANAGE_APP_TOKENS, "setEventDispatching()")) {
4531 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4534 synchronized (mWindowMap) {
4535 mEventDispatchingEnabled = enabled;
4536 if (mDisplayEnabled) {
4537 mInputMonitor.setEventDispatchingLw(enabled);
4542 private WindowState getFocusedWindow() {
4543 synchronized (mWindowMap) {
4544 return getFocusedWindowLocked();
4548 private WindowState getFocusedWindowLocked() {
4549 return mCurrentFocus;
4552 TaskStack getImeFocusStackLocked() {
4553 // Don't use mCurrentFocus.getStack() because it returns home stack for system windows.
4554 // Also don't use mInputMethodTarget's stack, because some window with FLAG_NOT_FOCUSABLE
4555 // and FLAG_ALT_FOCUSABLE_IM flags both set might be set to IME target so they're moved
4556 // to make room for IME, but the window is not the focused window that's taking input.
4557 return (mFocusedApp != null && mFocusedApp.getTask() != null) ?
4558 mFocusedApp.getTask().mStack : null;
4561 public boolean detectSafeMode() {
4562 if (!mInputMonitor.waitForInputDevicesReady(
4563 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
4564 Slog.w(TAG_WM, "Devices still not ready after waiting "
4565 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
4566 + " milliseconds before attempting to detect safe mode.");
4569 if (Settings.Global.getInt(
4570 mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) {
4574 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
4575 KeyEvent.KEYCODE_MENU);
4576 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
4577 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
4578 KeyEvent.KEYCODE_DPAD_CENTER);
4579 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
4580 InputManagerService.BTN_MOUSE);
4581 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
4582 KeyEvent.KEYCODE_VOLUME_DOWN);
4583 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
4584 || volumeDownState > 0;
4586 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0
4587 || SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) != 0) {
4589 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
4591 } catch (IllegalArgumentException e) {
4594 Log.i(TAG_WM, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
4595 + " dpad=" + dpadState + " trackball=" + trackballState + ")");
4596 SystemProperties.set(ShutdownThread.RO_SAFEMODE_PROPERTY, "1");
4598 Log.i(TAG_WM, "SAFE MODE not enabled");
4600 mPolicy.setSafeMode(mSafeMode);
4604 public void displayReady() {
4605 for (Display display : mDisplays) {
4606 displayReady(display.getDisplayId());
4609 synchronized(mWindowMap) {
4610 final DisplayContent displayContent = getDefaultDisplayContentLocked();
4611 if (mMaxUiWidth > 0) {
4612 displayContent.setMaxUiWidth(mMaxUiWidth);
4614 readForcedDisplayPropertiesLocked(displayContent);
4615 mDisplayReady = true;
4619 mActivityManager.updateConfiguration(null);
4620 } catch (RemoteException e) {
4623 synchronized(mWindowMap) {
4624 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
4625 PackageManager.FEATURE_TOUCHSCREEN);
4626 configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
4630 mActivityManager.updateConfiguration(null);
4631 } catch (RemoteException e) {
4634 updateCircularDisplayMaskIfNeeded();
4637 private void displayReady(int displayId) {
4638 synchronized(mWindowMap) {
4639 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
4640 if (displayContent != null) {
4641 mAnimator.addDisplayLocked(displayId);
4642 displayContent.initializeDisplayBaseInfo();
4647 public void systemReady() {
4648 mPolicy.systemReady();
4649 mTaskSnapshotController.systemReady();
4652 // -------------------------------------------------------------
4654 // -------------------------------------------------------------
4656 final class H extends android.os.Handler {
4657 public static final int REPORT_FOCUS_CHANGE = 2;
4658 public static final int REPORT_LOSING_FOCUS = 3;
4659 public static final int WINDOW_FREEZE_TIMEOUT = 11;
4661 public static final int APP_TRANSITION_TIMEOUT = 13;
4662 public static final int PERSIST_ANIMATION_SCALE = 14;
4663 public static final int FORCE_GC = 15;
4664 public static final int ENABLE_SCREEN = 16;
4665 public static final int APP_FREEZE_TIMEOUT = 17;
4666 public static final int SEND_NEW_CONFIGURATION = 18;
4667 public static final int REPORT_WINDOWS_CHANGE = 19;
4668 public static final int DRAG_START_TIMEOUT = 20;
4669 public static final int DRAG_END_TIMEOUT = 21;
4670 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
4671 public static final int BOOT_TIMEOUT = 23;
4672 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
4673 public static final int SHOW_STRICT_MODE_VIOLATION = 25;
4674 public static final int DO_ANIMATION_CALLBACK = 26;
4676 public static final int CLIENT_FREEZE_TIMEOUT = 30;
4677 public static final int TAP_OUTSIDE_TASK = 31;
4678 public static final int NOTIFY_ACTIVITY_DRAWN = 32;
4680 public static final int ALL_WINDOWS_DRAWN = 33;
4682 public static final int NEW_ANIMATOR_SCALE = 34;
4684 public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35;
4685 public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36;
4687 public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37;
4688 public static final int RESET_ANR_MESSAGE = 38;
4689 public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39;
4691 public static final int FINISH_TASK_POSITIONING = 40;
4693 public static final int UPDATE_DOCKED_STACK_DIVIDER = 41;
4695 public static final int TEAR_DOWN_DRAG_AND_DROP_INPUT = 44;
4697 public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
4699 public static final int NOTIFY_APP_TRANSITION_STARTING = 47;
4700 public static final int NOTIFY_APP_TRANSITION_CANCELLED = 48;
4701 public static final int NOTIFY_APP_TRANSITION_FINISHED = 49;
4702 public static final int UPDATE_ANIMATION_SCALE = 51;
4703 public static final int WINDOW_HIDE_TIMEOUT = 52;
4704 public static final int NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED = 53;
4705 public static final int SEAMLESS_ROTATION_TIMEOUT = 54;
4706 public static final int RESTORE_POINTER_ICON = 55;
4707 public static final int NOTIFY_KEYGUARD_FLAGS_CHANGED = 56;
4708 public static final int NOTIFY_KEYGUARD_TRUSTED_CHANGED = 57;
4709 public static final int SET_HAS_OVERLAY_UI = 58;
4712 * Used to denote that an integer field in a message will not be used.
4714 public static final int UNUSED = 0;
4717 public void handleMessage(Message msg) {
4718 if (DEBUG_WINDOW_TRACE) {
4719 Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what);
4722 case REPORT_FOCUS_CHANGE: {
4723 WindowState lastFocus;
4724 WindowState newFocus;
4726 AccessibilityController accessibilityController = null;
4728 synchronized(mWindowMap) {
4729 // TODO(multidisplay): Accessibility supported only of default desiplay.
4730 if (mAccessibilityController != null && getDefaultDisplayContentLocked()
4731 .getDisplayId() == DEFAULT_DISPLAY) {
4732 accessibilityController = mAccessibilityController;
4735 lastFocus = mLastFocus;
4736 newFocus = mCurrentFocus;
4737 if (lastFocus == newFocus) {
4738 // Focus is not changing, so nothing to do.
4741 mLastFocus = newFocus;
4742 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Focus moving from " + lastFocus +
4744 if (newFocus != null && lastFocus != null
4745 && !newFocus.isDisplayedLw()) {
4746 //Slog.i(TAG_WM, "Delaying loss of focus...");
4747 mLosingFocus.add(lastFocus);
4752 // First notify the accessibility manager for the change so it has
4753 // the windows before the newly focused one starts firing eventgs.
4754 if (accessibilityController != null) {
4755 accessibilityController.onWindowFocusChangedNotLocked();
4758 //System.out.println("Changing focus from " + lastFocus
4759 // + " to " + newFocus);
4760 if (newFocus != null) {
4761 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Gaining focus: " + newFocus);
4762 newFocus.reportFocusChangedSerialized(true, mInTouchMode);
4763 notifyFocusChanged();
4766 if (lastFocus != null) {
4767 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing focus: " + lastFocus);
4768 lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
4772 case REPORT_LOSING_FOCUS: {
4773 ArrayList<WindowState> losers;
4775 synchronized(mWindowMap) {
4776 losers = mLosingFocus;
4777 mLosingFocus = new ArrayList<WindowState>();
4780 final int N = losers.size();
4781 for (int i=0; i<N; i++) {
4782 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing delayed focus: " +
4784 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
4788 case WINDOW_FREEZE_TIMEOUT: {
4789 // TODO(multidisplay): Can non-default displays rotate?
4790 synchronized (mWindowMap) {
4791 getDefaultDisplayContentLocked().onWindowFreezeTimeout();
4796 case APP_TRANSITION_TIMEOUT: {
4797 synchronized (mWindowMap) {
4798 if (mAppTransition.isTransitionSet() || !mOpeningApps.isEmpty()
4799 || !mClosingApps.isEmpty()) {
4800 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "*** APP TRANSITION TIMEOUT."
4801 + " isTransitionSet()=" + mAppTransition.isTransitionSet()
4802 + " mOpeningApps.size()=" + mOpeningApps.size()
4803 + " mClosingApps.size()=" + mClosingApps.size());
4804 mAppTransition.setTimeout();
4805 mWindowPlacerLocked.performSurfacePlacement();
4811 case PERSIST_ANIMATION_SCALE: {
4812 Settings.Global.putFloat(mContext.getContentResolver(),
4813 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
4814 Settings.Global.putFloat(mContext.getContentResolver(),
4815 Settings.Global.TRANSITION_ANIMATION_SCALE,
4816 mTransitionAnimationScaleSetting);
4817 Settings.Global.putFloat(mContext.getContentResolver(),
4818 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting);
4822 case UPDATE_ANIMATION_SCALE: {
4823 @UpdateAnimationScaleMode
4824 final int mode = msg.arg1;
4826 case WINDOW_ANIMATION_SCALE: {
4827 mWindowAnimationScaleSetting = Settings.Global.getFloat(
4828 mContext.getContentResolver(),
4829 Settings.Global.WINDOW_ANIMATION_SCALE,
4830 mWindowAnimationScaleSetting);
4833 case TRANSITION_ANIMATION_SCALE: {
4834 mTransitionAnimationScaleSetting = Settings.Global.getFloat(
4835 mContext.getContentResolver(),
4836 Settings.Global.TRANSITION_ANIMATION_SCALE,
4837 mTransitionAnimationScaleSetting);
4840 case ANIMATION_DURATION_SCALE: {
4841 mAnimatorDurationScaleSetting = Settings.Global.getFloat(
4842 mContext.getContentResolver(),
4843 Settings.Global.ANIMATOR_DURATION_SCALE,
4844 mAnimatorDurationScaleSetting);
4845 dispatchNewAnimatorScaleLocked(null);
4853 synchronized (mWindowMap) {
4854 // Since we're holding both mWindowMap and mAnimator we don't need to
4855 // hold mAnimator.mLayoutToAnim.
4856 if (mAnimator.isAnimating() || mAnimator.isAnimationScheduled()) {
4857 // If we are animating, don't do the gc now but
4858 // delay a bit so we don't interrupt the animation.
4859 sendEmptyMessageDelayed(H.FORCE_GC, 2000);
4862 // If we are currently rotating the display, it will
4863 // schedule a new message when done.
4864 if (mDisplayFrozen) {
4868 Runtime.getRuntime().gc();
4872 case ENABLE_SCREEN: {
4873 performEnableScreen();
4877 case APP_FREEZE_TIMEOUT: {
4878 synchronized (mWindowMap) {
4879 Slog.w(TAG_WM, "App freeze timeout expired.");
4880 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
4881 for (int i = mAppFreezeListeners.size() - 1; i >=0 ; --i) {
4882 mAppFreezeListeners.get(i).onAppFreezeTimeout();
4888 case CLIENT_FREEZE_TIMEOUT: {
4889 synchronized (mWindowMap) {
4890 if (mClientFreezingScreen) {
4891 mClientFreezingScreen = false;
4892 mLastFinishedFreezeSource = "client-timeout";
4893 stopFreezingDisplayLocked();
4899 case SEND_NEW_CONFIGURATION: {
4900 removeMessages(SEND_NEW_CONFIGURATION, msg.obj);
4901 final int displayId = (Integer) msg.obj;
4902 if (mRoot.getDisplayContent(displayId) != null) {
4903 sendNewConfiguration(displayId);
4905 // Message could come after display has already been removed.
4906 if (DEBUG_CONFIGURATION) {
4907 Slog.w(TAG, "Trying to send configuration to non-existing displayId="
4914 case REPORT_WINDOWS_CHANGE: {
4915 if (mWindowsChanged) {
4916 synchronized (mWindowMap) {
4917 mWindowsChanged = false;
4919 notifyWindowsChanged();
4924 case DRAG_START_TIMEOUT: {
4925 IBinder win = (IBinder)msg.obj;
4927 Slog.w(TAG_WM, "Timeout starting drag by win " + win);
4929 synchronized (mWindowMap) {
4930 // !!! TODO: ANR the app that has failed to start the drag in time
4931 if (mDragState != null) {
4932 mDragState.unregister();
4940 case DRAG_END_TIMEOUT: {
4941 IBinder win = (IBinder)msg.obj;
4943 Slog.w(TAG_WM, "Timeout ending drag to win " + win);
4945 synchronized (mWindowMap) {
4946 // !!! TODO: ANR the drag-receiving app
4947 if (mDragState != null) {
4948 mDragState.mDragResult = false;
4949 mDragState.endDragLw();
4955 case TEAR_DOWN_DRAG_AND_DROP_INPUT: {
4956 if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ending; tearing down input channel");
4957 DragState.InputInterceptor interceptor = (DragState.InputInterceptor) msg.obj;
4958 if (interceptor != null) {
4959 synchronized (mWindowMap) {
4960 interceptor.tearDown();
4966 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
4967 notifyHardKeyboardStatusChange();
4971 case BOOT_TIMEOUT: {
4972 performBootTimeout();
4976 case WAITING_FOR_DRAWN_TIMEOUT: {
4977 Runnable callback = null;
4978 synchronized (mWindowMap) {
4979 Slog.w(TAG_WM, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
4980 mWaitingForDrawn.clear();
4981 callback = mWaitingForDrawnCallback;
4982 mWaitingForDrawnCallback = null;
4984 if (callback != null) {
4990 case SHOW_STRICT_MODE_VIOLATION: {
4991 showStrictModeViolation(msg.arg1, msg.arg2);
4995 case SHOW_CIRCULAR_DISPLAY_MASK: {
4996 showCircularMask(msg.arg1 == 1);
5000 case SHOW_EMULATOR_DISPLAY_OVERLAY: {
5001 showEmulatorDisplayOverlay();
5005 case DO_ANIMATION_CALLBACK: {
5007 ((IRemoteCallback)msg.obj).sendResult(null);
5008 } catch (RemoteException e) {
5013 case TAP_OUTSIDE_TASK: {
5014 handleTapOutsideTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
5018 case FINISH_TASK_POSITIONING: {
5019 finishPositioning();
5023 case NOTIFY_ACTIVITY_DRAWN:
5025 mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
5026 } catch (RemoteException e) {
5029 case ALL_WINDOWS_DRAWN: {
5031 synchronized (mWindowMap) {
5032 callback = mWaitingForDrawnCallback;
5033 mWaitingForDrawnCallback = null;
5035 if (callback != null) {
5039 case NEW_ANIMATOR_SCALE: {
5040 float scale = getCurrentAnimatorScale();
5041 ValueAnimator.setDurationScale(scale);
5042 Session session = (Session)msg.obj;
5043 if (session != null) {
5045 session.mCallback.onAnimatorScaleChanged(scale);
5046 } catch (RemoteException e) {
5049 ArrayList<IWindowSessionCallback> callbacks
5050 = new ArrayList<IWindowSessionCallback>();
5051 synchronized (mWindowMap) {
5052 for (int i=0; i<mSessions.size(); i++) {
5053 callbacks.add(mSessions.valueAt(i).mCallback);
5057 for (int i=0; i<callbacks.size(); i++) {
5059 callbacks.get(i).onAnimatorScaleChanged(scale);
5060 } catch (RemoteException e) {
5066 case CHECK_IF_BOOT_ANIMATION_FINISHED: {
5067 final boolean bootAnimationComplete;
5068 synchronized (mWindowMap) {
5069 if (DEBUG_BOOT) Slog.i(TAG_WM, "CHECK_IF_BOOT_ANIMATION_FINISHED:");
5070 bootAnimationComplete = checkBootAnimationCompleteLocked();
5072 if (bootAnimationComplete) {
5073 performEnableScreen();
5077 case RESET_ANR_MESSAGE: {
5078 synchronized (mWindowMap) {
5079 mLastANRState = null;
5083 case WALLPAPER_DRAW_PENDING_TIMEOUT: {
5084 synchronized (mWindowMap) {
5085 if (mRoot.mWallpaperController.processWallpaperDrawPendingTimeout()) {
5086 mWindowPlacerLocked.performSurfacePlacement();
5090 case UPDATE_DOCKED_STACK_DIVIDER: {
5091 synchronized (mWindowMap) {
5092 final DisplayContent displayContent = getDefaultDisplayContentLocked();
5093 displayContent.getDockedDividerController().reevaluateVisibility(false);
5094 displayContent.adjustForImeIfNeeded();
5098 case WINDOW_REPLACEMENT_TIMEOUT: {
5099 synchronized (mWindowMap) {
5100 for (int i = mWindowReplacementTimeouts.size() - 1; i >= 0; i--) {
5101 final AppWindowToken token = mWindowReplacementTimeouts.get(i);
5102 token.onWindowReplacementTimeout();
5104 mWindowReplacementTimeouts.clear();
5107 case NOTIFY_APP_TRANSITION_STARTING: {
5108 mAmInternal.notifyAppTransitionStarting((SparseIntArray) msg.obj);
5111 case NOTIFY_APP_TRANSITION_CANCELLED: {
5112 mAmInternal.notifyAppTransitionCancelled();
5115 case NOTIFY_APP_TRANSITION_FINISHED: {
5116 mAmInternal.notifyAppTransitionFinished();
5119 case WINDOW_HIDE_TIMEOUT: {
5120 final WindowState window = (WindowState) msg.obj;
5121 synchronized(mWindowMap) {
5122 // TODO: This is all about fixing b/21693547
5123 // where partially initialized Toasts get stuck
5124 // around and keep the screen on. We'd like
5125 // to just remove the toast...but this can cause clients
5126 // who miss the timeout due to normal circumstances (e.g.
5127 // running under debugger) to crash (b/29105388). The windows will
5128 // eventually be removed when the client process finishes.
5129 // The best we can do for now is remove the FLAG_KEEP_SCREEN_ON
5130 // and prevent the symptoms of b/21693547. Since apps don't
5131 // support windows being removed under them we hide the window
5132 // and it will be removed when the app dies.
5133 window.mAttrs.flags &= ~FLAG_KEEP_SCREEN_ON;
5134 window.hidePermanentlyLw();
5135 window.setDisplayLayoutNeeded();
5136 mWindowPlacerLocked.performSurfacePlacement();
5140 case NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED: {
5141 mAmInternal.notifyDockedStackMinimizedChanged(msg.arg1 == 1);
5144 case RESTORE_POINTER_ICON: {
5145 synchronized (mWindowMap) {
5146 restorePointerIconLocked((DisplayContent)msg.obj, msg.arg1, msg.arg2);
5150 case SEAMLESS_ROTATION_TIMEOUT: {
5151 // Rotation only supported on primary display.
5152 // TODO(multi-display)
5153 synchronized(mWindowMap) {
5154 final DisplayContent dc = getDefaultDisplayContentLocked();
5155 dc.onSeamlessRotationTimeout();
5159 case NOTIFY_KEYGUARD_FLAGS_CHANGED: {
5160 mAmInternal.notifyKeyguardFlagsChanged((Runnable) msg.obj);
5163 case NOTIFY_KEYGUARD_TRUSTED_CHANGED: {
5164 mAmInternal.notifyKeyguardTrustedChanged();
5167 case SET_HAS_OVERLAY_UI: {
5168 mAmInternal.setHasOverlayUi(msg.arg1, msg.arg2 == 1);
5172 if (DEBUG_WINDOW_TRACE) {
5173 Slog.v(TAG_WM, "handleMessage: exit");
5178 void destroyPreservedSurfaceLocked() {
5179 for (int i = mDestroyPreservedSurface.size() - 1; i >= 0 ; i--) {
5180 final WindowState w = mDestroyPreservedSurface.get(i);
5181 w.mWinAnimator.destroyPreservedSurfaceLocked();
5183 mDestroyPreservedSurface.clear();
5186 void stopUsingSavedSurfaceLocked() {
5187 for (int i = mFinishedEarlyAnim.size() - 1; i >= 0 ; i--) {
5188 final AppWindowToken wtoken = mFinishedEarlyAnim.get(i);
5189 wtoken.stopUsingSavedSurfaceLocked();
5191 mFinishedEarlyAnim.clear();
5194 // -------------------------------------------------------------
5195 // IWindowManager API
5196 // -------------------------------------------------------------
5199 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
5200 IInputContext inputContext) {
5201 if (client == null) throw new IllegalArgumentException("null client");
5202 if (inputContext == null) throw new IllegalArgumentException("null inputContext");
5203 Session session = new Session(this, callback, client, inputContext);
5208 public boolean inputMethodClientHasFocus(IInputMethodClient client) {
5209 synchronized (mWindowMap) {
5210 // TODO: multi-display
5211 if (getDefaultDisplayContentLocked().inputMethodClientHasFocus(client)) {
5215 // Okay, how about this... what is the current focus?
5216 // It seems in some cases we may not have moved the IM
5217 // target window, such as when it was in a pop-up window,
5218 // so let's also look at the current focus. (An example:
5219 // go to Gmail, start searching so the keyboard goes up,
5220 // press home. Sometimes the IME won't go down.)
5221 // Would be nice to fix this more correctly, but it's
5222 // way at the end of a release, and this should be good enough.
5223 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
5224 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
5232 public void getInitialDisplaySize(int displayId, Point size) {
5233 synchronized (mWindowMap) {
5234 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5235 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
5236 size.x = displayContent.mInitialDisplayWidth;
5237 size.y = displayContent.mInitialDisplayHeight;
5243 public void getBaseDisplaySize(int displayId, Point size) {
5244 synchronized (mWindowMap) {
5245 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5246 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
5247 size.x = displayContent.mBaseDisplayWidth;
5248 size.y = displayContent.mBaseDisplayHeight;
5254 public void setForcedDisplaySize(int displayId, int width, int height) {
5255 if (mContext.checkCallingOrSelfPermission(
5256 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5257 PackageManager.PERMISSION_GRANTED) {
5258 throw new SecurityException("Must hold permission " +
5259 android.Manifest.permission.WRITE_SECURE_SETTINGS);
5261 if (displayId != DEFAULT_DISPLAY) {
5262 throw new IllegalArgumentException("Can only set the default display");
5264 final long ident = Binder.clearCallingIdentity();
5266 synchronized(mWindowMap) {
5267 // Set some sort of reasonable bounds on the size of the display that we
5268 // will try to emulate.
5269 final int MIN_WIDTH = 200;
5270 final int MIN_HEIGHT = 200;
5271 final int MAX_SCALE = 2;
5272 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5273 if (displayContent != null) {
5274 width = Math.min(Math.max(width, MIN_WIDTH),
5275 displayContent.mInitialDisplayWidth * MAX_SCALE);
5276 height = Math.min(Math.max(height, MIN_HEIGHT),
5277 displayContent.mInitialDisplayHeight * MAX_SCALE);
5278 setForcedDisplaySizeLocked(displayContent, width, height);
5279 Settings.Global.putString(mContext.getContentResolver(),
5280 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
5284 Binder.restoreCallingIdentity(ident);
5289 public void setForcedDisplayScalingMode(int displayId, int mode) {
5290 if (mContext.checkCallingOrSelfPermission(
5291 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5292 PackageManager.PERMISSION_GRANTED) {
5293 throw new SecurityException("Must hold permission " +
5294 android.Manifest.permission.WRITE_SECURE_SETTINGS);
5296 if (displayId != DEFAULT_DISPLAY) {
5297 throw new IllegalArgumentException("Can only set the default display");
5299 final long ident = Binder.clearCallingIdentity();
5301 synchronized(mWindowMap) {
5302 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5303 if (displayContent != null) {
5304 if (mode < 0 || mode > 1) {
5307 setForcedDisplayScalingModeLocked(displayContent, mode);
5308 Settings.Global.putInt(mContext.getContentResolver(),
5309 Settings.Global.DISPLAY_SCALING_FORCE, mode);
5313 Binder.restoreCallingIdentity(ident);
5317 private void setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode) {
5318 Slog.i(TAG_WM, "Using display scaling mode: " + (mode == 0 ? "auto" : "off"));
5319 displayContent.mDisplayScalingDisabled = (mode != 0);
5320 reconfigureDisplayLocked(displayContent);
5323 private void readForcedDisplayPropertiesLocked(final DisplayContent displayContent) {
5325 String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
5326 Settings.Global.DISPLAY_SIZE_FORCED);
5327 if (sizeStr == null || sizeStr.length() == 0) {
5328 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
5330 if (sizeStr != null && sizeStr.length() > 0) {
5331 final int pos = sizeStr.indexOf(',');
5332 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
5335 width = Integer.parseInt(sizeStr.substring(0, pos));
5336 height = Integer.parseInt(sizeStr.substring(pos+1));
5337 if (displayContent.mBaseDisplayWidth != width
5338 || displayContent.mBaseDisplayHeight != height) {
5339 Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
5340 displayContent.updateBaseDisplayMetrics(width, height,
5341 displayContent.mBaseDisplayDensity);
5343 } catch (NumberFormatException ex) {
5349 final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId);
5351 displayContent.mBaseDisplayDensity = density;
5354 // Display scaling mode.
5355 int mode = Settings.Global.getInt(mContext.getContentResolver(),
5356 Settings.Global.DISPLAY_SCALING_FORCE, 0);
5358 Slog.i(TAG_WM, "FORCED DISPLAY SCALING DISABLED");
5359 displayContent.mDisplayScalingDisabled = true;
5363 // displayContent must not be null
5364 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
5365 Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
5366 displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity);
5367 reconfigureDisplayLocked(displayContent);
5371 public void clearForcedDisplaySize(int displayId) {
5372 if (mContext.checkCallingOrSelfPermission(
5373 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5374 PackageManager.PERMISSION_GRANTED) {
5375 throw new SecurityException("Must hold permission " +
5376 android.Manifest.permission.WRITE_SECURE_SETTINGS);
5378 if (displayId != DEFAULT_DISPLAY) {
5379 throw new IllegalArgumentException("Can only set the default display");
5381 final long ident = Binder.clearCallingIdentity();
5383 synchronized(mWindowMap) {
5384 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5385 if (displayContent != null) {
5386 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
5387 displayContent.mInitialDisplayHeight);
5388 Settings.Global.putString(mContext.getContentResolver(),
5389 Settings.Global.DISPLAY_SIZE_FORCED, "");
5393 Binder.restoreCallingIdentity(ident);
5398 public int getInitialDisplayDensity(int displayId) {
5399 synchronized (mWindowMap) {
5400 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5401 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
5402 return displayContent.mInitialDisplayDensity;
5409 public int getBaseDisplayDensity(int displayId) {
5410 synchronized (mWindowMap) {
5411 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5412 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
5413 return displayContent.mBaseDisplayDensity;
5420 public void setForcedDisplayDensityForUser(int displayId, int density, int userId) {
5421 if (mContext.checkCallingOrSelfPermission(
5422 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5423 PackageManager.PERMISSION_GRANTED) {
5424 throw new SecurityException("Must hold permission " +
5425 android.Manifest.permission.WRITE_SECURE_SETTINGS);
5427 if (displayId != DEFAULT_DISPLAY) {
5428 throw new IllegalArgumentException("Can only set the default display");
5431 final int targetUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
5432 Binder.getCallingUid(), userId, false, true, "setForcedDisplayDensityForUser",
5434 final long ident = Binder.clearCallingIdentity();
5436 synchronized(mWindowMap) {
5437 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5438 if (displayContent != null && mCurrentUserId == targetUserId) {
5439 setForcedDisplayDensityLocked(displayContent, density);
5441 Settings.Secure.putStringForUser(mContext.getContentResolver(),
5442 Settings.Secure.DISPLAY_DENSITY_FORCED,
5443 Integer.toString(density), targetUserId);
5446 Binder.restoreCallingIdentity(ident);
5451 public void clearForcedDisplayDensityForUser(int displayId, int userId) {
5452 if (mContext.checkCallingOrSelfPermission(
5453 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5454 PackageManager.PERMISSION_GRANTED) {
5455 throw new SecurityException("Must hold permission " +
5456 android.Manifest.permission.WRITE_SECURE_SETTINGS);
5458 if (displayId != DEFAULT_DISPLAY) {
5459 throw new IllegalArgumentException("Can only set the default display");
5462 final int callingUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
5463 Binder.getCallingUid(), userId, false, true, "clearForcedDisplayDensityForUser",
5465 final long ident = Binder.clearCallingIdentity();
5467 synchronized(mWindowMap) {
5468 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5469 if (displayContent != null && mCurrentUserId == callingUserId) {
5470 setForcedDisplayDensityLocked(displayContent,
5471 displayContent.mInitialDisplayDensity);
5473 Settings.Secure.putStringForUser(mContext.getContentResolver(),
5474 Settings.Secure.DISPLAY_DENSITY_FORCED, "", callingUserId);
5477 Binder.restoreCallingIdentity(ident);
5482 * @param userId the ID of the user
5483 * @return the forced display density for the specified user, if set, or
5484 * {@code 0} if not set
5486 private int getForcedDisplayDensityForUserLocked(int userId) {
5487 String densityStr = Settings.Secure.getStringForUser(mContext.getContentResolver(),
5488 Settings.Secure.DISPLAY_DENSITY_FORCED, userId);
5489 if (densityStr == null || densityStr.length() == 0) {
5490 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
5492 if (densityStr != null && densityStr.length() > 0) {
5494 return Integer.parseInt(densityStr);
5495 } catch (NumberFormatException ex) {
5502 * Forces the given display to the use the specified density.
5504 * @param displayContent the display to modify
5505 * @param density the density in DPI to use
5507 private void setForcedDisplayDensityLocked(@NonNull DisplayContent displayContent,
5509 displayContent.mBaseDisplayDensity = density;
5510 reconfigureDisplayLocked(displayContent);
5513 void reconfigureDisplayLocked(@NonNull DisplayContent displayContent) {
5514 if (!mDisplayReady) {
5517 configureDisplayPolicyLocked(displayContent);
5518 displayContent.setLayoutNeeded();
5520 final int displayId = displayContent.getDisplayId();
5521 boolean configChanged = updateOrientationFromAppTokensLocked(false /* inTransaction */,
5523 final Configuration currentDisplayConfig = displayContent.getConfiguration();
5524 mTempConfiguration.setTo(currentDisplayConfig);
5525 displayContent.computeScreenConfiguration(mTempConfiguration);
5526 configChanged |= currentDisplayConfig.diff(mTempConfiguration) != 0;
5528 if (configChanged) {
5529 mWaitingForConfig = true;
5530 startFreezingDisplayLocked(false /* inTransaction */, 0 /* exitAnim */,
5532 mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
5535 mWindowPlacerLocked.performSurfacePlacement();
5538 void configureDisplayPolicyLocked(DisplayContent displayContent) {
5539 mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
5540 displayContent.mBaseDisplayWidth,
5541 displayContent.mBaseDisplayHeight,
5542 displayContent.mBaseDisplayDensity);
5544 DisplayInfo displayInfo = displayContent.getDisplayInfo();
5545 mPolicy.setDisplayOverscan(displayContent.getDisplay(),
5546 displayInfo.overscanLeft, displayInfo.overscanTop,
5547 displayInfo.overscanRight, displayInfo.overscanBottom);
5551 * Get an array with display ids ordered by focus priority - last items should be given
5552 * focus first. Sparse array just maps position to displayId.
5554 // TODO: Maintain display list in focus order in ActivityManager and remove this call.
5555 public void getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder) {
5556 synchronized(mWindowMap) {
5557 mRoot.getDisplaysInFocusOrder(displaysInFocusOrder);
5562 public void setOverscan(int displayId, int left, int top, int right, int bottom) {
5563 if (mContext.checkCallingOrSelfPermission(
5564 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5565 PackageManager.PERMISSION_GRANTED) {
5566 throw new SecurityException("Must hold permission " +
5567 android.Manifest.permission.WRITE_SECURE_SETTINGS);
5569 final long ident = Binder.clearCallingIdentity();
5571 synchronized(mWindowMap) {
5572 DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5573 if (displayContent != null) {
5574 setOverscanLocked(displayContent, left, top, right, bottom);
5578 Binder.restoreCallingIdentity(ident);
5582 private void setOverscanLocked(DisplayContent displayContent,
5583 int left, int top, int right, int bottom) {
5584 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5585 displayInfo.overscanLeft = left;
5586 displayInfo.overscanTop = top;
5587 displayInfo.overscanRight = right;
5588 displayInfo.overscanBottom = bottom;
5590 mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, displayInfo.name, left, top,
5592 mDisplaySettings.writeSettingsLocked();
5594 reconfigureDisplayLocked(displayContent);
5597 // -------------------------------------------------------------
5599 // -------------------------------------------------------------
5601 final WindowState windowForClientLocked(Session session, IWindow client, boolean throwOnError) {
5602 return windowForClientLocked(session, client.asBinder(), throwOnError);
5605 final WindowState windowForClientLocked(Session session, IBinder client, boolean throwOnError) {
5606 WindowState win = mWindowMap.get(client);
5607 if (localLOGV) Slog.v(TAG_WM, "Looking up client " + client + ": " + win);
5609 RuntimeException ex = new IllegalArgumentException(
5610 "Requested window " + client + " does not exist");
5614 Slog.w(TAG_WM, "Failed looking up window", ex);
5617 if (session != null && win.mSession != session) {
5618 RuntimeException ex = new IllegalArgumentException(
5619 "Requested window " + client + " is in session " +
5620 win.mSession + ", not " + session);
5624 Slog.w(TAG_WM, "Failed looking up window", ex);
5631 void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
5632 // If the screen is currently frozen or off, then keep
5633 // it frozen/off until this window draws at its new
5635 if (!okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
5636 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w);
5637 w.mOrientationChanging = true;
5638 w.mLastFreezeDuration = 0;
5639 mRoot.mOrientationChangeComplete = false;
5640 if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) {
5641 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
5642 // XXX should probably keep timeout from
5643 // when we first froze the display.
5644 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
5645 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
5646 WINDOW_FREEZE_TIMEOUT_DURATION);
5652 * @return bitmap indicating if another pass through layout must be made.
5654 int handleAnimatingStoppedAndTransitionLocked() {
5657 mAppTransition.setIdle();
5659 for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) {
5660 final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i);
5661 mAppTransition.notifyAppTransitionFinishedLocked(token);
5663 mNoAnimationNotifyOnTransitionFinished.clear();
5665 // TODO: multi-display.
5666 final DisplayContent dc = getDefaultDisplayContentLocked();
5668 dc.mWallpaperController.hideDeferredWallpapersIfNeeded();
5670 dc.onAppTransitionDone();
5672 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5673 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM,
5674 "Wallpaper layer changed: assigning layers + relayout");
5675 dc.computeImeTarget(true /* updateImeTarget */);
5676 mRoot.mWallpaperMayChange = true;
5677 // Since the window list has been rebuilt, focus might have to be recomputed since the
5678 // actual order of windows might have changed again.
5679 mFocusMayChange = true;
5684 void checkDrawnWindowsLocked() {
5685 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
5688 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
5689 WindowState win = mWaitingForDrawn.get(j);
5690 if (DEBUG_SCREEN_ON) Slog.i(TAG_WM, "Waiting for drawn " + win +
5691 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
5692 " mHasSurface=" + win.mHasSurface +
5693 " drawState=" + win.mWinAnimator.mDrawState);
5694 if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) {
5695 // Window has been removed or hidden; no draw will now happen, so stop waiting.
5696 if (DEBUG_SCREEN_ON) Slog.w(TAG_WM, "Aborted waiting for drawn: " + win);
5697 mWaitingForDrawn.remove(win);
5698 } else if (win.hasDrawnLw()) {
5699 // Window is now drawn (and shown).
5700 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "Window drawn win=" + win);
5701 mWaitingForDrawn.remove(win);
5704 if (mWaitingForDrawn.isEmpty()) {
5705 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "All windows drawn!");
5706 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
5707 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
5711 void setHoldScreenLocked(final Session newHoldScreen) {
5712 final boolean hold = newHoldScreen != null;
5714 if (hold && mHoldingScreenOn != newHoldScreen) {
5715 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
5717 mHoldingScreenOn = newHoldScreen;
5719 final boolean state = mHoldingScreenWakeLock.isHeld();
5720 if (hold != state) {
5722 if (DEBUG_KEEP_SCREEN_ON) {
5723 Slog.d(TAG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to "
5724 + mRoot.mHoldScreenWindow);
5726 mLastWakeLockHoldingWindow = mRoot.mHoldScreenWindow;
5727 mLastWakeLockObscuringWindow = null;
5728 mHoldingScreenWakeLock.acquire();
5729 mPolicy.keepScreenOnStartedLw();
5731 if (DEBUG_KEEP_SCREEN_ON) {
5732 Slog.d(TAG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by "
5733 + mRoot.mObscuringWindow);
5735 mLastWakeLockHoldingWindow = null;
5736 mLastWakeLockObscuringWindow = mRoot.mObscuringWindow;
5737 mPolicy.keepScreenOnStoppedLw();
5738 mHoldingScreenWakeLock.release();
5743 void requestTraversal() {
5744 synchronized (mWindowMap) {
5745 mWindowPlacerLocked.requestTraversal();
5749 /** Note that Locked in this case is on mLayoutToAnim */
5750 void scheduleAnimationLocked() {
5751 mAnimator.scheduleAnimation();
5754 // TODO: Move to DisplayContent
5755 boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
5756 WindowState newFocus = mRoot.computeFocusedWindow();
5757 if (mCurrentFocus != newFocus) {
5758 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
5759 // This check makes sure that we don't already have the focus
5760 // change message pending.
5761 mH.removeMessages(H.REPORT_FOCUS_CHANGE);
5762 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
5763 // TODO(multidisplay): Focused windows on default display only.
5764 final DisplayContent displayContent = getDefaultDisplayContentLocked();
5765 boolean imWindowChanged = false;
5766 if (mInputMethodWindow != null) {
5767 final WindowState prevTarget = mInputMethodTarget;
5768 final WindowState newTarget =
5769 displayContent.computeImeTarget(true /* updateImeTarget*/);
5771 imWindowChanged = prevTarget != newTarget;
5773 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
5774 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) {
5775 final int prevImeAnimLayer = mInputMethodWindow.mWinAnimator.mAnimLayer;
5776 displayContent.assignWindowLayers(false /* setLayoutNeeded */);
5778 prevImeAnimLayer != mInputMethodWindow.mWinAnimator.mAnimLayer;
5782 if (imWindowChanged) {
5783 mWindowsChanged = true;
5784 displayContent.setLayoutNeeded();
5785 newFocus = mRoot.computeFocusedWindow();
5788 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG_WM, "Changing focus from " +
5789 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
5790 final WindowState oldFocus = mCurrentFocus;
5791 mCurrentFocus = newFocus;
5792 mLosingFocus.remove(newFocus);
5794 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
5796 if (imWindowChanged && oldFocus != mInputMethodWindow) {
5797 // Focus of the input method window changed. Perform layout if needed.
5798 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
5799 displayContent.performLayout(true /*initial*/, updateInputWindows);
5800 focusChanged &= ~FINISH_LAYOUT_REDO_LAYOUT;
5801 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
5802 // Client will do the layout, but we need to assign layers
5803 // for handleNewWindowLocked() below.
5804 displayContent.assignWindowLayers(false /* setLayoutNeeded */);
5808 if ((focusChanged & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
5809 // The change in focus caused us to need to do a layout. Okay.
5810 displayContent.setLayoutNeeded();
5811 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
5812 displayContent.performLayout(true /*initial*/, updateInputWindows);
5816 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
5817 // If we defer assigning layers, then the caller is responsible for
5819 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
5822 displayContent.adjustForImeIfNeeded();
5824 // We may need to schedule some toast windows to be removed. The toasts for an app that
5825 // does not have input focus are removed within a timeout to prevent apps to redress
5827 displayContent.scheduleToastWindowsTimeoutIfNeededLocked(oldFocus, newFocus);
5829 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
5835 void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
5836 if (mDisplayFrozen) {
5840 if (!mDisplayReady || !mPolicy.isScreenOn()) {
5841 // No need to freeze the screen before the system is ready or if
5842 // the screen is off.
5846 if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
5847 "startFreezingDisplayLocked: inTransaction=" + inTransaction
5848 + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim
5849 + " called by " + Debug.getCallers(8));
5850 mScreenFrozenLock.acquire();
5852 mDisplayFrozen = true;
5853 mDisplayFreezeTime = SystemClock.elapsedRealtime();
5854 mLastFinishedFreezeSource = null;
5856 mInputMonitor.freezeInputDispatchingLw();
5858 // Clear the last input window -- that is just used for
5859 // clean transitions between IMEs, and if we are freezing
5860 // the screen then the whole world is changing behind the scenes.
5861 mPolicy.setLastInputMethodWindowLw(null, null);
5863 if (mAppTransition.isTransitionSet()) {
5864 mAppTransition.freeze();
5867 if (PROFILE_ORIENTATION) {
5868 File file = new File("/data/system/frozen");
5869 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
5872 if (CUSTOM_SCREEN_ROTATION) {
5873 mExitAnimId = exitAnim;
5874 mEnterAnimId = enterAnim;
5875 final DisplayContent displayContent = getDefaultDisplayContentLocked();
5876 final int displayId = displayContent.getDisplayId();
5877 ScreenRotationAnimation screenRotationAnimation =
5878 mAnimator.getScreenRotationAnimationLocked(displayId);
5879 if (screenRotationAnimation != null) {
5880 screenRotationAnimation.kill();
5883 // Check whether the current screen contains any secure content.
5884 boolean isSecure = displayContent.hasSecureWindowOnScreen();
5886 // TODO(multidisplay): rotation on main screen only.
5887 displayContent.updateDisplayInfo();
5888 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
5889 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure, this);
5890 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
5894 void stopFreezingDisplayLocked() {
5895 if (!mDisplayFrozen) {
5899 if (mWaitingForConfig || mAppsFreezingScreen > 0
5900 || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE
5901 || mClientFreezingScreen || !mOpeningApps.isEmpty()) {
5902 if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
5903 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
5904 + ", mAppsFreezingScreen=" + mAppsFreezingScreen
5905 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
5906 + ", mClientFreezingScreen=" + mClientFreezingScreen
5907 + ", mOpeningApps.size()=" + mOpeningApps.size());
5911 if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
5912 "stopFreezingDisplayLocked: Unfreezing now");
5914 mDisplayFrozen = false;
5915 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
5916 StringBuilder sb = new StringBuilder(128);
5917 sb.append("Screen frozen for ");
5918 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
5919 if (mLastFinishedFreezeSource != null) {
5920 sb.append(" due to ");
5921 sb.append(mLastFinishedFreezeSource);
5923 Slog.i(TAG_WM, sb.toString());
5924 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
5925 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
5926 if (PROFILE_ORIENTATION) {
5927 Debug.stopMethodTracing();
5930 boolean updateRotation = false;
5932 final DisplayContent displayContent = getDefaultDisplayContentLocked();
5933 final int displayId = displayContent.getDisplayId();
5934 ScreenRotationAnimation screenRotationAnimation =
5935 mAnimator.getScreenRotationAnimationLocked(displayId);
5936 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
5937 && screenRotationAnimation.hasScreenshot()) {
5938 if (DEBUG_ORIENTATION) Slog.i(TAG_WM, "**** Dismissing screen rotation animation");
5939 // TODO(multidisplay): rotation on main screen only.
5940 DisplayInfo displayInfo = displayContent.getDisplayInfo();
5941 // Get rotation animation again, with new top window
5942 boolean isDimming = displayContent.isDimming();
5943 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
5944 mExitAnimId = mEnterAnimId = 0;
5946 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
5947 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth,
5948 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
5949 scheduleAnimationLocked();
5951 screenRotationAnimation.kill();
5952 mAnimator.setScreenRotationAnimationLocked(displayId, null);
5953 updateRotation = true;
5956 if (screenRotationAnimation != null) {
5957 screenRotationAnimation.kill();
5958 mAnimator.setScreenRotationAnimationLocked(displayId, null);
5960 updateRotation = true;
5963 mInputMonitor.thawInputDispatchingLw();
5965 boolean configChanged;
5967 // While the display is frozen we don't re-compute the orientation
5968 // to avoid inconsistent states. However, something interesting
5969 // could have actually changed during that time so re-evaluate it
5970 // now to catch that.
5971 configChanged = updateOrientationFromAppTokensLocked(false, displayId);
5973 // A little kludge: a lot could have happened while the
5974 // display was frozen, so now that we are coming back we
5975 // do a gc so that any remote references the system
5976 // processes holds on others can be released if they are
5977 // no longer needed.
5978 mH.removeMessages(H.FORCE_GC);
5979 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
5981 mScreenFrozenLock.release();
5983 if (updateRotation) {
5984 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation");
5985 configChanged |= displayContent.updateRotationUnchecked(
5986 false /* inTransaction */);
5989 if (configChanged) {
5990 mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
5994 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
5995 DisplayMetrics dm) {
5996 if (index < tokens.length) {
5997 String str = tokens[index];
5998 if (str != null && str.length() > 0) {
6000 int val = Integer.parseInt(str);
6002 } catch (Exception e) {
6006 if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
6009 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
6013 void createWatermarkInTransaction() {
6014 if (mWatermark != null) {
6018 File file = new File("/system/etc/setup.conf");
6019 FileInputStream in = null;
6020 DataInputStream ind = null;
6022 in = new FileInputStream(file);
6023 ind = new DataInputStream(in);
6024 String line = ind.readLine();
6026 String[] toks = line.split("%");
6027 if (toks != null && toks.length > 0) {
6028 // TODO(multi-display): Show watermarks on secondary displays.
6029 final DisplayContent displayContent = getDefaultDisplayContentLocked();
6030 mWatermark = new Watermark(displayContent.getDisplay(),
6031 displayContent.mRealDisplayMetrics, mFxSession, toks);
6034 } catch (FileNotFoundException e) {
6035 } catch (IOException e) {
6040 } catch (IOException e) {
6042 } else if (in != null) {
6045 } catch (IOException e) {
6052 public void setRecentsVisibility(boolean visible) {
6053 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
6054 != PackageManager.PERMISSION_GRANTED) {
6055 throw new SecurityException("Caller does not hold permission "
6056 + android.Manifest.permission.STATUS_BAR);
6059 synchronized (mWindowMap) {
6060 mPolicy.setRecentsVisibilityLw(visible);
6065 public void setPipVisibility(boolean visible) {
6066 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
6067 != PackageManager.PERMISSION_GRANTED) {
6068 throw new SecurityException("Caller does not hold permission "
6069 + android.Manifest.permission.STATUS_BAR);
6072 synchronized (mWindowMap) {
6073 mPolicy.setPipVisibilityLw(visible);
6078 public void statusBarVisibilityChanged(int visibility) {
6079 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
6080 != PackageManager.PERMISSION_GRANTED) {
6081 throw new SecurityException("Caller does not hold permission "
6082 + android.Manifest.permission.STATUS_BAR);
6085 synchronized (mWindowMap) {
6086 mLastStatusBarVisibility = visibility;
6087 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
6088 updateStatusBarVisibilityLocked(visibility);
6092 // TODO(multidisplay): StatusBar on multiple screens?
6093 private boolean updateStatusBarVisibilityLocked(int visibility) {
6094 if (mLastDispatchedSystemUiVisibility == visibility) {
6097 final int globalDiff = (visibility ^ mLastDispatchedSystemUiVisibility)
6098 // We are only interested in differences of one of the
6099 // clearable flags...
6100 & View.SYSTEM_UI_CLEARABLE_FLAGS
6101 // ...if it has actually been cleared.
6104 mLastDispatchedSystemUiVisibility = visibility;
6105 mInputManager.setSystemUiVisibility(visibility);
6106 getDefaultDisplayContentLocked().updateSystemUiVisibility(visibility, globalDiff);
6111 public void reevaluateStatusBarVisibility() {
6112 synchronized (mWindowMap) {
6113 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
6114 if (updateStatusBarVisibilityLocked(visibility)) {
6115 mWindowPlacerLocked.requestTraversal();
6121 public WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name,
6122 InputEventReceiver.Factory inputEventReceiverFactory) {
6123 synchronized (mWindowMap) {
6124 return mInputMonitor.createInputConsumer(looper, name, inputEventReceiverFactory);
6129 public void createInputConsumer(String name, InputChannel inputChannel) {
6130 synchronized (mWindowMap) {
6131 mInputMonitor.createInputConsumer(name, inputChannel);
6136 public boolean destroyInputConsumer(String name) {
6137 synchronized (mWindowMap) {
6138 return mInputMonitor.destroyInputConsumer(name);
6143 public boolean hasNavigationBar() {
6144 return mPolicy.hasNavigationBar();
6148 public void lockNow(Bundle options) {
6149 mPolicy.lockNow(options);
6152 public void showRecentApps(boolean fromHome) {
6153 mPolicy.showRecentApps(fromHome);
6157 public boolean isSafeModeEnabled() {
6162 public boolean clearWindowContentFrameStats(IBinder token) {
6163 if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
6164 "clearWindowContentFrameStats()")) {
6165 throw new SecurityException("Requires FRAME_STATS permission");
6167 synchronized (mWindowMap) {
6168 WindowState windowState = mWindowMap.get(token);
6169 if (windowState == null) {
6172 WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
6173 if (surfaceController == null) {
6176 return surfaceController.clearWindowContentFrameStats();
6181 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
6182 if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
6183 "getWindowContentFrameStats()")) {
6184 throw new SecurityException("Requires FRAME_STATS permission");
6186 synchronized (mWindowMap) {
6187 WindowState windowState = mWindowMap.get(token);
6188 if (windowState == null) {
6191 WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
6192 if (surfaceController == null) {
6195 if (mTempWindowRenderStats == null) {
6196 mTempWindowRenderStats = new WindowContentFrameStats();
6198 WindowContentFrameStats stats = mTempWindowRenderStats;
6199 if (!surfaceController.getWindowContentFrameStats(stats)) {
6206 public void notifyAppRelaunching(IBinder token) {
6207 synchronized (mWindowMap) {
6208 final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
6209 if (appWindow != null) {
6210 appWindow.startRelaunching();
6215 public void notifyAppRelaunchingFinished(IBinder token) {
6216 synchronized (mWindowMap) {
6217 final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
6218 if (appWindow != null) {
6219 appWindow.finishRelaunching();
6224 public void notifyAppRelaunchesCleared(IBinder token) {
6225 synchronized (mWindowMap) {
6226 final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
6227 if (appWindow != null) {
6228 appWindow.clearRelaunching();
6233 public void notifyAppResumedFinished(IBinder token) {
6234 synchronized (mWindowMap) {
6235 final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
6236 if (appWindow != null) {
6237 mUnknownAppVisibilityController.notifyAppResumedFinished(appWindow);
6243 * Called when a task has been removed from the recent tasks list.
6245 * Note: This doesn't go through {@link TaskWindowContainerController} yet as the window
6246 * container may not exist when this happens.
6248 public void notifyTaskRemovedFromRecents(int taskId, int userId) {
6249 synchronized (mWindowMap) {
6250 mTaskSnapshotController.notifyTaskRemovedFromRecents(taskId, userId);
6255 public int getDockedDividerInsetsLw() {
6256 return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets();
6259 private void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
6260 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
6261 mPolicy.dump(" ", pw, args);
6264 private void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
6265 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
6266 mAnimator.dumpLocked(pw, " ", dumpAll);
6269 private void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
6270 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
6271 mRoot.dumpTokens(pw, dumpAll);
6272 if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty()) {
6274 if (mOpeningApps.size() > 0) {
6275 pw.print(" mOpeningApps="); pw.println(mOpeningApps);
6277 if (mClosingApps.size() > 0) {
6278 pw.print(" mClosingApps="); pw.println(mClosingApps);
6283 private void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
6284 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
6285 for (int i=0; i<mSessions.size(); i++) {
6286 Session s = mSessions.valueAt(i);
6287 pw.print(" Session "); pw.print(s); pw.println(':');
6292 private void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
6293 ArrayList<WindowState> windows) {
6294 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
6295 dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
6298 private void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
6299 ArrayList<WindowState> windows) {
6300 mRoot.dumpWindowsNoHeader(pw, dumpAll, windows);
6302 if (mPendingRemove.size() > 0) {
6304 pw.println(" Remove pending for:");
6305 for (int i=mPendingRemove.size()-1; i>=0; i--) {
6306 WindowState w = mPendingRemove.get(i);
6307 if (windows == null || windows.contains(w)) {
6308 pw.print(" Remove #"); pw.print(i); pw.print(' ');
6312 w.dump(pw, " ", true);
6319 if (mForceRemoves != null && mForceRemoves.size() > 0) {
6321 pw.println(" Windows force removing:");
6322 for (int i=mForceRemoves.size()-1; i>=0; i--) {
6323 WindowState w = mForceRemoves.get(i);
6324 pw.print(" Removing #"); pw.print(i); pw.print(' ');
6328 w.dump(pw, " ", true);
6334 if (mDestroySurface.size() > 0) {
6336 pw.println(" Windows waiting to destroy their surface:");
6337 for (int i=mDestroySurface.size()-1; i>=0; i--) {
6338 WindowState w = mDestroySurface.get(i);
6339 if (windows == null || windows.contains(w)) {
6340 pw.print(" Destroy #"); pw.print(i); pw.print(' ');
6344 w.dump(pw, " ", true);
6351 if (mLosingFocus.size() > 0) {
6353 pw.println(" Windows losing focus:");
6354 for (int i=mLosingFocus.size()-1; i>=0; i--) {
6355 WindowState w = mLosingFocus.get(i);
6356 if (windows == null || windows.contains(w)) {
6357 pw.print(" Losing #"); pw.print(i); pw.print(' ');
6361 w.dump(pw, " ", true);
6368 if (mResizingWindows.size() > 0) {
6370 pw.println(" Windows waiting to resize:");
6371 for (int i=mResizingWindows.size()-1; i>=0; i--) {
6372 WindowState w = mResizingWindows.get(i);
6373 if (windows == null || windows.contains(w)) {
6374 pw.print(" Resizing #"); pw.print(i); pw.print(' ');
6378 w.dump(pw, " ", true);
6385 if (mWaitingForDrawn.size() > 0) {
6387 pw.println(" Clients waiting for these windows to be drawn:");
6388 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
6389 WindowState win = mWaitingForDrawn.get(i);
6390 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
6394 pw.print(" mGlobalConfiguration="); pw.println(mRoot.getConfiguration());
6395 pw.print(" mHasPermanentDpad="); pw.println(mHasPermanentDpad);
6396 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus);
6397 if (mLastFocus != mCurrentFocus) {
6398 pw.print(" mLastFocus="); pw.println(mLastFocus);
6400 pw.print(" mFocusedApp="); pw.println(mFocusedApp);
6401 if (mInputMethodTarget != null) {
6402 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
6404 pw.print(" mInTouchMode="); pw.print(mInTouchMode);
6405 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
6406 pw.print(" mLastDisplayFreezeDuration=");
6407 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
6408 if ( mLastFinishedFreezeSource != null) {
6409 pw.print(" due to ");
6410 pw.print(mLastFinishedFreezeSource);
6413 pw.print(" mLastWakeLockHoldingWindow=");pw.print(mLastWakeLockHoldingWindow);
6414 pw.print(" mLastWakeLockObscuringWindow="); pw.print(mLastWakeLockObscuringWindow);
6417 mInputMonitor.dump(pw, " ");
6418 mUnknownAppVisibilityController.dump(pw, " ");
6419 mTaskSnapshotController.dump(pw, " ");
6422 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer);
6423 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
6424 if (mLastStatusBarVisibility != 0) {
6425 pw.print(" mLastStatusBarVisibility=0x");
6426 pw.println(Integer.toHexString(mLastStatusBarVisibility));
6428 if (mInputMethodWindow != null) {
6429 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
6431 mWindowPlacerLocked.dump(pw, " ");
6432 mRoot.mWallpaperController.dump(pw, " ");
6433 pw.print(" mSystemBooted="); pw.print(mSystemBooted);
6434 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
6436 mRoot.dumpLayoutNeededDisplayIds(pw);
6438 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence);
6439 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen);
6440 pw.print(" windows="); pw.print(mWindowsFreezingScreen);
6441 pw.print(" client="); pw.print(mClientFreezingScreen);
6442 pw.print(" apps="); pw.print(mAppsFreezingScreen);
6443 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
6444 final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
6445 pw.print(" mRotation="); pw.print(defaultDisplayContent.getRotation());
6446 pw.print(" mAltOrientation=");
6447 pw.println(defaultDisplayContent.getAltOrientation());
6448 pw.print(" mLastWindowForcedOrientation=");
6449 pw.print(defaultDisplayContent.getLastWindowForcedOrientation());
6450 pw.print(" mLastOrientation=");
6451 pw.println(defaultDisplayContent.getLastOrientation());
6452 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
6453 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled);
6454 pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
6455 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
6456 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting);
6457 pw.print(" mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation);
6458 pw.println(" mLayoutToAnim:");
6459 mAppTransition.dump(pw, " ");
6463 private boolean dumpWindows(PrintWriter pw, String name, String[] args, int opti,
6465 final ArrayList<WindowState> windows = new ArrayList();
6466 if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
6467 final boolean appsOnly = name.contains("apps");
6468 final boolean visibleOnly = name.contains("visible");
6469 synchronized(mWindowMap) {
6471 mRoot.dumpDisplayContents(pw);
6474 mRoot.forAllWindows((w) -> {
6475 if ((!visibleOnly || w.mWinAnimator.getShown())
6476 && (!appsOnly || w.mAppToken != null)) {
6479 }, true /* traverseTopToBottom */);
6482 synchronized(mWindowMap) {
6483 mRoot.getWindowsByName(windows, name);
6487 if (windows.size() <= 0) {
6491 synchronized(mWindowMap) {
6492 dumpWindowsLocked(pw, dumpAll, windows);
6497 private void dumpLastANRLocked(PrintWriter pw) {
6498 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
6499 if (mLastANRState == null) {
6500 pw.println(" <no ANR has occurred since boot>");
6502 pw.println(mLastANRState);
6507 * Saves information about the state of the window manager at
6508 * the time an ANR occurred before anything else in the system changes
6511 * @param appWindowToken The application that ANR'd, may be null.
6512 * @param windowState The window that ANR'd, may be null.
6513 * @param reason The reason for the ANR, may be null.
6515 void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, String reason) {
6516 StringWriter sw = new StringWriter();
6517 PrintWriter pw = new FastPrintWriter(sw, false, 1024);
6518 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date()));
6519 if (appWindowToken != null) {
6520 pw.println(" Application at fault: " + appWindowToken.stringName);
6522 if (windowState != null) {
6523 pw.println(" Window at fault: " + windowState.mAttrs.getTitle());
6525 if (reason != null) {
6526 pw.println(" Reason: " + reason);
6529 dumpWindowsNoHeaderLocked(pw, true, null);
6531 pw.println("Last ANR continued");
6532 mRoot.dumpDisplayContents(pw);
6534 mLastANRState = sw.toString();
6536 mH.removeMessages(H.RESET_ANR_MESSAGE);
6537 mH.sendEmptyMessageDelayed(H.RESET_ANR_MESSAGE, LAST_ANR_LIFETIME_DURATION_MSECS);
6541 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
6542 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
6544 boolean dumpAll = false;
6547 while (opti < args.length) {
6548 String opt = args[opti];
6549 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6553 if ("-a".equals(opt)) {
6555 } else if ("-h".equals(opt)) {
6556 pw.println("Window manager dump options:");
6557 pw.println(" [-a] [-h] [cmd] ...");
6558 pw.println(" cmd may be one of:");
6559 pw.println(" l[astanr]: last ANR information");
6560 pw.println(" p[policy]: policy state");
6561 pw.println(" a[animator]: animator state");
6562 pw.println(" s[essions]: active sessions");
6563 pw.println(" surfaces: active surfaces (debugging enabled only)");
6564 pw.println(" d[isplays]: active display contents");
6565 pw.println(" t[okens]: token list");
6566 pw.println(" w[indows]: window list");
6567 pw.println(" cmd may also be a NAME to dump windows. NAME may");
6568 pw.println(" be a partial substring in a window name, a");
6569 pw.println(" Window hex object identifier, or");
6570 pw.println(" \"all\" for all windows, or");
6571 pw.println(" \"visible\" for the visible windows.");
6572 pw.println(" \"visible-apps\" for the visible app windows.");
6573 pw.println(" -a: include all available server state.");
6576 pw.println("Unknown argument: " + opt + "; use -h for help");
6580 // Is the caller requesting to dump a particular piece of data?
6581 if (opti < args.length) {
6582 String cmd = args[opti];
6584 if ("lastanr".equals(cmd) || "l".equals(cmd)) {
6585 synchronized(mWindowMap) {
6586 dumpLastANRLocked(pw);
6589 } else if ("policy".equals(cmd) || "p".equals(cmd)) {
6590 synchronized(mWindowMap) {
6591 dumpPolicyLocked(pw, args, true);
6594 } else if ("animator".equals(cmd) || "a".equals(cmd)) {
6595 synchronized(mWindowMap) {
6596 dumpAnimatorLocked(pw, args, true);
6599 } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
6600 synchronized(mWindowMap) {
6601 dumpSessionsLocked(pw, true);
6604 } else if ("surfaces".equals(cmd)) {
6605 synchronized(mWindowMap) {
6606 WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, null);
6609 } else if ("displays".equals(cmd) || "d".equals(cmd)) {
6610 synchronized(mWindowMap) {
6611 mRoot.dumpDisplayContents(pw);
6614 } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
6615 synchronized(mWindowMap) {
6616 dumpTokensLocked(pw, true);
6619 } else if ("windows".equals(cmd) || "w".equals(cmd)) {
6620 synchronized(mWindowMap) {
6621 dumpWindowsLocked(pw, true, null);
6624 } else if ("all".equals(cmd) || "a".equals(cmd)) {
6625 synchronized(mWindowMap) {
6626 dumpWindowsLocked(pw, true, null);
6629 } else if ("containers".equals(cmd)) {
6630 synchronized(mWindowMap) {
6631 StringBuilder output = new StringBuilder();
6632 mRoot.dumpChildrenNames(output, " ");
6633 pw.println(output.toString());
6635 mRoot.forAllWindows(w -> {pw.println(w);}, true /* traverseTopToBottom */);
6639 // Dumping a single name?
6640 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
6641 pw.println("Bad window command, or no windows match: " + cmd);
6642 pw.println("Use -h for help.");
6648 synchronized(mWindowMap) {
6651 pw.println("-------------------------------------------------------------------------------");
6653 dumpLastANRLocked(pw);
6656 pw.println("-------------------------------------------------------------------------------");
6658 dumpPolicyLocked(pw, args, dumpAll);
6661 pw.println("-------------------------------------------------------------------------------");
6663 dumpAnimatorLocked(pw, args, dumpAll);
6666 pw.println("-------------------------------------------------------------------------------");
6668 dumpSessionsLocked(pw, dumpAll);
6671 pw.println("-------------------------------------------------------------------------------");
6673 WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ?
6674 "-------------------------------------------------------------------------------"
6678 pw.println("-------------------------------------------------------------------------------");
6680 mRoot.dumpDisplayContents(pw);
6683 pw.println("-------------------------------------------------------------------------------");
6685 dumpTokensLocked(pw, dumpAll);
6688 pw.println("-------------------------------------------------------------------------------");
6690 dumpWindowsLocked(pw, dumpAll, null);
6694 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
6696 public void monitor() {
6697 synchronized (mWindowMap) { }
6700 // TODO: All the display method below should probably be moved into the RootWindowContainer...
6701 private void createDisplayContentLocked(final Display display) {
6702 if (display == null) {
6703 throw new IllegalArgumentException("getDisplayContent: display must not be null");
6705 mRoot.getDisplayContentOrCreate(display.getDisplayId());
6708 // There is an inherent assumption that this will never return null.
6709 // TODO(multi-display): Inspect all the call-points of this method to see if they make sense to
6710 // support non-default display.
6711 DisplayContent getDefaultDisplayContentLocked() {
6712 return mRoot.getDisplayContentOrCreate(DEFAULT_DISPLAY);
6715 public void onDisplayAdded(int displayId) {
6716 synchronized (mWindowMap) {
6717 final Display display = mDisplayManager.getDisplay(displayId);
6718 if (display != null) {
6719 createDisplayContentLocked(display);
6720 displayReady(displayId);
6722 mWindowPlacerLocked.requestTraversal();
6726 public void onDisplayRemoved(int displayId) {
6727 synchronized (mWindowMap) {
6728 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
6729 if (displayContent != null) {
6730 displayContent.removeIfPossible();
6732 mAnimator.removeDisplayLocked(displayId);
6733 mWindowPlacerLocked.requestTraversal();
6737 public void onDisplayChanged(int displayId) {
6738 synchronized (mWindowMap) {
6739 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
6740 if (displayContent != null) {
6741 displayContent.updateDisplayInfo();
6743 mWindowPlacerLocked.requestTraversal();
6748 public Object getWindowManagerLock() {
6753 * Hint to a token that its activity will relaunch, which will trigger removal and addition of
6755 * @param token Application token for which the activity will be relaunched.
6757 public void setWillReplaceWindow(IBinder token, boolean animate) {
6758 synchronized (mWindowMap) {
6759 final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
6760 if (appWindowToken == null || !appWindowToken.hasContentToDisplay()) {
6761 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
6765 appWindowToken.setWillReplaceWindows(animate);
6770 * Hint to a token that its windows will be replaced across activity relaunch.
6771 * The windows would otherwise be removed shortly following this as the
6772 * activity is torn down.
6773 * @param token Application token for which the activity will be relaunched.
6774 * @param childrenOnly Whether to mark only child windows for replacement
6775 * (for the case where main windows are being preserved/
6776 * reused rather than replaced).
6779 // TODO: The s at the end of the method name is the only difference with the name of the method
6780 // above. We should combine them or find better names.
6781 void setWillReplaceWindows(IBinder token, boolean childrenOnly) {
6782 synchronized (mWindowMap) {
6783 final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
6784 if (appWindowToken == null || !appWindowToken.hasContentToDisplay()) {
6785 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
6791 appWindowToken.setWillReplaceChildWindows();
6793 appWindowToken.setWillReplaceWindows(false /* animate */);
6796 scheduleClearWillReplaceWindows(token, true /* replacing */);
6801 * If we're replacing the window, schedule a timer to clear the replaced window
6802 * after a timeout, in case the replacing window is not coming.
6804 * If we're not replacing the window, clear the replace window settings of the app.
6806 * @param token Application token for the activity whose window might be replaced.
6807 * @param replacing Whether the window is being replaced or not.
6809 public void scheduleClearWillReplaceWindows(IBinder token, boolean replacing) {
6810 synchronized (mWindowMap) {
6811 final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
6812 if (appWindowToken == null) {
6813 Slog.w(TAG_WM, "Attempted to reset replacing window on non-existing app token "
6818 scheduleWindowReplacementTimeouts(appWindowToken);
6820 appWindowToken.clearWillReplaceWindows();
6825 void scheduleWindowReplacementTimeouts(AppWindowToken appWindowToken) {
6826 if (!mWindowReplacementTimeouts.contains(appWindowToken)) {
6827 mWindowReplacementTimeouts.add(appWindowToken);
6829 mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
6830 mH.sendEmptyMessageDelayed(
6831 H.WINDOW_REPLACEMENT_TIMEOUT, WINDOW_REPLACEMENT_TIMEOUT_DURATION);
6835 public int getDockedStackSide() {
6836 synchronized (mWindowMap) {
6837 final TaskStack dockedStack = getDefaultDisplayContentLocked()
6838 .getDockedStackIgnoringVisibility();
6839 return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide();
6844 public void setDockedStackResizing(boolean resizing) {
6845 synchronized (mWindowMap) {
6846 getDefaultDisplayContentLocked().getDockedDividerController().setResizing(resizing);
6852 public void setDockedStackDividerTouchRegion(Rect touchRegion) {
6853 synchronized (mWindowMap) {
6854 getDefaultDisplayContentLocked().getDockedDividerController()
6855 .setTouchRegion(touchRegion);
6856 setFocusTaskRegionLocked(null);
6861 public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
6862 synchronized (mWindowMap) {
6863 getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer(
6864 visible, targetStackId, alpha);
6868 public void setForceResizableTasks(boolean forceResizableTasks) {
6869 synchronized (mWindowMap) {
6870 mForceResizableTasks = forceResizableTasks;
6874 public void setSupportsPictureInPicture(boolean supportsPictureInPicture) {
6875 synchronized (mWindowMap) {
6876 mSupportsPictureInPicture = supportsPictureInPicture;
6880 static int dipToPixel(int dip, DisplayMetrics displayMetrics) {
6881 return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics);
6885 public void registerDockedStackListener(IDockedStackListener listener) {
6886 if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS,
6887 "registerDockedStackListener()")) {
6890 // TODO(multi-display): The listener is registered on the default display only.
6891 getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener(
6896 public void registerPinnedStackListener(int displayId, IPinnedStackListener listener) {
6897 if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS,
6898 "registerPinnedStackListener()")) {
6901 if (!mSupportsPictureInPicture) {
6904 synchronized (mWindowMap) {
6905 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
6906 displayContent.getPinnedStackController().registerPinnedStackListener(listener);
6911 public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
6913 WindowState focusedWindow = getFocusedWindow();
6914 if (focusedWindow != null && focusedWindow.mClient != null) {
6915 getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId);
6917 } catch (RemoteException e) {
6922 public void getStableInsets(int displayId, Rect outInsets) throws RemoteException {
6923 synchronized (mWindowMap) {
6924 getStableInsetsLocked(displayId, outInsets);
6928 void getStableInsetsLocked(int displayId, Rect outInsets) {
6929 outInsets.setEmpty();
6930 final DisplayContent dc = mRoot.getDisplayContent(displayId);
6932 final DisplayInfo di = dc.getDisplayInfo();
6933 mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
6937 void intersectDisplayInsetBounds(Rect display, Rect insets, Rect inOutBounds) {
6938 mTmpRect3.set(display);
6939 mTmpRect3.inset(insets);
6940 inOutBounds.intersect(mTmpRect3);
6943 MousePositionTracker mMousePositionTracker = new MousePositionTracker();
6945 private static class MousePositionTracker implements PointerEventListener {
6946 private boolean mLatestEventWasMouse;
6947 private float mLatestMouseX;
6948 private float mLatestMouseY;
6950 void updatePosition(float x, float y) {
6951 synchronized (this) {
6952 mLatestEventWasMouse = true;
6959 public void onPointerEvent(MotionEvent motionEvent) {
6960 if (motionEvent.isFromSource(InputDevice.SOURCE_MOUSE)) {
6961 updatePosition(motionEvent.getRawX(), motionEvent.getRawY());
6963 synchronized (this) {
6964 mLatestEventWasMouse = false;
6970 void updatePointerIcon(IWindow client) {
6971 float mouseX, mouseY;
6973 synchronized(mMousePositionTracker) {
6974 if (!mMousePositionTracker.mLatestEventWasMouse) {
6977 mouseX = mMousePositionTracker.mLatestMouseX;
6978 mouseY = mMousePositionTracker.mLatestMouseY;
6981 synchronized (mWindowMap) {
6982 if (mDragState != null) {
6983 // Drag cursor overrides the app cursor.
6986 WindowState callingWin = windowForClientLocked(null, client, false);
6987 if (callingWin == null) {
6988 Slog.w(TAG_WM, "Bad requesting window " + client);
6991 final DisplayContent displayContent = callingWin.getDisplayContent();
6992 if (displayContent == null) {
6995 WindowState windowUnderPointer =
6996 displayContent.getTouchableWinAtPointLocked(mouseX, mouseY);
6997 if (windowUnderPointer != callingWin) {
7001 windowUnderPointer.mClient.updatePointerIcon(
7002 windowUnderPointer.translateToWindowX(mouseX),
7003 windowUnderPointer.translateToWindowY(mouseY));
7004 } catch (RemoteException e) {
7005 Slog.w(TAG_WM, "unable to update pointer icon");
7010 void restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY) {
7011 // Mouse position tracker has not been getting updates while dragging, update it now.
7012 mMousePositionTracker.updatePosition(latestX, latestY);
7014 WindowState windowUnderPointer =
7015 displayContent.getTouchableWinAtPointLocked(latestX, latestY);
7016 if (windowUnderPointer != null) {
7018 windowUnderPointer.mClient.updatePointerIcon(
7019 windowUnderPointer.translateToWindowX(latestX),
7020 windowUnderPointer.translateToWindowY(latestY));
7021 } catch (RemoteException e) {
7022 Slog.w(TAG_WM, "unable to restore pointer icon");
7025 InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_DEFAULT);
7030 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
7031 throws RemoteException {
7032 if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS, "registerShortcutKey")) {
7033 throw new SecurityException(
7034 "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission");
7036 mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver);
7039 void markForSeamlessRotation(WindowState w, boolean seamlesslyRotated) {
7040 if (seamlesslyRotated == w.mSeamlesslyRotated) {
7043 w.mSeamlesslyRotated = seamlesslyRotated;
7044 if (seamlesslyRotated) {
7045 mSeamlessRotationCount++;
7047 mSeamlessRotationCount--;
7049 if (mSeamlessRotationCount == 0) {
7050 if (DEBUG_ORIENTATION) {
7051 Slog.i(TAG, "Performing post-rotate rotation after seamless rotation");
7053 final DisplayContent displayContent = w.getDisplayContent();
7054 if (displayContent.updateRotationUnchecked(false /* inTransaction */)) {
7055 mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
7061 private final class LocalService extends WindowManagerInternal {
7063 public void requestTraversalFromDisplayManager() {
7068 public void setMagnificationSpec(MagnificationSpec spec) {
7069 synchronized (mWindowMap) {
7070 if (mAccessibilityController != null) {
7071 mAccessibilityController.setMagnificationSpecLocked(spec);
7073 throw new IllegalStateException("Magnification callbacks not set!");
7076 if (Binder.getCallingPid() != myPid()) {
7082 public void setForceShowMagnifiableBounds(boolean show) {
7083 synchronized (mWindowMap) {
7084 if (mAccessibilityController != null) {
7085 mAccessibilityController.setForceShowMagnifiableBoundsLocked(show);
7087 throw new IllegalStateException("Magnification callbacks not set!");
7093 public void getMagnificationRegion(@NonNull Region magnificationRegion) {
7094 synchronized (mWindowMap) {
7095 if (mAccessibilityController != null) {
7096 mAccessibilityController.getMagnificationRegionLocked(magnificationRegion);
7098 throw new IllegalStateException("Magnification callbacks not set!");
7104 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
7105 synchronized (mWindowMap) {
7106 WindowState windowState = mWindowMap.get(windowToken);
7107 if (windowState == null) {
7110 MagnificationSpec spec = null;
7111 if (mAccessibilityController != null) {
7112 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState);
7114 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
7117 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
7118 spec.scale *= windowState.mGlobalScale;
7124 public void setMagnificationCallbacks(@Nullable MagnificationCallbacks callbacks) {
7125 synchronized (mWindowMap) {
7126 if (mAccessibilityController == null) {
7127 mAccessibilityController = new AccessibilityController(
7128 WindowManagerService.this);
7130 mAccessibilityController.setMagnificationCallbacksLocked(callbacks);
7131 if (!mAccessibilityController.hasCallbacksLocked()) {
7132 mAccessibilityController = null;
7138 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) {
7139 synchronized (mWindowMap) {
7140 if (mAccessibilityController == null) {
7141 mAccessibilityController = new AccessibilityController(
7142 WindowManagerService.this);
7144 mAccessibilityController.setWindowsForAccessibilityCallback(callback);
7145 if (!mAccessibilityController.hasCallbacksLocked()) {
7146 mAccessibilityController = null;
7152 public void setInputFilter(IInputFilter filter) {
7153 mInputManager.setInputFilter(filter);
7157 public IBinder getFocusedWindowToken() {
7158 synchronized (mWindowMap) {
7159 WindowState windowState = getFocusedWindowLocked();
7160 if (windowState != null) {
7161 return windowState.mClient.asBinder();
7168 public boolean isKeyguardLocked() {
7169 return WindowManagerService.this.isKeyguardLocked();
7173 public void showGlobalActions() {
7174 WindowManagerService.this.showGlobalActions();
7178 public void getWindowFrame(IBinder token, Rect outBounds) {
7179 synchronized (mWindowMap) {
7180 WindowState windowState = mWindowMap.get(token);
7181 if (windowState != null) {
7182 outBounds.set(windowState.mFrame);
7184 outBounds.setEmpty();
7190 public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
7191 boolean allWindowsDrawn = false;
7192 synchronized (mWindowMap) {
7193 mWaitingForDrawnCallback = callback;
7194 getDefaultDisplayContentLocked().waitForAllWindowsDrawn();
7195 mWindowPlacerLocked.requestTraversal();
7196 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
7197 if (mWaitingForDrawn.isEmpty()) {
7198 allWindowsDrawn = true;
7200 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
7201 checkDrawnWindowsLocked();
7204 if (allWindowsDrawn) {
7210 public void addWindowToken(IBinder token, int type, int displayId) {
7211 WindowManagerService.this.addWindowToken(token, type, displayId);
7215 public void removeWindowToken(IBinder binder, boolean removeWindows, int displayId) {
7216 synchronized(mWindowMap) {
7217 if (removeWindows) {
7218 final DisplayContent dc = mRoot.getDisplayContent(displayId);
7220 Slog.w(TAG_WM, "removeWindowToken: Attempted to remove token: " + binder
7221 + " for non-exiting displayId=" + displayId);
7225 final WindowToken token = dc.removeWindowToken(binder);
7226 if (token == null) {
7227 Slog.w(TAG_WM, "removeWindowToken: Attempted to remove non-existing token: "
7232 token.removeAllWindowsIfPossible();
7234 WindowManagerService.this.removeWindowToken(binder, displayId);
7239 public void registerAppTransitionListener(AppTransitionListener listener) {
7240 synchronized (mWindowMap) {
7241 mAppTransition.registerListenerLocked(listener);
7246 public int getInputMethodWindowVisibleHeight() {
7247 synchronized (mWindowMap) {
7248 return mPolicy.getInputMethodWindowVisibleHeightLw();
7253 public void saveLastInputMethodWindowForTransition() {
7254 synchronized (mWindowMap) {
7255 if (mInputMethodWindow != null) {
7256 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
7262 public void clearLastInputMethodWindowForTransition() {
7263 synchronized (mWindowMap) {
7264 mPolicy.setLastInputMethodWindowLw(null, null);
7269 public void updateInputMethodWindowStatus(@NonNull IBinder imeToken,
7270 boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed,
7271 @Nullable IBinder targetWindowToken) {
7272 // TODO (b/34628091): Use this method to address the window animation issue.
7273 if (DEBUG_INPUT_METHOD) {
7274 Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken=" + imeToken
7275 + " dismissImeOnBackKeyPressed=" + dismissImeOnBackKeyPressed
7276 + " imeWindowVisible=" + imeWindowVisible
7277 + " targetWindowToken=" + targetWindowToken);
7279 mPolicy.setDismissImeOnBackKeyPressed(dismissImeOnBackKeyPressed);
7283 public boolean isHardKeyboardAvailable() {
7284 synchronized (mWindowMap) {
7285 return mHardKeyboardAvailable;
7290 public void setOnHardKeyboardStatusChangeListener(
7291 OnHardKeyboardStatusChangeListener listener) {
7292 synchronized (mWindowMap) {
7293 mHardKeyboardStatusChangeListener = listener;
7298 public boolean isStackVisible(int stackId) {
7299 synchronized (mWindowMap) {
7300 final DisplayContent dc = getDefaultDisplayContentLocked();
7301 return dc.isStackVisible(stackId);
7306 public boolean isDockedDividerResizing() {
7307 synchronized (mWindowMap) {
7308 return getDefaultDisplayContentLocked().getDockedDividerController().isResizing();
7313 public void computeWindowsForAccessibility() {
7314 final AccessibilityController accessibilityController;
7315 synchronized (mWindowMap) {
7316 accessibilityController = mAccessibilityController;
7318 if (accessibilityController != null) {
7319 accessibilityController.performComputeChangedWindowsNotLocked();
7324 void registerAppFreezeListener(AppFreezeListener listener) {
7325 if (!mAppFreezeListeners.contains(listener)) {
7326 mAppFreezeListeners.add(listener);
7330 void unregisterAppFreezeListener(AppFreezeListener listener) {
7331 mAppFreezeListeners.remove(listener);
7335 * WARNING: This interrupts surface updates, be careful! Don't
7336 * execute within the transaction for longer than you would
7337 * execute on an animation thread.
7338 * WARNING: This holds the WindowManager lock, so if exec will acquire
7339 * the ActivityManager lock, you should hold it BEFORE calling this
7340 * otherwise there is a risk of deadlock if another thread holding the AM
7341 * lock waits on the WM lock.
7342 * WARNING: This method contains locks known to the State of California
7343 * to cause Deadlocks and other conditions.
7345 * Begins a surface transaction with which the AM can batch operations.
7346 * All Surface updates performed by the WindowManager following this
7347 * will not appear on screen until after the call to
7348 * closeSurfaceTransaction.
7350 * ActivityManager can use this to ensure multiple 'commands' will all
7351 * be reflected in a single frame. For example when reparenting a window
7352 * which was previously hidden due to it's parent properties, we may
7353 * need to ensure it is hidden in the same frame that the properties
7354 * from the new parent are inherited, otherwise it could be revealed
7357 * TODO(b/36393204): We can investigate totally replacing #deferSurfaceLayout
7358 * with something like this but it seems that some existing cases of
7359 * deferSurfaceLayout may be a little too broad, in particular the total
7360 * enclosure of startActivityUnchecked which could run for quite some time.
7362 public void inSurfaceTransaction(Runnable exec) {
7363 // We hold the WindowManger lock to ensure relayoutWindow
7364 // does not return while a Surface transaction is opening.
7365 // The client depends on us to have resized the surface
7366 // by that point (b/36462635)
7368 synchronized (mWindowMap) {
7369 SurfaceControl.openTransaction();
7373 SurfaceControl.closeTransaction();
7378 /** Called to inform window manager if non-Vr UI shoul be disabled or not. */
7379 public void disableNonVrUi(boolean disable) {
7380 synchronized (mWindowMap) {
7381 // Allow alert window notifications to be shown if non-vr UI is enabled.
7382 final boolean showAlertWindowNotifications = !disable;
7383 if (showAlertWindowNotifications == mShowAlertWindowNotifications) {
7386 mShowAlertWindowNotifications = showAlertWindowNotifications;
7388 for (int i = mSessions.size() - 1; i >= 0; --i) {
7389 final Session s = mSessions.valueAt(i);
7390 s.setShowingAlertWindowNotificationAllowed(mShowAlertWindowNotifications);