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 android.Manifest;
20 import android.animation.ValueAnimator;
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.app.ActivityManagerInternal;
25 import android.app.ActivityManagerNative;
26 import android.app.AppOpsManager;
27 import android.app.IActivityManager;
28 import android.app.Notification;
29 import android.app.NotificationManager;
30 import android.app.PendingIntent;
31 import android.app.admin.DevicePolicyManager;
32 import android.content.BroadcastReceiver;
33 import android.content.ContentResolver;
34 import android.content.Context;
35 import android.content.Intent;
36 import android.content.IntentFilter;
37 import android.content.pm.ActivityInfo;
38 import android.content.pm.PackageManager;
39 import android.content.res.CompatibilityInfo;
40 import android.content.res.Configuration;
41 import android.database.ContentObserver;
42 import android.graphics.Bitmap;
43 import android.graphics.PixelFormat;
44 import android.graphics.Matrix;
45 import android.graphics.Point;
46 import android.graphics.Rect;
47 import android.graphics.RectF;
48 import android.graphics.Region;
49 import android.hardware.display.DisplayManager;
50 import android.hardware.display.DisplayManagerInternal;
51 import android.hardware.input.InputManager;
52 import android.net.Uri;
53 import android.os.Binder;
54 import android.os.Build;
55 import android.os.Bundle;
56 import android.os.Debug;
57 import android.os.Handler;
58 import android.os.IBinder;
59 import android.os.IRemoteCallback;
60 import android.os.Looper;
61 import android.os.Message;
62 import android.os.Parcel;
63 import android.os.ParcelFileDescriptor;
64 import android.os.PowerManager;
65 import android.os.PowerManagerInternal;
66 import android.os.Process;
67 import android.os.RemoteException;
68 import android.os.ServiceManager;
69 import android.os.StrictMode;
70 import android.os.SystemClock;
71 import android.os.SystemProperties;
72 import android.os.SystemService;
73 import android.os.Trace;
74 import android.os.UserHandle;
75 import android.os.WorkSource;
76 import android.provider.Settings;
77 import android.util.ArraySet;
78 import android.util.DisplayMetrics;
79 import android.util.EventLog;
80 import android.util.Log;
81 import android.util.Pair;
82 import android.util.Slog;
83 import android.util.SparseArray;
84 import android.util.SparseIntArray;
85 import android.util.TimeUtils;
86 import android.util.TypedValue;
87 import android.view.AppTransitionAnimationSpec;
88 import android.view.Choreographer;
89 import android.view.Display;
90 import android.view.DisplayInfo;
91 import android.view.Gravity;
92 import android.view.PointerIcon;
93 import android.view.IAppTransitionAnimationSpecsFuture;
94 import android.view.IApplicationToken;
95 import android.view.IDockedStackListener;
96 import android.view.IInputFilter;
97 import android.view.IOnKeyguardExitResult;
98 import android.view.IRotationWatcher;
99 import android.view.IWindow;
100 import android.view.IWindowId;
101 import android.view.IWindowManager;
102 import android.view.IWindowSession;
103 import android.view.IWindowSessionCallback;
104 import android.view.InputChannel;
105 import android.view.InputDevice;
106 import android.view.InputEvent;
107 import android.view.InputEventReceiver;
108 import android.view.KeyEvent;
109 import android.view.MagnificationSpec;
110 import android.view.MotionEvent;
111 import android.view.Surface;
112 import android.view.Surface.OutOfResourcesException;
113 import android.view.SurfaceControl;
114 import android.view.SurfaceSession;
115 import android.view.View;
116 import android.view.WindowContentFrameStats;
117 import android.view.WindowManager;
118 import android.view.WindowManager.LayoutParams;
119 import android.view.WindowManagerGlobal;
120 import android.view.WindowManagerInternal;
121 import android.view.WindowManagerPolicy;
122 import android.view.WindowManagerPolicy.PointerEventListener;
123 import android.view.animation.Animation;
124 import android.view.inputmethod.InputMethodManagerInternal;
126 import com.android.internal.R;
127 import com.android.internal.app.IAssistScreenshotReceiver;
128 import com.android.internal.os.IResultReceiver;
129 import com.android.internal.policy.IShortcutService;
130 import com.android.internal.util.ArrayUtils;
131 import com.android.internal.util.FastPrintWriter;
132 import com.android.internal.view.IInputContext;
133 import com.android.internal.view.IInputMethodClient;
134 import com.android.internal.view.IInputMethodManager;
135 import com.android.internal.view.WindowManagerPolicyThread;
136 import com.android.server.AttributeCache;
137 import com.android.server.DisplayThread;
138 import com.android.server.EventLogTags;
139 import com.android.server.FgThread;
140 import com.android.server.LocalServices;
141 import com.android.server.UiThread;
142 import com.android.server.Watchdog;
143 import com.android.server.input.InputManagerService;
144 import com.android.server.policy.PhoneWindowManager;
145 import com.android.server.power.ShutdownThread;
147 import java.io.BufferedWriter;
148 import java.io.DataInputStream;
150 import java.io.FileDescriptor;
151 import java.io.FileInputStream;
152 import java.io.FileNotFoundException;
153 import java.io.IOException;
154 import java.io.OutputStream;
155 import java.io.OutputStreamWriter;
156 import java.io.PrintWriter;
157 import java.io.StringWriter;
158 import java.lang.annotation.Retention;
159 import java.lang.annotation.RetentionPolicy;
160 import java.net.Socket;
161 import java.text.DateFormat;
162 import java.util.ArrayList;
163 import java.util.Arrays;
164 import java.util.Date;
165 import java.util.HashMap;
166 import java.util.Iterator;
167 import java.util.List;
169 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
170 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
171 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
172 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
173 import static android.app.StatusBarManager.DISABLE_MASK;
174 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
175 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
176 import static android.view.WindowManager.DOCKED_BOTTOM;
177 import static android.view.WindowManager.DOCKED_INVALID;
178 import static android.view.WindowManager.DOCKED_TOP;
179 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
180 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
181 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
182 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
183 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
184 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
185 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
186 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
187 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
188 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
189 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
190 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
191 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
192 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
193 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
194 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
195 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
196 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
197 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
198 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
199 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
200 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
201 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
202 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
203 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
204 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
205 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
206 import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
207 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
208 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
209 import static android.view.WindowManagerPolicy.TRANSIT_EXIT;
210 import static android.view.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
211 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END;
212 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
213 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
214 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
215 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
216 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
217 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
218 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_ORIENTATION;
219 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
220 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
221 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
222 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
223 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
224 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
225 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
226 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
227 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD;
228 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
229 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
230 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
231 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
232 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
233 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
234 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
235 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
236 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
237 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
238 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
239 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
240 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
241 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
242 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
243 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
244 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
245 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
246 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
247 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSACTIONS;
248 import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
249 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
250 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
251 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
254 public class WindowManagerService extends IWindowManager.Stub
255 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
256 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowManagerService" : TAG_WM;
258 static final int LAYOUT_REPEAT_THRESHOLD = 4;
260 static final boolean PROFILE_ORIENTATION = false;
261 static final boolean localLOGV = DEBUG;
263 /** How much to multiply the policy's type layer, to reserve room
264 * for multiple windows of the same type and Z-ordering adjustment
265 * with TYPE_LAYER_OFFSET. */
266 static final int TYPE_LAYER_MULTIPLIER = 10000;
268 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
269 * or below others in the same layer. */
270 static final int TYPE_LAYER_OFFSET = 1000;
272 /** How much to increment the layer for each window, to reserve room
273 * for effect surfaces between them.
275 static final int WINDOW_LAYER_MULTIPLIER = 5;
278 * Dim surface layer is immediately below target window.
280 static final int LAYER_OFFSET_DIM = 1;
283 * Animation thumbnail is as far as possible below the window above
284 * the thumbnail (or in other words as far as possible above the window
287 static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER - 1;
289 /** The maximum length we will accept for a loaded animation duration:
290 * this is 10 seconds.
292 static final int MAX_ANIMATION_DURATION = 10 * 1000;
294 /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
295 static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
297 /** Amount of time (in milliseconds) to delay before declaring a seamless rotation timeout. */
298 static final int SEAMLESS_ROTATION_TIMEOUT_DURATION = 2000;
300 /** Amount of time (in milliseconds) to delay before declaring a window replacement timeout. */
301 static final int WINDOW_REPLACEMENT_TIMEOUT_DURATION = 2000;
303 /** Amount of time to allow a last ANR message to exist before freeing the memory. */
304 static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours
306 * If true, the window manager will do its own custom freezing and general
307 * management of the screen during rotation.
309 static final boolean CUSTOM_SCREEN_ROTATION = true;
311 // Maximum number of milliseconds to wait for input devices to be enumerated before
312 // proceding with safe mode detection.
313 private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
315 // Default input dispatching timeout in nanoseconds.
316 static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
318 // Poll interval in milliseconds for watching boot animation finished.
319 private static final int BOOT_ANIMATION_POLL_INTERVAL = 200;
321 // The name of the boot animation service in init.rc.
322 private static final String BOOT_ANIMATION_SERVICE = "bootanim";
324 static final int UPDATE_FOCUS_NORMAL = 0;
325 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
326 static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
327 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
329 private static final String SYSTEM_SECURE = "ro.secure";
330 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
332 private static final String DENSITY_OVERRIDE = "ro.config.density_override";
333 private static final String SIZE_OVERRIDE = "ro.config.size_override";
335 private static final int MAX_SCREENSHOT_RETRIES = 3;
337 private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
339 // Used to indicate that if there is already a transition set, it should be preserved when
340 // trying to apply a new one.
341 private static final boolean ALWAYS_KEEP_CURRENT = true;
343 private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f;
345 private static final String PROPERTY_BUILD_DATE_UTC = "ro.build.date.utc";
347 // Enums for animation scale update types.
348 @Retention(RetentionPolicy.SOURCE)
349 @IntDef({WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE, ANIMATION_DURATION_SCALE})
350 private @interface UpdateAnimationScaleMode {};
351 private static final int WINDOW_ANIMATION_SCALE = 0;
352 private static final int TRANSITION_ANIMATION_SCALE = 1;
353 private static final int ANIMATION_DURATION_SCALE = 2;
355 final private KeyguardDisableHandler mKeyguardDisableHandler;
357 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
359 public void onReceive(Context context, Intent intent) {
360 final String action = intent.getAction();
361 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
362 mKeyguardDisableHandler.sendEmptyMessage(
363 KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED);
367 final WindowSurfacePlacer mWindowPlacerLocked;
370 * Current user when multi-user is enabled. Don't show windows of
371 * non-current user. Also see mCurrentProfileIds.
375 * Users that are profiles of the current user. These are also allowed to show windows
376 * on the current user.
378 int[] mCurrentProfileIds = new int[] {};
380 final Context mContext;
382 final boolean mHaveInputMethods;
384 final boolean mHasPermanentDpad;
385 final long mDrawLockTimeoutMillis;
386 final boolean mAllowAnimationsInLowPowerMode;
388 final boolean mAllowBootMessages;
390 final boolean mLimitedAlphaCompositing;
392 final WindowManagerPolicy mPolicy = new PhoneWindowManager();
394 final IActivityManager mActivityManager;
395 final ActivityManagerInternal mAmInternal;
397 final AppOpsManager mAppOps;
399 final DisplaySettings mDisplaySettings;
402 * All currently active sessions with clients.
404 final ArraySet<Session> mSessions = new ArraySet<>();
407 * Mapping from an IWindow IBinder to the server's Window object.
408 * This is also used as the lock for all of our state.
409 * NOTE: Never call into methods that lock ActivityManagerService while holding this object.
411 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>();
414 * Mapping from a token IBinder to a WindowToken object.
416 final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<>();
419 * List of window tokens that have finished starting their application,
420 * and now need to have the policy remove their windows.
422 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<>();
425 * List of window tokens that have finished drawing their own windows and
426 * no longer need to show any saved surfaces. Windows that's still showing
427 * saved surfaces will be cleaned up after next animation pass.
429 final ArrayList<AppWindowToken> mFinishedEarlyAnim = new ArrayList<>();
432 * List of app window tokens that are waiting for replacing windows. If the
433 * replacement doesn't come in time the stale windows needs to be disposed of.
435 final ArrayList<AppWindowToken> mReplacingWindowTimeouts = new ArrayList<>();
438 * The input consumer added to the window manager which consumes input events to windows below
441 InputConsumerImpl mInputConsumer;
444 * The input consumer added to the window manager before all wallpaper windows.
446 InputConsumerImpl mWallpaperInputConsumer;
449 * Windows that are being resized. Used so we can tell the client about
450 * the resize after closing the transaction in which we resized the
451 * underlying surface.
453 final ArrayList<WindowState> mResizingWindows = new ArrayList<>();
456 * Windows whose animations have ended and now must be removed.
458 final ArrayList<WindowState> mPendingRemove = new ArrayList<>();
461 * Used when processing mPendingRemove to avoid working on the original array.
463 WindowState[] mPendingRemoveTmp = new WindowState[20];
466 * Windows whose surface should be destroyed.
468 final ArrayList<WindowState> mDestroySurface = new ArrayList<>();
471 * Windows with a preserved surface waiting to be destroyed. These windows
472 * are going through a surface change. We keep the old surface around until
473 * the first frame on the new surface finishes drawing.
475 final ArrayList<WindowState> mDestroyPreservedSurface = new ArrayList<>();
478 * Windows that have lost input focus and are waiting for the new
479 * focus window to be displayed before they are told about this.
481 ArrayList<WindowState> mLosingFocus = new ArrayList<>();
484 * This is set when we have run out of memory, and will either be an empty
485 * list or contain windows that need to be force removed.
487 final ArrayList<WindowState> mForceRemoves = new ArrayList<>();
490 * Windows that clients are waiting to have drawn.
492 ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>();
494 * And the callback to make when they've all been drawn.
496 Runnable mWaitingForDrawnCallback;
499 * Used when rebuilding window list to keep track of windows that have
502 WindowState[] mRebuildTmp = new WindowState[20];
505 * Stores for each user whether screencapture is disabled
506 * This array is essentially a cache for all userId for
507 * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled}
509 SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>();
511 IInputMethodManager mInputMethodManager;
513 AccessibilityController mAccessibilityController;
515 final SurfaceSession mFxSession;
516 Watermark mWatermark;
517 StrictModeFlash mStrictModeFlash;
518 CircularDisplayMask mCircularDisplayMask;
519 EmulatorDisplayOverlay mEmulatorDisplayOverlay;
521 final float[] mTmpFloats = new float[9];
522 final Rect mTmpRect = new Rect();
523 final Rect mTmpRect2 = new Rect();
524 final Rect mTmpRect3 = new Rect();
525 final RectF mTmpRectF = new RectF();
527 final Matrix mTmpTransform = new Matrix();
529 boolean mDisplayReady;
531 boolean mDisplayEnabled = false;
532 boolean mSystemBooted = false;
533 boolean mForceDisplayEnabled = false;
534 boolean mShowingBootMessages = false;
535 boolean mBootAnimationStopped = false;
537 // Following variables are for debugging screen wakelock only.
538 WindowState mLastWakeLockHoldingWindow = null;
539 WindowState mLastWakeLockObscuringWindow = null;
541 /** Dump of the windows and app tokens at the time of the last ANR. Cleared after
542 * LAST_ANR_LIFETIME_DURATION_MSECS */
543 String mLastANRState;
545 /** All DisplayContents in the world, kept here */
546 SparseArray<DisplayContent> mDisplayContents = new SparseArray<>(2);
549 int mLastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
550 boolean mAltOrientation = false;
552 private boolean mKeyguardWaitingForActivityDrawn;
554 int mDockedStackCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
555 Rect mDockedStackCreateBounds;
557 private final SparseIntArray mTmpTaskIds = new SparseIntArray();
559 private final ArrayList<Integer> mChangedStackList = new ArrayList();
561 boolean mForceResizableTasks = false;
563 int getDragLayerLocked() {
564 return mPolicy.windowTypeToLayerLw(LayoutParams.TYPE_DRAG) * TYPE_LAYER_MULTIPLIER
568 class RotationWatcher {
569 IRotationWatcher watcher;
570 IBinder.DeathRecipient deathRecipient;
571 RotationWatcher(IRotationWatcher w, IBinder.DeathRecipient d) {
576 ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<>();
577 int mDeferredRotationPauseCount;
579 int mSystemDecorLayer = 0;
580 final Rect mScreenRect = new Rect();
582 boolean mDisplayFrozen = false;
583 long mDisplayFreezeTime = 0;
584 int mLastDisplayFreezeDuration = 0;
585 Object mLastFinishedFreezeSource = null;
586 boolean mWaitingForConfig = false;
588 final static int WINDOWS_FREEZING_SCREENS_NONE = 0;
589 final static int WINDOWS_FREEZING_SCREENS_ACTIVE = 1;
590 final static int WINDOWS_FREEZING_SCREENS_TIMEOUT = 2;
591 int mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
593 boolean mClientFreezingScreen = false;
594 int mAppsFreezingScreen = 0;
595 int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
596 int mLastKeyguardForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
600 // Last systemUiVisibility we received from status bar.
601 int mLastStatusBarVisibility = 0;
602 // Last systemUiVisibility we dispatched to windows.
603 int mLastDispatchedSystemUiVisibility = 0;
605 // State while inside of layoutAndPlaceSurfacesLocked().
606 boolean mFocusMayChange;
608 Configuration mCurConfiguration = new Configuration();
610 // This is held as long as we have the screen frozen, to give us time to
611 // perform a rotation animation when turning off shows the lock screen which
612 // changes the orientation.
613 private final PowerManager.WakeLock mScreenFrozenLock;
615 final AppTransition mAppTransition;
616 boolean mSkipAppTransitionAnimation = false;
618 final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<>();
619 final ArraySet<AppWindowToken> mClosingApps = new ArraySet<>();
621 boolean mIsTouchDevice;
623 final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
624 final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
625 final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
626 final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics();
628 final H mH = new H();
630 final Choreographer mChoreographer = Choreographer.getInstance();
632 WindowState mCurrentFocus = null;
633 WindowState mLastFocus = null;
635 /** This just indicates the window the input method is on top of, not
636 * necessarily the window its input is going to. */
637 WindowState mInputMethodTarget = null;
639 /** If true hold off on modifying the animation layer of mInputMethodTarget */
640 boolean mInputMethodTargetWaitingAnim;
642 WindowState mInputMethodWindow = null;
643 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<>();
645 /** Temporary list for comparison. Always clear this after use so we don't end up with
646 * orphaned windows references */
647 final ArrayList<WindowState> mTmpWindows = new ArrayList<>();
649 boolean mHardKeyboardAvailable;
650 WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
651 SettingsObserver mSettingsObserver;
653 private final class SettingsObserver extends ContentObserver {
654 private final Uri mDisplayInversionEnabledUri =
655 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
656 private final Uri mWindowAnimationScaleUri =
657 Settings.Global.getUriFor(Settings.Global.WINDOW_ANIMATION_SCALE);
658 private final Uri mTransitionAnimationScaleUri =
659 Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE);
660 private final Uri mAnimationDurationScaleUri =
661 Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE);
663 public SettingsObserver() {
664 super(new Handler());
665 ContentResolver resolver = mContext.getContentResolver();
666 resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this,
667 UserHandle.USER_ALL);
668 resolver.registerContentObserver(mWindowAnimationScaleUri, false, this,
669 UserHandle.USER_ALL);
670 resolver.registerContentObserver(mTransitionAnimationScaleUri, false, this,
671 UserHandle.USER_ALL);
672 resolver.registerContentObserver(mAnimationDurationScaleUri, false, this,
673 UserHandle.USER_ALL);
677 public void onChange(boolean selfChange, Uri uri) {
682 if (mDisplayInversionEnabledUri.equals(uri)) {
683 updateCircularDisplayMaskIfNeeded();
685 @UpdateAnimationScaleMode
687 if (mWindowAnimationScaleUri.equals(uri)) {
688 mode = WINDOW_ANIMATION_SCALE;
689 } else if (mTransitionAnimationScaleUri.equals(uri)) {
690 mode = TRANSITION_ANIMATION_SCALE;
691 } else if (mAnimationDurationScaleUri.equals(uri)) {
692 mode = ANIMATION_DURATION_SCALE;
694 // Ignoring unrecognized content changes
697 Message m = mH.obtainMessage(H.UPDATE_ANIMATION_SCALE, mode, 0);
703 WallpaperController mWallpaperControllerLocked;
705 final WindowLayersController mLayersController;
707 boolean mAnimateWallpaperWithTarget;
709 AppWindowToken mFocusedApp = null;
711 PowerManager mPowerManager;
712 PowerManagerInternal mPowerManagerInternal;
714 float mWindowAnimationScaleSetting = 1.0f;
715 float mTransitionAnimationScaleSetting = 1.0f;
716 float mAnimatorDurationScaleSetting = 1.0f;
717 boolean mAnimationsDisabled = false;
719 final InputManagerService mInputManager;
720 final DisplayManagerInternal mDisplayManagerInternal;
721 final DisplayManager mDisplayManager;
722 final Display[] mDisplays;
724 // Who is holding the screen on.
725 Session mHoldingScreenOn;
726 PowerManager.WakeLock mHoldingScreenWakeLock;
728 boolean mTurnOnScreen;
730 // Whether or not a layout can cause a wake up when theater mode is enabled.
731 boolean mAllowTheaterModeWakeFromLayout;
733 TaskPositioner mTaskPositioner;
734 DragState mDragState = null;
736 // For frozen screen animations.
737 int mExitAnimId, mEnterAnimId;
739 boolean mAnimationScheduled;
741 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
742 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
743 int mTransactionSequence;
745 final WindowAnimator mAnimator;
747 private final BoundsAnimationController mBoundsAnimationController;
749 SparseArray<Task> mTaskIdToTask = new SparseArray<>();
751 /** All of the TaskStacks in the window manager, unordered. For an ordered list call
752 * DisplayContent.getStacks(). */
753 SparseArray<TaskStack> mStackIdToStack = new SparseArray<>();
755 private final PointerEventDispatcher mPointerEventDispatcher;
757 private WindowContentFrameStats mTempWindowRenderStats;
759 final class DragInputEventReceiver extends InputEventReceiver {
760 // Set, if stylus button was down at the start of the drag.
761 private boolean mStylusButtonDownAtStart;
762 // Indicates the first event to check for button state.
763 private boolean mIsStartEvent = true;
765 public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
766 super(inputChannel, looper);
770 public void onInputEvent(InputEvent event) {
771 boolean handled = false;
773 if (event instanceof MotionEvent
774 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0
775 && mDragState != null) {
776 final MotionEvent motionEvent = (MotionEvent)event;
777 boolean endDrag = false;
778 final float newX = motionEvent.getRawX();
779 final float newY = motionEvent.getRawY();
780 final boolean isStylusButtonDown =
781 (motionEvent.getButtonState() & MotionEvent.BUTTON_STYLUS_PRIMARY) != 0;
784 if (isStylusButtonDown) {
785 // First event and the button was down, check for the button being
786 // lifted in the future, if that happens we'll drop the item.
787 mStylusButtonDownAtStart = true;
789 mIsStartEvent = false;
792 switch (motionEvent.getAction()) {
793 case MotionEvent.ACTION_DOWN: {
795 Slog.w(TAG_WM, "Unexpected ACTION_DOWN in drag layer");
799 case MotionEvent.ACTION_MOVE: {
800 if (mStylusButtonDownAtStart && !isStylusButtonDown) {
801 if (DEBUG_DRAG) Slog.d(TAG_WM, "Button no longer pressed; dropping at "
802 + newX + "," + newY);
803 synchronized (mWindowMap) {
804 endDrag = mDragState.notifyDropLw(newX, newY);
807 synchronized (mWindowMap) {
808 // move the surface and tell the involved window(s) where we are
809 mDragState.notifyMoveLw(newX, newY);
814 case MotionEvent.ACTION_UP: {
815 if (DEBUG_DRAG) Slog.d(TAG_WM, "Got UP on move channel; dropping at "
816 + newX + "," + newY);
817 synchronized (mWindowMap) {
818 endDrag = mDragState.notifyDropLw(newX, newY);
822 case MotionEvent.ACTION_CANCEL: {
823 if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag cancelled!");
829 if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ended; tearing down state");
830 // tell all the windows that the drag has ended
831 synchronized (mWindowMap) {
832 mDragState.endDragLw();
834 mStylusButtonDownAtStart = false;
835 mIsStartEvent = true;
840 } catch (Exception e) {
841 Slog.e(TAG_WM, "Exception caught by drag handleMotion", e);
843 finishInputEvent(event, handled);
849 * Whether the UI is currently running in touch mode (not showing
850 * navigational focus because the user is directly pressing the screen).
852 boolean mInTouchMode;
854 private ViewServer mViewServer;
855 final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
856 boolean mWindowsChanged = false;
858 public interface WindowChangeListener {
859 public void windowsChanged();
860 public void focusChanged();
863 final Configuration mTempConfiguration = new Configuration();
865 // The desired scaling factor for compatible apps.
866 float mCompatibleScreenScale;
868 // If true, only the core apps and services are being launched because the device
869 // is in a special boot mode, such as being encrypted or waiting for a decryption password.
870 // For example, when this flag is true, there will be no wallpaper service.
871 final boolean mOnlyCore;
873 // List of clients without a transtiton animation that we notify once we are done transitioning
874 // since they won't be notified through the app window animator.
875 final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
877 // List of displays to reconfigure after configuration changes.
878 // Some of the information reported for a display is dependent on resources to do the right
879 // calculations. For example, {@link DisplayInfo#smallestNominalAppWidth} and company are
880 // dependent on the height and width of the status and nav bar which change depending on the
881 // current configuration.
882 private final DisplayContentList mReconfigureOnConfigurationChanged = new DisplayContentList();
884 /** Listener to notify activity manager about app transitions. */
885 private final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier
886 = new WindowManagerInternal.AppTransitionListener() {
889 public void onAppTransitionCancelledLocked() {
890 mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_CANCELLED);
894 public void onAppTransitionFinishedLocked(IBinder token) {
895 mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_FINISHED);
896 AppWindowToken atoken = findAppWindowToken(token);
897 if (atoken == null) {
900 if (atoken.mLaunchTaskBehind) {
902 mActivityManager.notifyLaunchTaskBehindComplete(atoken.token);
903 } catch (RemoteException e) {
905 atoken.mLaunchTaskBehind = false;
907 atoken.updateReportedVisibilityLocked();
908 if (atoken.mEnteringAnimation) {
909 atoken.mEnteringAnimation = false;
911 mActivityManager.notifyEnterAnimationComplete(atoken.token);
912 } catch (RemoteException e) {
919 public static WindowManagerService main(final Context context,
920 final InputManagerService im,
921 final boolean haveInputMethods, final boolean showBootMsgs,
922 final boolean onlyCore) {
923 final WindowManagerService[] holder = new WindowManagerService[1];
924 DisplayThread.getHandler().runWithScissors(new Runnable() {
927 holder[0] = new WindowManagerService(context, im,
928 haveInputMethods, showBootMsgs, onlyCore);
934 private void initPolicy() {
935 UiThread.getHandler().runWithScissors(new Runnable() {
938 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
940 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
945 private WindowManagerService(Context context, InputManagerService inputManager,
946 boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
948 mHaveInputMethods = haveInputMethods;
949 mAllowBootMessages = showBootMsgs;
950 mOnlyCore = onlyCore;
951 mLimitedAlphaCompositing = context.getResources().getBoolean(
952 com.android.internal.R.bool.config_sf_limitedAlpha);
953 mHasPermanentDpad = context.getResources().getBoolean(
954 com.android.internal.R.bool.config_hasPermanentDpad);
955 mInTouchMode = context.getResources().getBoolean(
956 com.android.internal.R.bool.config_defaultInTouchMode);
957 mDrawLockTimeoutMillis = context.getResources().getInteger(
958 com.android.internal.R.integer.config_drawLockTimeoutMillis);
959 mAllowAnimationsInLowPowerMode = context.getResources().getBoolean(
960 com.android.internal.R.bool.config_allowAnimationsInLowPowerMode);
961 mInputManager = inputManager; // Must be before createDisplayContentLocked.
962 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
963 mDisplaySettings = new DisplaySettings();
964 mDisplaySettings.readSettingsLocked();
966 mWallpaperControllerLocked = new WallpaperController(this);
967 mWindowPlacerLocked = new WindowSurfacePlacer(this);
968 mLayersController = new WindowLayersController(this);
970 LocalServices.addService(WindowManagerPolicy.class, mPolicy);
972 mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG_WM));
974 mFxSession = new SurfaceSession();
975 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
976 mDisplays = mDisplayManager.getDisplays();
977 for (Display display : mDisplays) {
978 createDisplayContentLocked(display);
981 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
983 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
984 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
985 mPowerManagerInternal.registerLowPowerModeObserver(
986 new PowerManagerInternal.LowPowerModeListener() {
988 public void onLowPowerModeChanged(boolean enabled) {
989 synchronized (mWindowMap) {
990 if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
991 mAnimationsDisabled = enabled;
992 dispatchNewAnimatorScaleLocked(null);
997 mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled();
998 mScreenFrozenLock = mPowerManager.newWakeLock(
999 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
1000 mScreenFrozenLock.setReferenceCounted(false);
1002 mAppTransition = new AppTransition(context, this);
1003 mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier);
1005 mBoundsAnimationController =
1006 new BoundsAnimationController(mAppTransition, UiThread.getHandler());
1008 mActivityManager = ActivityManagerNative.getDefault();
1009 mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
1010 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
1011 AppOpsManager.OnOpChangedInternalListener opListener =
1012 new AppOpsManager.OnOpChangedInternalListener() {
1013 @Override public void onOpChanged(int op, String packageName) {
1014 updateAppOpsState();
1017 mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null, opListener);
1018 mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener);
1020 // Get persisted window scale setting
1021 mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
1022 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
1023 mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
1024 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting);
1025 setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
1026 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
1028 // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
1029 IntentFilter filter = new IntentFilter();
1030 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
1031 mContext.registerReceiver(mBroadcastReceiver, filter);
1033 mSettingsObserver = new SettingsObserver();
1035 mHoldingScreenWakeLock = mPowerManager.newWakeLock(
1036 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
1037 mHoldingScreenWakeLock.setReferenceCounted(false);
1039 mAnimator = new WindowAnimator(this);
1041 mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
1042 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
1045 LocalServices.addService(WindowManagerInternal.class, new LocalService());
1048 // Add ourself to the Watchdog monitors.
1049 Watchdog.getInstance().addMonitor(this);
1051 SurfaceControl.openTransaction();
1053 createWatermarkInTransaction();
1055 SurfaceControl.closeTransaction();
1058 showEmulatorDisplayOverlayIfNeeded();
1061 public InputMonitor getInputMonitor() {
1062 return mInputMonitor;
1066 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1067 throws RemoteException {
1069 return super.onTransact(code, data, reply, flags);
1070 } catch (RuntimeException e) {
1071 // The window manager only throws security exceptions, so let's
1073 if (!(e instanceof SecurityException)) {
1074 Slog.wtf(TAG_WM, "Window Manager Crash", e);
1080 private void placeWindowAfter(WindowState pos, WindowState window) {
1081 final WindowList windows = pos.getWindowList();
1082 final int i = windows.indexOf(pos);
1083 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
1084 TAG_WM, "Adding window " + window + " at "
1085 + (i+1) + " of " + windows.size() + " (after " + pos + ")");
1086 windows.add(i+1, window);
1087 mWindowsChanged = true;
1090 private void placeWindowBefore(WindowState pos, WindowState window) {
1091 final WindowList windows = pos.getWindowList();
1092 int i = windows.indexOf(pos);
1093 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
1094 TAG_WM, "Adding window " + window + " at "
1095 + i + " of " + windows.size() + " (before " + pos + ")");
1097 Slog.w(TAG_WM, "placeWindowBefore: Unable to find " + pos + " in " + windows);
1100 windows.add(i, window);
1101 mWindowsChanged = true;
1104 //This method finds out the index of a window that has the same app token as
1105 //win. used for z ordering the windows in mWindows
1106 private int findIdxBasedOnAppTokens(WindowState win) {
1107 WindowList windows = win.getWindowList();
1108 for(int j = windows.size() - 1; j >= 0; j--) {
1109 WindowState wentry = windows.get(j);
1110 if(wentry.mAppToken == win.mAppToken) {
1118 * Return the list of Windows from the passed token on the given Display.
1119 * @param token The token with all the windows.
1120 * @param displayContent The display we are interested in.
1121 * @return List of windows from token that are on displayContent.
1123 private WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) {
1124 final WindowList windowList = new WindowList();
1125 final int count = token.windows.size();
1126 for (int i = 0; i < count; i++) {
1127 final WindowState win = token.windows.get(i);
1128 if (win.getDisplayContent() == displayContent) {
1129 windowList.add(win);
1136 * Recursive search through a WindowList and all of its windows' children.
1137 * @param targetWin The window to search for.
1138 * @param windows The list to search.
1139 * @return The index of win in windows or of the window that is an ancestor of win.
1141 private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) {
1142 for (int i = windows.size() - 1; i >= 0; i--) {
1143 final WindowState w = windows.get(i);
1144 if (w == targetWin) {
1147 if (!w.mChildWindows.isEmpty()) {
1148 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) {
1156 private int addAppWindowToListLocked(final WindowState win) {
1157 final DisplayContent displayContent = win.getDisplayContent();
1158 if (displayContent == null) {
1159 // It doesn't matter this display is going away.
1162 final IWindow client = win.mClient;
1163 final WindowToken token = win.mToken;
1165 final WindowList windows = displayContent.getWindowList();
1166 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
1167 int tokenWindowsPos = 0;
1168 if (!tokenWindowList.isEmpty()) {
1169 return addAppWindowToTokenListLocked(win, token, windows, tokenWindowList);
1172 // No windows from this token on this display
1173 if (localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window " + client.asBinder()
1174 + " (token=" + token + ")");
1175 // Figure out where the window should go, based on the
1176 // order of applications.
1177 WindowState pos = null;
1179 final ArrayList<Task> tasks = displayContent.getTasks();
1182 for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
1183 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
1184 for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
1185 final AppWindowToken t = tokens.get(tokenNdx);
1191 tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1;
1197 // We haven't reached the token yet; if this token
1198 // is not going to the bottom and has windows on this display, we can
1199 // use it as an anchor for when we do reach the token.
1200 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
1201 if (!t.sendingToBottom && tokenWindowList.size() > 0) {
1202 pos = tokenWindowList.get(0);
1205 if (tokenNdx >= 0) {
1211 // We now know the index into the apps. If we found
1212 // an app window above, that gives us the position; else
1213 // we need to look some more.
1215 // Move behind any windows attached to this one.
1216 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
1217 if (atoken != null) {
1219 getTokenWindowsOnDisplay(atoken, displayContent);
1220 final int NC = tokenWindowList.size();
1222 WindowState bottom = tokenWindowList.get(0);
1223 if (bottom.mSubLayer < 0) {
1228 placeWindowBefore(pos, win);
1229 return tokenWindowsPos;
1232 // Continue looking down until we find the first
1233 // token that has windows on this display.
1234 for ( ; taskNdx >= 0; --taskNdx) {
1235 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
1236 for ( ; tokenNdx >= 0; --tokenNdx) {
1237 final AppWindowToken t = tokens.get(tokenNdx);
1238 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
1239 final int NW = tokenWindowList.size();
1241 pos = tokenWindowList.get(NW-1);
1245 if (tokenNdx >= 0) {
1252 // Move in front of any windows attached to this
1254 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
1255 if (atoken != null) {
1256 final int NC = atoken.windows.size();
1258 WindowState top = atoken.windows.get(NC-1);
1259 if (top.mSubLayer >= 0) {
1264 placeWindowAfter(pos, win);
1265 return tokenWindowsPos;
1268 // Just search for the start of this layer.
1269 final int myLayer = win.mBaseLayer;
1271 for (i = windows.size() - 1; i >= 0; --i) {
1272 WindowState w = windows.get(i);
1273 // Dock divider shares the base layer with application windows, but we want to always
1274 // keep it above the application windows. The sharing of the base layer is intended
1275 // for window animations, which need to be above the dock divider for the duration
1276 // of the animation.
1277 if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) {
1281 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1282 "Based on layer: Adding window " + win + " at " + (i + 1) + " of "
1284 windows.add(i + 1, win);
1285 mWindowsChanged = true;
1286 return tokenWindowsPos;
1289 private int addAppWindowToTokenListLocked(WindowState win, WindowToken token,
1290 WindowList windows, WindowList tokenWindowList) {
1291 int tokenWindowsPos;
1292 // If this application has existing windows, we
1293 // simply place the new window on top of them... but
1294 // keep the starting window on top.
1295 if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
1296 // Base windows go behind everything else.
1297 WindowState lowestWindow = tokenWindowList.get(0);
1298 placeWindowBefore(lowestWindow, win);
1299 tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows);
1301 AppWindowToken atoken = win.mAppToken;
1302 final int windowListPos = tokenWindowList.size();
1303 WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
1304 if (atoken != null && lastWindow == atoken.startingWindow) {
1305 placeWindowBefore(lastWindow, win);
1306 tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows);
1308 int newIdx = findIdxBasedOnAppTokens(win);
1309 //there is a window above this one associated with the same
1310 //apptoken note that the window could be a floating window
1311 //that was created later or a window at the top of the list of
1312 //windows associated with this token.
1313 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1314 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of "
1316 windows.add(newIdx + 1, win);
1318 // No window from token found on win's display.
1319 tokenWindowsPos = 0;
1321 tokenWindowsPos = indexOfWinInWindowList(
1322 windows.get(newIdx), token.windows) + 1;
1324 mWindowsChanged = true;
1327 return tokenWindowsPos;
1330 private void addFreeWindowToListLocked(final WindowState win) {
1331 final WindowList windows = win.getWindowList();
1333 // Figure out where window should go, based on layer.
1334 final int myLayer = win.mBaseLayer;
1336 for (i = windows.size() - 1; i >= 0; i--) {
1337 final WindowState otherWin = windows.get(i);
1338 if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= myLayer) {
1339 // Wallpaper wanders through the window list, for example to position itself
1340 // directly behind keyguard. Because of this it will break the ordering based on
1341 // WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and
1342 // we don't want the new window to appear above them. An example of this is adding
1343 // of the docked stack divider. Consider a scenario with the following ordering (top
1344 // to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider
1345 // to land below the assist preview, so the dock divider must ignore the wallpaper,
1346 // with which it shares the base layer.
1351 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1352 "Free window: Adding window " + win + " at " + i + " of " + windows.size());
1353 windows.add(i, win);
1354 mWindowsChanged = true;
1357 private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) {
1358 final WindowToken token = win.mToken;
1359 final DisplayContent displayContent = win.getDisplayContent();
1360 if (displayContent == null) {
1363 final WindowState attached = win.mAttachedWindow;
1365 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
1367 // Figure out this window's ordering relative to the window
1368 // it is attached to.
1369 final int NA = tokenWindowList.size();
1370 final int sublayer = win.mSubLayer;
1371 int largestSublayer = Integer.MIN_VALUE;
1372 WindowState windowWithLargestSublayer = null;
1374 for (i = 0; i < NA; i++) {
1375 WindowState w = tokenWindowList.get(i);
1376 final int wSublayer = w.mSubLayer;
1377 if (wSublayer >= largestSublayer) {
1378 largestSublayer = wSublayer;
1379 windowWithLargestSublayer = w;
1382 // For negative sublayers, we go below all windows
1383 // in the same sublayer.
1384 if (wSublayer >= sublayer) {
1386 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + token);
1387 token.windows.add(i, win);
1389 placeWindowBefore(wSublayer >= 0 ? attached : w, win);
1393 // For positive sublayers, we go above all windows
1394 // in the same sublayer.
1395 if (wSublayer > sublayer) {
1397 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + token);
1398 token.windows.add(i, win);
1400 placeWindowBefore(w, win);
1407 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + token);
1408 token.windows.add(win);
1411 placeWindowBefore(attached, win);
1413 placeWindowAfter(largestSublayer >= 0
1414 ? windowWithLargestSublayer
1421 private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) {
1422 if (DEBUG_FOCUS) Slog.d(TAG_WM, "addWindowToListInOrderLocked: win=" + win +
1423 " Callers=" + Debug.getCallers(4));
1424 if (win.mAttachedWindow == null) {
1425 final WindowToken token = win.mToken;
1426 int tokenWindowsPos = 0;
1427 if (token.appWindowToken != null) {
1428 tokenWindowsPos = addAppWindowToListLocked(win);
1430 addFreeWindowToListLocked(win);
1433 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + token);
1434 token.windows.add(tokenWindowsPos, win);
1437 addAttachedWindowToListLocked(win, addToToken);
1440 final AppWindowToken appToken = win.mAppToken;
1441 if (appToken != null) {
1443 appToken.addWindow(win);
1448 static boolean canBeImeTarget(WindowState w) {
1449 final int fl = w.mAttrs.flags
1450 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
1451 final int type = w.mAttrs.type;
1452 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)
1453 || type == TYPE_APPLICATION_STARTING) {
1454 if (DEBUG_INPUT_METHOD) {
1455 Slog.i(TAG_WM, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
1456 if (!w.isVisibleOrAdding()) {
1457 Slog.i(TAG_WM, " mSurfaceController=" + w.mWinAnimator.mSurfaceController
1458 + " relayoutCalled=" + w.mRelayoutCalled
1459 + " viewVis=" + w.mViewVisibility
1460 + " policyVis=" + w.mPolicyVisibility
1461 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
1462 + " attachHid=" + w.mAttachedHidden
1463 + " exiting=" + w.mAnimatingExit + " destroying=" + w.mDestroying);
1464 if (w.mAppToken != null) {
1465 Slog.i(TAG_WM, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
1469 return w.isVisibleOrAdding();
1475 * Dig through the WindowStates and find the one that the Input Method will target.
1477 * @return The index+1 in mWindows of the discovered target.
1479 int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
1480 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
1481 // same display. Or even when the current IME/target are not on the same screen as the next
1482 // IME/target. For now only look for input windows on the main screen.
1483 WindowList windows = getDefaultWindowListLocked();
1484 WindowState w = null;
1486 for (i = windows.size() - 1; i >= 0; --i) {
1487 WindowState win = windows.get(i);
1489 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG_WM, "Checking window @" + i
1490 + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
1491 if (canBeImeTarget(win)) {
1493 //Slog.i(TAG_WM, "Putting input method here!");
1495 // Yet more tricksyness! If this window is a "starting"
1496 // window, we do actually want to be on top of it, but
1497 // it is not -really- where input will go. So if the caller
1498 // is not actually looking to move the IME, look down below
1499 // for a real window to target...
1501 && w.mAttrs.type == TYPE_APPLICATION_STARTING
1503 WindowState wb = windows.get(i-1);
1504 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
1513 // Now w is either mWindows[0] or an IME (or null if mWindows is empty).
1515 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG_WM, "Proposed new IME target: " + w);
1517 // Now, a special case -- if the last target's window is in the
1518 // process of exiting, and is above the new target, keep on the
1519 // last target to avoid flicker. Consider for example a Dialog with
1520 // the IME shown: when the Dialog is dismissed, we want to keep
1521 // the IME above it until it is completely gone so it doesn't drop
1522 // behind the dialog or its full-screen scrim.
1523 final WindowState curTarget = mInputMethodTarget;
1524 if (curTarget != null
1525 && curTarget.isDisplayedLw()
1526 && curTarget.isClosing()
1527 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
1528 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing");
1529 return windows.indexOf(curTarget) + 1;
1532 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target="
1533 + w + " willMove=" + willMove);
1535 if (willMove && w != null) {
1536 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
1537 if (token != null) {
1539 // Now some fun for dealing with window animations that
1540 // modify the Z order. We need to look at all windows below
1541 // the current target that are in this app, finding the highest
1542 // visible one in layering.
1543 WindowState highestTarget = null;
1545 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
1546 WindowList curWindows = curTarget.getWindowList();
1547 int pos = curWindows.indexOf(curTarget);
1549 WindowState win = curWindows.get(pos);
1550 if (win.mAppToken != token) {
1553 if (!win.mRemoved) {
1554 if (highestTarget == null || win.mWinAnimator.mAnimLayer >
1555 highestTarget.mWinAnimator.mAnimLayer) {
1556 highestTarget = win;
1564 if (highestTarget != null) {
1565 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, mAppTransition + " " + highestTarget
1566 + " animating=" + highestTarget.mWinAnimator.isAnimationSet()
1567 + " layer=" + highestTarget.mWinAnimator.mAnimLayer
1568 + " new layer=" + w.mWinAnimator.mAnimLayer);
1570 if (mAppTransition.isTransitionSet()) {
1571 // If we are currently setting up for an animation,
1572 // hold everything until we can find out what will happen.
1573 mInputMethodTargetWaitingAnim = true;
1574 mInputMethodTarget = highestTarget;
1575 return highestPos + 1;
1576 } else if (highestTarget.mWinAnimator.isAnimationSet() &&
1577 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
1578 // If the window we are currently targeting is involved
1579 // with an animation, and it is on top of the next target
1580 // we will be over, then hold off on moving until
1582 mInputMethodTargetWaitingAnim = true;
1583 mInputMethodTarget = highestTarget;
1584 return highestPos + 1;
1590 //Slog.i(TAG_WM, "Placing input method @" + (i+1));
1593 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
1594 + w + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
1595 mInputMethodTarget = w;
1596 mInputMethodTargetWaitingAnim = false;
1597 if (w.mAppToken != null) {
1598 mLayersController.setInputMethodAnimLayerAdjustment(
1599 w.mAppToken.mAppAnimator.animLayerAdjustment);
1601 mLayersController.setInputMethodAnimLayerAdjustment(0);
1605 // If the docked divider is visible, we still need to go through this whole
1606 // excercise to find the appropriate input method target (used for animations
1607 // and dialog adjustments), but for purposes of Z ordering we simply wish to
1608 // place it above the docked divider. Unless it is already above the divider.
1609 WindowState dockedDivider = w.mDisplayContent.mDividerControllerLocked.getWindow();
1610 if (dockedDivider != null && dockedDivider.isVisibleLw()) {
1611 int dividerIndex = windows.indexOf(dockedDivider);
1612 if (dividerIndex > 0 && dividerIndex > i) {
1613 return dividerIndex + 1;
1619 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to null."
1620 + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
1621 mInputMethodTarget = null;
1622 mLayersController.setInputMethodAnimLayerAdjustment(0);
1627 void addInputMethodWindowToListLocked(WindowState win) {
1628 int pos = findDesiredInputMethodWindowIndexLocked(true);
1630 win.mTargetAppToken = mInputMethodTarget.mAppToken;
1631 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
1632 TAG_WM, "Adding input method window " + win + " at " + pos);
1633 // TODO(multidisplay): IMEs are only supported on the default display.
1634 getDefaultWindowListLocked().add(pos, win);
1635 mWindowsChanged = true;
1636 moveInputMethodDialogsLocked(pos + 1);
1639 win.mTargetAppToken = null;
1640 addWindowToListInOrderLocked(win, true);
1641 moveInputMethodDialogsLocked(pos);
1644 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
1645 WindowList windows = win.getWindowList();
1646 int wpos = windows.indexOf(win);
1648 if (wpos < interestingPos) interestingPos--;
1649 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing at " + wpos + ": " + win);
1650 windows.remove(wpos);
1651 mWindowsChanged = true;
1652 int NC = win.mChildWindows.size();
1655 WindowState cw = win.mChildWindows.get(NC);
1656 int cpos = windows.indexOf(cw);
1658 if (cpos < interestingPos) interestingPos--;
1659 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing child at "
1660 + cpos + ": " + cw);
1661 windows.remove(cpos);
1665 return interestingPos;
1668 private void reAddWindowToListInOrderLocked(WindowState win) {
1669 addWindowToListInOrderLocked(win, false);
1670 // This is a hack to get all of the child windows added as well
1671 // at the right position. Child windows should be rare and
1672 // this case should be rare, so it shouldn't be that big a deal.
1673 WindowList windows = win.getWindowList();
1674 int wpos = windows.indexOf(win);
1676 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "ReAdd removing from " + wpos + ": " + win);
1677 windows.remove(wpos);
1678 mWindowsChanged = true;
1679 reAddWindowLocked(wpos, win);
1683 void logWindowList(final WindowList windows, String prefix) {
1684 int N = windows.size();
1687 Slog.v(TAG_WM, prefix + "#" + N + ": " + windows.get(N));
1691 void moveInputMethodDialogsLocked(int pos) {
1692 ArrayList<WindowState> dialogs = mInputMethodDialogs;
1694 // TODO(multidisplay): IMEs are only supported on the default display.
1695 WindowList windows = getDefaultWindowListLocked();
1696 final int N = dialogs.size();
1697 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Removing " + N + " dialogs w/pos=" + pos);
1698 for (int i=0; i<N; i++) {
1699 pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
1701 if (DEBUG_INPUT_METHOD) {
1702 Slog.v(TAG_WM, "Window list w/pos=" + pos);
1703 logWindowList(windows, " ");
1707 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
1708 // Skip windows owned by the input method.
1709 if (mInputMethodWindow != null) {
1710 while (pos < windows.size()) {
1711 WindowState wp = windows.get(pos);
1712 if (wp == mInputMethodWindow || wp.mAttachedWindow == mInputMethodWindow) {
1719 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Adding " + N + " dialogs at pos=" + pos);
1720 for (int i=0; i<N; i++) {
1721 WindowState win = dialogs.get(i);
1722 win.mTargetAppToken = targetAppToken;
1723 pos = reAddWindowLocked(pos, win);
1725 if (DEBUG_INPUT_METHOD) {
1726 Slog.v(TAG_WM, "Final window list:");
1727 logWindowList(windows, " ");
1731 for (int i=0; i<N; i++) {
1732 WindowState win = dialogs.get(i);
1733 win.mTargetAppToken = null;
1734 reAddWindowToListInOrderLocked(win);
1735 if (DEBUG_INPUT_METHOD) {
1736 Slog.v(TAG_WM, "No IM target, final list:");
1737 logWindowList(windows, " ");
1742 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
1743 final WindowState imWin = mInputMethodWindow;
1744 final int DN = mInputMethodDialogs.size();
1745 if (imWin == null && DN == 0) {
1749 // TODO(multidisplay): IMEs are only supported on the default display.
1750 WindowList windows = getDefaultWindowListLocked();
1752 int imPos = findDesiredInputMethodWindowIndexLocked(true);
1754 // In this case, the input method windows are to be placed
1755 // immediately above the window they are targeting.
1757 // First check to see if the input method windows are already
1758 // located here, and contiguous.
1759 final int N = windows.size();
1760 WindowState firstImWin = imPos < N
1761 ? windows.get(imPos) : null;
1763 // Figure out the actual input method window that should be
1764 // at the bottom of their stack.
1765 WindowState baseImWin = imWin != null
1766 ? imWin : mInputMethodDialogs.get(0);
1767 if (baseImWin.mChildWindows.size() > 0) {
1768 WindowState cw = baseImWin.mChildWindows.get(0);
1769 if (cw.mSubLayer < 0) baseImWin = cw;
1772 if (firstImWin == baseImWin) {
1773 // The windows haven't moved... but are they still contiguous?
1774 // First find the top IM window.
1777 if (!(windows.get(pos)).mIsImWindow) {
1783 // Now there should be no more input method windows above.
1785 if ((windows.get(pos)).mIsImWindow) {
1792 // The IM target window may be changed, so update the mTargetAppToken.
1793 if (imWin != null) {
1794 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1800 if (imWin != null) {
1801 if (DEBUG_INPUT_METHOD) {
1802 Slog.v(TAG_WM, "Moving IM from " + imPos);
1803 logWindowList(windows, " ");
1805 imPos = tmpRemoveWindowLocked(imPos, imWin);
1806 if (DEBUG_INPUT_METHOD) {
1807 Slog.v(TAG_WM, "List after removing with new pos " + imPos + ":");
1808 logWindowList(windows, " ");
1810 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1811 reAddWindowLocked(imPos, imWin);
1812 if (DEBUG_INPUT_METHOD) {
1813 Slog.v(TAG_WM, "List after moving IM to " + imPos + ":");
1814 logWindowList(windows, " ");
1816 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
1818 moveInputMethodDialogsLocked(imPos);
1822 // In this case, the input method windows go in a fixed layer,
1823 // because they aren't currently associated with a focus window.
1825 if (imWin != null) {
1826 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Moving IM from " + imPos);
1827 tmpRemoveWindowLocked(0, imWin);
1828 imWin.mTargetAppToken = null;
1829 reAddWindowToListInOrderLocked(imWin);
1830 if (DEBUG_INPUT_METHOD) {
1831 Slog.v(TAG_WM, "List with no IM target:");
1832 logWindowList(windows, " ");
1834 if (DN > 0) moveInputMethodDialogsLocked(-1);
1836 moveInputMethodDialogsLocked(-1);
1841 if (needAssignLayers) {
1842 mLayersController.assignLayersLocked(windows);
1848 private static boolean excludeWindowTypeFromTapOutTask(int windowType) {
1849 switch (windowType) {
1850 case TYPE_STATUS_BAR:
1851 case TYPE_NAVIGATION_BAR:
1852 case TYPE_INPUT_METHOD_DIALOG:
1858 public int addWindow(Session session, IWindow client, int seq,
1859 WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
1860 Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
1861 InputChannel outInputChannel) {
1862 int[] appOp = new int[1];
1863 int res = mPolicy.checkAddPermission(attrs, appOp);
1864 if (res != WindowManagerGlobal.ADD_OKAY) {
1868 boolean reportNewConfig = false;
1869 WindowState attachedWindow = null;
1871 final int type = attrs.type;
1873 synchronized(mWindowMap) {
1874 if (!mDisplayReady) {
1875 throw new IllegalStateException("Display has not been initialialized");
1878 final DisplayContent displayContent = getDisplayContentLocked(displayId);
1879 if (displayContent == null) {
1880 Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "
1881 + displayId + ". Aborting.");
1882 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1884 if (!displayContent.hasAccess(session.mUid)) {
1885 Slog.w(TAG_WM, "Attempted to add window to a display for which the application "
1886 + "does not have access: " + displayId + ". Aborting.");
1887 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1890 if (mWindowMap.containsKey(client.asBinder())) {
1891 Slog.w(TAG_WM, "Window " + client + " is already added");
1892 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
1895 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
1896 attachedWindow = windowForClientLocked(null, attrs.token, false);
1897 if (attachedWindow == null) {
1898 Slog.w(TAG_WM, "Attempted to add window with token that is not a window: "
1899 + attrs.token + ". Aborting.");
1900 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
1902 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
1903 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
1904 Slog.w(TAG_WM, "Attempted to add window with token that is a sub-window: "
1905 + attrs.token + ". Aborting.");
1906 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
1910 if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
1911 Slog.w(TAG_WM, "Attempted to add private presentation window to a non-private display. Aborting.");
1912 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
1915 boolean addToken = false;
1916 WindowToken token = mTokenMap.get(attrs.token);
1917 AppWindowToken atoken = null;
1918 if (token == null) {
1919 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
1920 Slog.w(TAG_WM, "Attempted to add application window with unknown token "
1921 + attrs.token + ". Aborting.");
1922 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1924 if (type == TYPE_INPUT_METHOD) {
1925 Slog.w(TAG_WM, "Attempted to add input method window with unknown token "
1926 + attrs.token + ". Aborting.");
1927 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1929 if (type == TYPE_VOICE_INTERACTION) {
1930 Slog.w(TAG_WM, "Attempted to add voice interaction window with unknown token "
1931 + attrs.token + ". Aborting.");
1932 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1934 if (type == TYPE_WALLPAPER) {
1935 Slog.w(TAG_WM, "Attempted to add wallpaper window with unknown token "
1936 + attrs.token + ". Aborting.");
1937 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1939 if (type == TYPE_DREAM) {
1940 Slog.w(TAG_WM, "Attempted to add Dream window with unknown token "
1941 + attrs.token + ". Aborting.");
1942 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1944 if (type == TYPE_QS_DIALOG) {
1945 Slog.w(TAG_WM, "Attempted to add QS dialog window with unknown token "
1946 + attrs.token + ". Aborting.");
1947 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1949 if (type == TYPE_ACCESSIBILITY_OVERLAY) {
1950 Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with unknown token "
1951 + attrs.token + ". Aborting.");
1952 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1954 token = new WindowToken(this, attrs.token, -1, false);
1956 } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
1957 atoken = token.appWindowToken;
1958 if (atoken == null) {
1959 Slog.w(TAG_WM, "Attempted to add window with non-application token "
1960 + token + ". Aborting.");
1961 return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
1962 } else if (atoken.removed) {
1963 Slog.w(TAG_WM, "Attempted to add window with exiting application token "
1964 + token + ". Aborting.");
1965 return WindowManagerGlobal.ADD_APP_EXITING;
1967 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
1968 // No need for this guy!
1969 if (DEBUG_STARTING_WINDOW || localLOGV) Slog.v(
1970 TAG_WM, "**** NO NEED TO START: " + attrs.getTitle());
1971 return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
1973 } else if (type == TYPE_INPUT_METHOD) {
1974 if (token.windowType != TYPE_INPUT_METHOD) {
1975 Slog.w(TAG_WM, "Attempted to add input method window with bad token "
1976 + attrs.token + ". Aborting.");
1977 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1979 } else if (type == TYPE_VOICE_INTERACTION) {
1980 if (token.windowType != TYPE_VOICE_INTERACTION) {
1981 Slog.w(TAG_WM, "Attempted to add voice interaction window with bad token "
1982 + attrs.token + ". Aborting.");
1983 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1985 } else if (type == TYPE_WALLPAPER) {
1986 if (token.windowType != TYPE_WALLPAPER) {
1987 Slog.w(TAG_WM, "Attempted to add wallpaper window with bad token "
1988 + attrs.token + ". Aborting.");
1989 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1991 } else if (type == TYPE_DREAM) {
1992 if (token.windowType != TYPE_DREAM) {
1993 Slog.w(TAG_WM, "Attempted to add Dream window with bad token "
1994 + attrs.token + ". Aborting.");
1995 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1997 } else if (type == TYPE_ACCESSIBILITY_OVERLAY) {
1998 if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
1999 Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with bad token "
2000 + attrs.token + ". Aborting.");
2001 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2003 } else if (type == TYPE_QS_DIALOG) {
2004 if (token.windowType != TYPE_QS_DIALOG) {
2005 Slog.w(TAG_WM, "Attempted to add QS dialog window with bad token "
2006 + attrs.token + ". Aborting.");
2007 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2009 } else if (token.appWindowToken != null) {
2010 Slog.w(TAG_WM, "Non-null appWindowToken for system window of type=" + type);
2011 // It is not valid to use an app token with other system types; we will
2012 // instead make a new token for it (as if null had been passed in for the token).
2014 token = new WindowToken(this, null, -1, false);
2018 WindowState win = new WindowState(this, session, client, token,
2019 attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
2020 if (win.mDeathRecipient == null) {
2021 // Client has apparently died, so there is no reason to
2023 Slog.w(TAG_WM, "Adding window client " + client.asBinder()
2024 + " that is dead, aborting.");
2025 return WindowManagerGlobal.ADD_APP_EXITING;
2028 if (win.getDisplayContent() == null) {
2029 Slog.w(TAG_WM, "Adding window to Display that has been removed.");
2030 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
2033 mPolicy.adjustWindowParamsLw(win.mAttrs);
2034 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
2036 res = mPolicy.prepareAddWindowLw(win, attrs);
2037 if (res != WindowManagerGlobal.ADD_OKAY) {
2041 final boolean openInputChannels = (outInputChannel != null
2042 && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
2043 if (openInputChannels) {
2044 win.openInputChannel(outInputChannel);
2047 // From now on, no exceptions or errors allowed!
2049 res = WindowManagerGlobal.ADD_OKAY;
2051 if (excludeWindowTypeFromTapOutTask(type)) {
2052 displayContent.mTapExcludedWindows.add(win);
2055 origId = Binder.clearCallingIdentity();
2058 mTokenMap.put(attrs.token, token);
2061 mWindowMap.put(client.asBinder(), win);
2062 if (win.mAppOp != AppOpsManager.OP_NONE) {
2063 int startOpResult = mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(),
2064 win.getOwningPackage());
2065 if ((startOpResult != AppOpsManager.MODE_ALLOWED) &&
2066 (startOpResult != AppOpsManager.MODE_DEFAULT)) {
2067 win.setAppOpVisibilityLw(false);
2071 if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) {
2072 token.appWindowToken.startingWindow = win;
2073 if (DEBUG_STARTING_WINDOW) Slog.v (TAG_WM, "addWindow: " + token.appWindowToken
2074 + " startingWindow=" + win);
2077 boolean imMayMove = true;
2079 if (type == TYPE_INPUT_METHOD) {
2080 win.mGivenInsetsPending = true;
2081 mInputMethodWindow = win;
2082 addInputMethodWindowToListLocked(win);
2084 } else if (type == TYPE_INPUT_METHOD_DIALOG) {
2085 mInputMethodDialogs.add(win);
2086 addWindowToListInOrderLocked(win, true);
2087 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
2090 addWindowToListInOrderLocked(win, true);
2091 if (type == TYPE_WALLPAPER) {
2092 mWallpaperControllerLocked.clearLastWallpaperTimeoutTime();
2093 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2094 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2095 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2096 } else if (mWallpaperControllerLocked.isBelowWallpaperTarget(win)) {
2097 // If there is currently a wallpaper being shown, and
2098 // the base layer of the new window is below the current
2099 // layer of the target window, then adjust the wallpaper.
2100 // This is to avoid a new window being placed between the
2101 // wallpaper and its target.
2102 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2106 // If the window is being added to a task that's docked but non-resizeable,
2107 // we need to update this new window's scroll position when it's added.
2108 win.applyScrollIfNeeded();
2110 // If the window is being added to a stack that's currently adjusted for IME,
2111 // make sure to apply the same adjust to this new window.
2112 win.applyAdjustForImeIfNeeded();
2114 if (type == TYPE_DOCK_DIVIDER) {
2115 getDefaultDisplayContentLocked().getDockedDividerController().setWindow(win);
2118 final WindowStateAnimator winAnimator = win.mWinAnimator;
2119 winAnimator.mEnterAnimationPending = true;
2120 winAnimator.mEnteringAnimation = true;
2121 // Check if we need to prepare a transition for replacing window first.
2122 if (atoken != null && !prepareWindowReplacementTransition(atoken)) {
2123 // If not, check if need to set up a dummy transition during display freeze
2124 // so that the unfreeze wait for the apps to draw. This might be needed if
2125 // the app is relaunching.
2126 prepareNoneTransitionForRelaunching(atoken);
2129 if (displayContent.isDefaultDisplay) {
2130 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2131 final Rect taskBounds;
2132 if (atoken != null && atoken.mTask != null) {
2133 taskBounds = mTmpRect;
2134 atoken.mTask.getBounds(mTmpRect);
2138 if (mPolicy.getInsetHintLw(win.mAttrs, taskBounds, mRotation,
2139 displayInfo.logicalWidth, displayInfo.logicalHeight, outContentInsets,
2140 outStableInsets, outOutsets)) {
2141 res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR;
2144 outContentInsets.setEmpty();
2145 outStableInsets.setEmpty();
2149 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
2151 if (win.mAppToken == null || !win.mAppToken.clientHidden) {
2152 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
2155 mInputMonitor.setUpdateInputWindowsNeededLw();
2157 boolean focusChanged = false;
2158 if (win.canReceiveKeys()) {
2159 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
2160 false /*updateInputWindows*/);
2167 moveInputMethodWindowsIfNeededLocked(false);
2170 mLayersController.assignLayersLocked(displayContent.getWindowList());
2171 // Don't do layout here, the window must call
2172 // relayout to be displayed, so we'll do it there.
2175 mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
2177 mInputMonitor.updateInputWindowsLw(false /*force*/);
2179 if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client "
2180 + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5));
2182 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
2183 reportNewConfig = true;
2185 if (attrs.removeTimeoutMilliseconds > 0) {
2186 mH.sendMessageDelayed(
2187 mH.obtainMessage(H.WINDOW_REMOVE_TIMEOUT, win),
2188 attrs.removeTimeoutMilliseconds);
2192 if (reportNewConfig) {
2193 sendNewConfiguration();
2196 Binder.restoreCallingIdentity(origId);
2202 * Returns true if we're done setting up any transitions.
2204 private boolean prepareWindowReplacementTransition(AppWindowToken atoken) {
2205 atoken.clearAllDrawn();
2206 WindowState replacedWindow = null;
2207 for (int i = atoken.windows.size() - 1; i >= 0 && replacedWindow == null; i--) {
2208 WindowState candidate = atoken.windows.get(i);
2209 if (candidate.mAnimatingExit && candidate.mWillReplaceWindow
2210 && candidate.mAnimateReplacingWindow) {
2211 replacedWindow = candidate;
2214 if (replacedWindow == null) {
2215 // We expect to already receive a request to remove the old window. If it did not
2216 // happen, let's just simply add a window.
2219 // We use the visible frame, because we want the animation to morph the window from what
2220 // was visible to the user to the final destination of the new window.
2221 Rect frame = replacedWindow.mVisibleFrame;
2222 // We treat this as if this activity was opening, so we can trigger the app transition
2223 // animation and piggy-back on existing transition animation infrastructure.
2224 mOpeningApps.add(atoken);
2225 prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_RELAUNCH, ALWAYS_KEEP_CURRENT);
2226 mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top,
2227 frame.width(), frame.height());
2228 executeAppTransition();
2232 private void prepareNoneTransitionForRelaunching(AppWindowToken atoken) {
2233 // Set up a none-transition and add the app to opening apps, so that the display
2234 // unfreeze wait for the apps to be drawn.
2235 // Note that if the display unfroze already because app unfreeze timed out,
2236 // we don't set up the transition anymore and just let it go.
2237 if (mDisplayFrozen && !mOpeningApps.contains(atoken) && atoken.isRelaunching()) {
2238 mOpeningApps.add(atoken);
2239 prepareAppTransition(AppTransition.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT);
2240 executeAppTransition();
2245 * Returns whether screen capture is disabled for all windows of a specific user.
2247 boolean isScreenCaptureDisabledLocked(int userId) {
2248 Boolean disabled = mScreenCaptureDisabled.get(userId);
2249 if (disabled == null) {
2255 boolean isSecureLocked(WindowState w) {
2256 if ((w.mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
2259 if (isScreenCaptureDisabledLocked(UserHandle.getUserId(w.mOwnerUid))) {
2266 * Set mScreenCaptureDisabled for specific user
2269 public void setScreenCaptureDisabled(int userId, boolean disabled) {
2270 int callingUid = Binder.getCallingUid();
2271 if (callingUid != Process.SYSTEM_UID) {
2272 throw new SecurityException("Only system can call setScreenCaptureDisabled.");
2275 synchronized(mWindowMap) {
2276 mScreenCaptureDisabled.put(userId, disabled);
2277 // Update secure surface for all windows belonging to this user.
2278 for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
2279 WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
2280 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
2281 final WindowState win = windows.get(winNdx);
2282 if (win.mHasSurface && userId == UserHandle.getUserId(win.mOwnerUid)) {
2283 win.mWinAnimator.setSecureLocked(disabled);
2290 private void setupWindowForRemoveOnExit(WindowState win) {
2291 win.mRemoveOnExit = true;
2292 win.setDisplayLayoutNeeded();
2293 // Request a focus update as this window's input channel is already gone. Otherwise
2294 // we could have no focused window in input manager.
2295 final boolean focusChanged = updateFocusedWindowLocked(
2296 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
2297 mWindowPlacerLocked.performSurfacePlacement();
2299 mInputMonitor.updateInputWindowsLw(false /*force*/);
2303 public void removeWindow(Session session, IWindow client) {
2304 synchronized(mWindowMap) {
2305 WindowState win = windowForClientLocked(session, client, false);
2309 removeWindowLocked(win);
2313 void removeWindowLocked(WindowState win) {
2314 removeWindowLocked(win, false);
2317 void removeWindowLocked(WindowState win, boolean keepVisibleDeadWindow) {
2318 win.mWindowRemovalAllowed = true;
2319 if (DEBUG_ADD_REMOVE) Slog.v(TAG,
2320 "removeWindowLocked: " + win + " callers=" + Debug.getCallers(4));
2322 final boolean startingWindow = win.mAttrs.type == TYPE_APPLICATION_STARTING;
2323 if (startingWindow) {
2324 if (DEBUG_STARTING_WINDOW) Slog.d(TAG_WM, "Starting window removed " + win);
2327 if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win == mCurrentFocus) Slog.v(
2328 TAG_WM, "Remove " + win + " client="
2329 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder()))
2330 + ", surfaceController=" + win.mWinAnimator.mSurfaceController + " Callers="
2331 + Debug.getCallers(4));
2333 final long origId = Binder.clearCallingIdentity();
2335 win.disposeInputChannel();
2337 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
2338 "Remove " + win + ": mSurfaceController=" + win.mWinAnimator.mSurfaceController
2339 + " mAnimatingExit=" + win.mAnimatingExit
2340 + " mRemoveOnExit=" + win.mRemoveOnExit
2341 + " mHasSurface=" + win.mHasSurface
2342 + " surfaceShowing=" + win.mWinAnimator.getShown()
2343 + " isAnimationSet=" + win.mWinAnimator.isAnimationSet()
2345 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null)
2346 + " mWillReplaceWindow=" + win.mWillReplaceWindow
2347 + " inPendingTransaction="
2348 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
2349 + " mDisplayFrozen=" + mDisplayFrozen
2350 + " callers=" + Debug.getCallers(6));
2351 // Visibility of the removed window. Will be used later to update orientation later on.
2352 boolean wasVisible = false;
2353 // First, see if we need to run an animation. If we do, we have to hold off on removing the
2354 // window until the animation is done. If the display is frozen, just remove immediately,
2355 // since the animation wouldn't be seen.
2356 if (win.mHasSurface && okToDisplay()) {
2357 final AppWindowToken appToken = win.mAppToken;
2358 if (win.mWillReplaceWindow) {
2359 // This window is going to be replaced. We need to keep it around until the new one
2360 // gets added, then we will get rid of this one.
2361 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Preserving " + win + " until the new one is "
2363 // TODO: We are overloading mAnimatingExit flag to prevent the window state from
2364 // been removed. We probably need another flag to indicate that window removal
2365 // should be deffered vs. overloading the flag that says we are playing an exit
2367 win.mAnimatingExit = true;
2368 win.mReplacingRemoveRequested = true;
2369 Binder.restoreCallingIdentity(origId);
2373 if (win.isAnimatingWithSavedSurface() && !appToken.allDrawnExcludingSaved) {
2374 // We started enter animation early with a saved surface, now the app asks to remove
2375 // this window. If we remove it now and the app is not yet drawn, we'll show a
2376 // flicker. Delay the removal now until it's really drawn.
2377 if (DEBUG_ADD_REMOVE) {
2378 Slog.d(TAG_WM, "removeWindowLocked: delay removal of " + win
2379 + " due to early animation");
2381 // Do not set mAnimatingExit to true here, it will cause the surface to be hidden
2382 // immediately after the enter animation is done. If the app is not yet drawn then
2383 // it will show up as a flicker.
2384 setupWindowForRemoveOnExit(win);
2385 Binder.restoreCallingIdentity(origId);
2388 // If we are not currently running the exit animation, we need to see about starting one
2389 wasVisible = win.isWinVisibleLw();
2391 if (keepVisibleDeadWindow) {
2392 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
2393 "Not removing " + win + " because app died while it's visible");
2395 win.mAppDied = true;
2396 win.setDisplayLayoutNeeded();
2397 mWindowPlacerLocked.performSurfacePlacement();
2399 // Set up a replacement input channel since the app is now dead.
2400 // We need to catch tapping on the dead window to restart the app.
2401 win.openInputChannel(null);
2402 mInputMonitor.updateInputWindowsLw(true /*force*/);
2404 Binder.restoreCallingIdentity(origId);
2408 final WindowStateAnimator winAnimator = win.mWinAnimator;
2410 final int transit = (!startingWindow) ? TRANSIT_EXIT : TRANSIT_PREVIEW_DONE;
2412 // Try starting an animation.
2413 if (winAnimator.applyAnimationLocked(transit, false)) {
2414 win.mAnimatingExit = true;
2416 //TODO (multidisplay): Magnification is supported only for the default display.
2417 if (mAccessibilityController != null
2418 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
2419 mAccessibilityController.onWindowTransitionLocked(win, transit);
2422 final boolean isAnimating =
2423 winAnimator.isAnimationSet() && !winAnimator.isDummyAnimation();
2424 final boolean lastWindowIsStartingWindow = startingWindow && appToken != null
2425 && appToken.allAppWindows.size() == 1;
2426 // We delay the removal of a window if it has a showing surface that can be used to run
2427 // exit animation and it is marked as exiting.
2428 // Also, If isn't the an animating starting window that is the last window in the app.
2429 // We allow the removal of the non-animating starting window now as there is no
2430 // additional window or animation that will trigger its removal.
2431 if (winAnimator.getShown() && win.mAnimatingExit
2432 && (!lastWindowIsStartingWindow || isAnimating)) {
2433 // The exit animation is running or should run... wait for it!
2434 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
2435 "Not removing " + win + " due to exit animation ");
2436 setupWindowForRemoveOnExit(win);
2437 if (appToken != null) {
2438 appToken.updateReportedVisibilityLocked();
2440 Binder.restoreCallingIdentity(origId);
2445 removeWindowInnerLocked(win);
2446 // Removing a visible window will effect the computed orientation
2447 // So just update orientation if needed.
2448 if (wasVisible && updateOrientationFromAppTokensLocked(false)) {
2449 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
2451 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
2452 Binder.restoreCallingIdentity(origId);
2455 void removeWindowInnerLocked(WindowState win) {
2458 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
2459 "removeWindowInnerLocked: " + win + " Already removed...");
2463 for (int i = win.mChildWindows.size() - 1; i >= 0; i--) {
2464 WindowState cwin = win.mChildWindows.get(i);
2465 Slog.w(TAG_WM, "Force-removing child win " + cwin + " from container " + win);
2466 removeWindowInnerLocked(cwin);
2469 win.mRemoved = true;
2471 if (mInputMethodTarget == win) {
2472 moveInputMethodWindowsIfNeededLocked(false);
2476 RuntimeException e = new RuntimeException("here");
2477 e.fillInStackTrace();
2478 Slog.w(TAG_WM, "Removing window " + win, e);
2481 final int type = win.mAttrs.type;
2482 if (excludeWindowTypeFromTapOutTask(type)) {
2483 final DisplayContent displaycontent = win.getDisplayContent();
2484 displaycontent.mTapExcludedWindows.remove(win);
2486 mPolicy.removeWindowLw(win);
2489 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "removeWindowInnerLocked: " + win);
2490 mWindowMap.remove(win.mClient.asBinder());
2491 if (win.mAppOp != AppOpsManager.OP_NONE) {
2492 mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
2495 mPendingRemove.remove(win);
2496 mResizingWindows.remove(win);
2497 mWindowsChanged = true;
2498 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Final remove of window: " + win);
2500 if (mInputMethodWindow == win) {
2501 mInputMethodWindow = null;
2502 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
2503 mInputMethodDialogs.remove(win);
2506 final WindowToken token = win.mToken;
2507 final AppWindowToken atoken = win.mAppToken;
2508 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Removing " + win + " from " + token);
2509 token.windows.remove(win);
2510 if (atoken != null) {
2511 atoken.allAppWindows.remove(win);
2513 if (localLOGV) Slog.v(
2514 TAG_WM, "**** Removing window " + win + ": count="
2515 + token.windows.size());
2516 if (token.windows.size() == 0) {
2517 if (!token.explicit) {
2518 mTokenMap.remove(token.token);
2519 } else if (atoken != null) {
2520 atoken.firstWindowDrawn = false;
2521 atoken.clearAllDrawn();
2525 if (atoken != null) {
2526 if (atoken.startingWindow == win) {
2527 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
2528 scheduleRemoveStartingWindowLocked(atoken);
2530 if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
2531 // If this is the last window and we had requested a starting
2532 // transition window, well there is no point now.
2533 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingWindow");
2534 atoken.startingData = null;
2535 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
2536 // If this is the last window except for a starting transition
2537 // window, we need to get rid of the starting transition.
2538 scheduleRemoveStartingWindowLocked(atoken);
2542 if (type == TYPE_WALLPAPER) {
2543 mWallpaperControllerLocked.clearLastWallpaperTimeoutTime();
2544 getDefaultDisplayContentLocked().pendingLayoutChanges |=
2545 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2546 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2547 getDefaultDisplayContentLocked().pendingLayoutChanges |=
2548 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2551 final WindowList windows = win.getWindowList();
2552 if (windows != null) {
2553 windows.remove(win);
2554 if (!mWindowPlacerLocked.isInLayout()) {
2555 mLayersController.assignLayersLocked(windows);
2556 win.setDisplayLayoutNeeded();
2557 mWindowPlacerLocked.performSurfacePlacement();
2558 if (win.mAppToken != null) {
2559 win.mAppToken.updateReportedVisibilityLocked();
2564 mInputMonitor.updateInputWindowsLw(true /*force*/);
2567 public void updateAppOpsState() {
2568 synchronized(mWindowMap) {
2569 final int numDisplays = mDisplayContents.size();
2570 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
2571 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
2572 final int numWindows = windows.size();
2573 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
2574 final WindowState win = windows.get(winNdx);
2575 if (win.mAppOp != AppOpsManager.OP_NONE) {
2576 final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
2577 win.getOwningPackage());
2578 win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED ||
2579 mode == AppOpsManager.MODE_DEFAULT);
2586 static void logSurface(WindowState w, String msg, boolean withStackTrace) {
2587 String str = " SURFACE " + msg + ": " + w;
2588 if (withStackTrace) {
2589 logWithStack(TAG, str);
2591 Slog.i(TAG_WM, str);
2595 static void logSurface(SurfaceControl s, String title, String msg) {
2596 String str = " SURFACE " + s + ": " + msg + " / " + title;
2597 Slog.i(TAG_WM, str);
2600 static void logWithStack(String tag, String s) {
2601 RuntimeException e = null;
2602 if (SHOW_STACK_CRAWLS) {
2603 e = new RuntimeException();
2604 e.fillInStackTrace();
2609 void setTransparentRegionWindow(Session session, IWindow client, Region region) {
2610 long origId = Binder.clearCallingIdentity();
2612 synchronized (mWindowMap) {
2613 WindowState w = windowForClientLocked(session, client, false);
2614 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
2615 "transparentRegionHint=" + region, false);
2617 if ((w != null) && w.mHasSurface) {
2618 w.mWinAnimator.setTransparentRegionHintLocked(region);
2622 Binder.restoreCallingIdentity(origId);
2626 void setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets,
2627 Rect visibleInsets, Region touchableRegion) {
2628 long origId = Binder.clearCallingIdentity();
2630 synchronized (mWindowMap) {
2631 WindowState w = windowForClientLocked(session, client, false);
2632 if (DEBUG_LAYOUT) Slog.d(TAG, "setInsetsWindow " + w
2633 + ", contentInsets=" + w.mGivenContentInsets + " -> " + contentInsets
2634 + ", visibleInsets=" + w.mGivenVisibleInsets + " -> " + visibleInsets
2635 + ", touchableRegion=" + w.mGivenTouchableRegion + " -> " + touchableRegion
2636 + ", touchableInsets " + w.mTouchableInsets + " -> " + touchableInsets);
2638 w.mGivenInsetsPending = false;
2639 w.mGivenContentInsets.set(contentInsets);
2640 w.mGivenVisibleInsets.set(visibleInsets);
2641 w.mGivenTouchableRegion.set(touchableRegion);
2642 w.mTouchableInsets = touchableInsets;
2643 if (w.mGlobalScale != 1) {
2644 w.mGivenContentInsets.scale(w.mGlobalScale);
2645 w.mGivenVisibleInsets.scale(w.mGlobalScale);
2646 w.mGivenTouchableRegion.scale(w.mGlobalScale);
2648 w.setDisplayLayoutNeeded();
2649 mWindowPlacerLocked.performSurfacePlacement();
2653 Binder.restoreCallingIdentity(origId);
2657 public void getWindowDisplayFrame(Session session, IWindow client,
2658 Rect outDisplayFrame) {
2659 synchronized(mWindowMap) {
2660 WindowState win = windowForClientLocked(session, client, false);
2662 outDisplayFrame.setEmpty();
2665 outDisplayFrame.set(win.mDisplayFrame);
2669 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
2670 synchronized (mWindowMap) {
2671 if (mAccessibilityController != null) {
2672 WindowState window = mWindowMap.get(token);
2673 //TODO (multidisplay): Magnification is supported only for the default display.
2674 if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
2675 mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle);
2681 public IWindowId getWindowId(IBinder token) {
2682 synchronized (mWindowMap) {
2683 WindowState window = mWindowMap.get(token);
2684 return window != null ? window.mWindowId : null;
2688 public void pokeDrawLock(Session session, IBinder token) {
2689 synchronized (mWindowMap) {
2690 WindowState window = windowForClientLocked(session, token, false);
2691 if (window != null) {
2692 window.pokeDrawLockLw(mDrawLockTimeoutMillis);
2697 void repositionChild(Session session, IWindow client,
2698 int left, int top, int right, int bottom,
2699 long frameNumber, Rect outFrame) {
2700 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "repositionChild");
2701 long origId = Binder.clearCallingIdentity();
2704 synchronized(mWindowMap) {
2705 WindowState win = windowForClientLocked(session, client, false);
2709 if (win.mAttachedWindow == null) {
2710 throw new IllegalArgumentException(
2711 "repositionChild called but window is not"
2712 + "attached to a parent win=" + win);
2715 win.mAttrs.x = left;
2717 win.mAttrs.width = right - left;
2718 win.mAttrs.height = bottom - top;
2719 win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
2721 if (win.mHasSurface) {
2722 if (SHOW_TRANSACTIONS) {
2723 Slog.i(TAG_WM, ">>> OPEN TRANSACTION repositionChild");
2726 SurfaceControl.openTransaction();
2730 win.applyGravityAndUpdateFrame(win.mContainingFrame, win.mDisplayFrame);
2731 win.mWinAnimator.computeShownFrameLocked();
2733 win.mWinAnimator.setSurfaceBoundariesLocked(false);
2735 if (frameNumber > 0) {
2736 win.mWinAnimator.deferTransactionUntilParentFrame(frameNumber);
2740 SurfaceControl.closeTransaction();
2741 if (SHOW_TRANSACTIONS) {
2742 Slog.i(TAG_WM, "<<< CLOSE TRANSACTION repositionChild");
2747 outFrame = win.mCompatFrame;
2750 Binder.restoreCallingIdentity(origId);
2751 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
2755 public int relayoutWindow(Session session, IWindow client, int seq,
2756 WindowManager.LayoutParams attrs, int requestedWidth,
2757 int requestedHeight, int viewVisibility, int flags,
2758 Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
2759 Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
2760 Configuration outConfig, Surface outSurface) {
2762 boolean configChanged;
2763 boolean hasStatusBarPermission =
2764 mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
2765 == PackageManager.PERMISSION_GRANTED;
2767 long origId = Binder.clearCallingIdentity();
2768 synchronized(mWindowMap) {
2769 WindowState win = windowForClientLocked(session, client, false);
2774 WindowStateAnimator winAnimator = win.mWinAnimator;
2775 if (viewVisibility != View.GONE) {
2776 win.setRequestedSize(requestedWidth, requestedHeight);
2779 int attrChanges = 0;
2780 int flagChanges = 0;
2781 if (attrs != null) {
2782 mPolicy.adjustWindowParamsLw(attrs);
2783 // if they don't have the permission, mask out the status bar bits
2784 if (seq == win.mSeq) {
2785 int systemUiVisibility = attrs.systemUiVisibility
2786 | attrs.subtreeSystemUiVisibility;
2787 if ((systemUiVisibility & DISABLE_MASK) != 0) {
2788 if (!hasStatusBarPermission) {
2789 systemUiVisibility &= ~DISABLE_MASK;
2792 win.mSystemUiVisibility = systemUiVisibility;
2794 if (win.mAttrs.type != attrs.type) {
2795 throw new IllegalArgumentException(
2796 "Window type can not be changed after the window is added.");
2799 // Odd choice but less odd than embedding in copyFrom()
2800 if ((attrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY)
2802 attrs.x = win.mAttrs.x;
2803 attrs.y = win.mAttrs.y;
2804 attrs.width = win.mAttrs.width;
2805 attrs.height = win.mAttrs.height;
2808 flagChanges = win.mAttrs.flags ^= attrs.flags;
2809 attrChanges = win.mAttrs.copyFrom(attrs);
2810 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
2811 | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
2812 win.mLayoutNeeded = true;
2816 if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility
2817 + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
2818 winAnimator.mSurfaceDestroyDeferred = (flags & RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
2819 win.mEnforceSizeCompat =
2820 (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
2821 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2822 winAnimator.mAlpha = attrs.alpha;
2824 win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
2826 if (win.mAttrs.surfaceInsets.left != 0
2827 || win.mAttrs.surfaceInsets.top != 0
2828 || win.mAttrs.surfaceInsets.right != 0
2829 || win.mAttrs.surfaceInsets.bottom != 0) {
2830 winAnimator.setOpaqueLocked(false);
2833 boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
2834 final boolean isDefaultDisplay = win.isDefaultDisplay();
2835 boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
2836 || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
2837 || (!win.mRelayoutCalled));
2839 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2840 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
2841 wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
2842 if ((flagChanges & FLAG_SECURE) != 0 && winAnimator.mSurfaceController != null) {
2843 winAnimator.mSurfaceController.setSecure(isSecureLocked(win));
2846 win.mRelayoutCalled = true;
2847 win.mInRelayout = true;
2849 final int oldVisibility = win.mViewVisibility;
2850 win.mViewVisibility = viewVisibility;
2851 if (DEBUG_SCREEN_ON) {
2852 RuntimeException stack = new RuntimeException();
2853 stack.fillInStackTrace();
2854 Slog.i(TAG_WM, "Relayout " + win + ": oldVis=" + oldVisibility
2855 + " newVis=" + viewVisibility, stack);
2857 if (viewVisibility == View.VISIBLE &&
2858 (win.mAppToken == null || !win.mAppToken.clientHidden)) {
2859 result = relayoutVisibleWindow(outConfig, result, win, winAnimator, attrChanges,
2862 result = createSurfaceControl(outSurface, result, win, winAnimator);
2863 } catch (Exception e) {
2864 mInputMonitor.updateInputWindowsLw(true /*force*/);
2866 Slog.w(TAG_WM, "Exception thrown when creating surface for client "
2867 + client + " (" + win.mAttrs.getTitle() + ")",
2869 Binder.restoreCallingIdentity(origId);
2872 if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
2873 focusMayChange = isDefaultDisplay;
2875 if (win.mAttrs.type == TYPE_INPUT_METHOD && mInputMethodWindow == null) {
2876 mInputMethodWindow = win;
2879 win.adjustStartingWindowFlags();
2881 winAnimator.mEnterAnimationPending = false;
2882 winAnimator.mEnteringAnimation = false;
2883 final boolean usingSavedSurfaceBeforeVisible =
2884 oldVisibility != View.VISIBLE && win.isAnimatingWithSavedSurface();
2885 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
2886 if (winAnimator.hasSurface() && !win.mAnimatingExit
2887 && usingSavedSurfaceBeforeVisible) {
2888 Slog.d(TAG, "Ignoring layout to invisible when using saved surface " + win);
2892 if (winAnimator.hasSurface() && !win.mAnimatingExit
2893 && !usingSavedSurfaceBeforeVisible) {
2894 if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Relayout invis " + win
2895 + ": mAnimatingExit=" + win.mAnimatingExit);
2896 // If we are not currently running the exit animation, we
2897 // need to see about starting one.
2898 // We don't want to animate visibility of windows which are pending
2899 // replacement. In the case of activity relaunch child windows
2900 // could request visibility changes as they are detached from the main
2901 // application window during the tear down process. If we satisfied
2902 // these visibility changes though, we would cause a visual glitch
2903 // hiding the window before it's replacement was available.
2904 // So we just do nothing on our side.
2905 if (!win.mWillReplaceWindow) {
2906 focusMayChange = tryStartExitingAnimation(
2907 win, winAnimator, isDefaultDisplay, focusMayChange);
2909 result |= RELAYOUT_RES_SURFACE_CHANGED;
2911 final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
2912 if (viewVisibility == View.VISIBLE && surfaceController != null) {
2913 // We already told the client to go invisible, but the message may not be
2914 // handled yet, or it might want to draw a last frame. If we already have a
2915 // surface, let the client use that, but don't create new surface at this point.
2916 surfaceController.getSurface(outSurface);
2918 if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win);
2921 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmReleaseOutSurface_"
2922 + win.mAttrs.getTitle());
2923 outSurface.release();
2925 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
2930 if (focusMayChange) {
2931 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
2932 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
2933 false /*updateInputWindows*/)) {
2936 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
2939 // updateFocusedWindowLocked() already assigned layers so we only need to
2940 // reassign them at this point if the IM window state gets shuffled
2941 boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
2942 if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) {
2943 // Little hack here -- we -should- be able to rely on the
2944 // function to return true if the IME has moved and needs
2945 // its layer recomputed. However, if the IME was hidden
2946 // and isn't actually moved in the list, its layer may be
2947 // out of data so we make sure to recompute it.
2948 mLayersController.assignLayersLocked(win.getWindowList());
2951 if (wallpaperMayMove) {
2952 getDefaultDisplayContentLocked().pendingLayoutChanges |=
2953 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2956 win.setDisplayLayoutNeeded();
2957 win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
2958 configChanged = updateOrientationFromAppTokensLocked(false);
2959 mWindowPlacerLocked.performSurfacePlacement();
2960 if (toBeDisplayed && win.mIsWallpaper) {
2961 DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
2962 mWallpaperControllerLocked.updateWallpaperOffset(
2963 win, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
2965 if (win.mAppToken != null) {
2966 win.mAppToken.updateReportedVisibilityLocked();
2968 if (winAnimator.mReportSurfaceResized) {
2969 winAnimator.mReportSurfaceResized = false;
2970 result |= WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED;
2972 if (mPolicy.isNavBarForcedShownLw(win)) {
2973 result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR;
2975 if (!win.isGoneForLayoutLw()) {
2976 win.mResizedWhileGone = false;
2978 outFrame.set(win.mCompatFrame);
2979 outOverscanInsets.set(win.mOverscanInsets);
2980 outContentInsets.set(win.mContentInsets);
2981 outVisibleInsets.set(win.mVisibleInsets);
2982 outStableInsets.set(win.mStableInsets);
2983 outOutsets.set(win.mOutsets);
2984 outBackdropFrame.set(win.getBackdropFrame(win.mFrame));
2985 if (localLOGV) Slog.v(
2986 TAG_WM, "Relayout given client " + client.asBinder()
2987 + ", requestedWidth=" + requestedWidth
2988 + ", requestedHeight=" + requestedHeight
2989 + ", viewVisibility=" + viewVisibility
2990 + "\nRelayout returning frame=" + outFrame
2991 + ", surface=" + outSurface);
2993 if (localLOGV || DEBUG_FOCUS) Slog.v(
2994 TAG_WM, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
2996 result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0;
2998 mInputMonitor.updateInputWindowsLw(true /*force*/);
3001 Slog.v(TAG_WM, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
3003 win.mInRelayout = false;
3006 if (configChanged) {
3007 sendNewConfiguration();
3009 Binder.restoreCallingIdentity(origId);
3013 private boolean tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator,
3014 boolean isDefaultDisplay, boolean focusMayChange) {
3015 // Try starting an animation; if there isn't one, we
3016 // can destroy the surface right away.
3017 int transit = WindowManagerPolicy.TRANSIT_EXIT;
3018 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
3019 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
3021 if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) {
3022 focusMayChange = isDefaultDisplay;
3023 win.mAnimatingExit = true;
3024 win.mWinAnimator.mAnimating = true;
3025 } else if (win.mWinAnimator.isAnimationSet()) {
3026 // Currently in a hide animation... turn this into
3028 win.mAnimatingExit = true;
3029 win.mWinAnimator.mAnimating = true;
3030 } else if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
3031 // If the wallpaper is currently behind this
3032 // window, we need to change both of them inside
3033 // of a transaction to avoid artifacts.
3034 win.mAnimatingExit = true;
3035 win.mWinAnimator.mAnimating = true;
3037 if (mInputMethodWindow == win) {
3038 mInputMethodWindow = null;
3040 win.destroyOrSaveSurface();
3042 //TODO (multidisplay): Magnification is supported only for the default
3043 if (mAccessibilityController != null
3044 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
3045 mAccessibilityController.onWindowTransitionLocked(win, transit);
3047 return focusMayChange;
3050 private int createSurfaceControl(Surface outSurface, int result, WindowState win,
3051 WindowStateAnimator winAnimator) {
3052 if (!win.mHasSurface) {
3053 result |= RELAYOUT_RES_SURFACE_CHANGED;
3055 WindowSurfaceController surfaceController = winAnimator.createSurfaceLocked();
3056 if (surfaceController != null) {
3057 surfaceController.getSurface(outSurface);
3058 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " OUT SURFACE " + outSurface + ": copied");
3060 // For some reason there isn't a surface. Clear the
3061 // caller's object so they see the same state.
3062 Slog.w(TAG_WM, "Failed to create surface control for " + win);
3063 outSurface.release();
3068 private int relayoutVisibleWindow(Configuration outConfig, int result, WindowState win,
3069 WindowStateAnimator winAnimator, int attrChanges, int oldVisibility) {
3070 result |= !win.isVisibleLw() ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0;
3071 if (win.mAnimatingExit) {
3072 Slog.d(TAG, "relayoutVisibleWindow: " + win + " mAnimatingExit=true, mRemoveOnExit="
3073 + win.mRemoveOnExit + ", mDestroying=" + win.mDestroying);
3075 winAnimator.cancelExitAnimationForNextAnimationLocked();
3076 win.mAnimatingExit = false;
3078 if (win.mDestroying) {
3079 win.mDestroying = false;
3080 mDestroySurface.remove(win);
3082 if (oldVisibility == View.GONE) {
3083 winAnimator.mEnterAnimationPending = true;
3086 win.mLastVisibleLayoutRotation = mRotation;
3088 winAnimator.mEnteringAnimation = true;
3089 if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
3090 win.prepareWindowToDisplayDuringRelayout(outConfig);
3092 if ((attrChanges & LayoutParams.FORMAT_CHANGED) != 0) {
3093 // If the format can't be changed in place, preserve the old surface until the app draws
3094 // on the new one. This prevents blinking when we change elevation of freeform and
3096 if (!winAnimator.tryChangeFormatInPlaceLocked()) {
3097 winAnimator.preserveSurfaceLocked();
3098 result |= RELAYOUT_RES_SURFACE_CHANGED
3099 | WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
3103 // If we're starting a drag-resize, we'll be changing the surface size as well as
3104 // notifying the client to render to with an offset from the surface's top-left.
3105 if (win.isDragResizeChanged() || win.isResizedWhileNotDragResizing()) {
3106 win.setDragResizing();
3107 win.setResizedWhileNotDragResizing(false);
3108 // We can only change top level windows to the full-screen surface when
3109 // resizing (as we only have one full-screen surface). So there is no need
3110 // to preserve and destroy windows which are attached to another, they
3111 // will keep their surface and its size may change over time.
3112 if (win.mHasSurface && win.mAttachedWindow == null) {
3113 winAnimator.preserveSurfaceLocked();
3114 result |= WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
3117 final boolean freeformResizing = win.isDragResizing()
3118 && win.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
3119 final boolean dockedResizing = win.isDragResizing()
3120 && win.getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER;
3121 result |= freeformResizing ? WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM : 0;
3122 result |= dockedResizing ? WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED : 0;
3123 if (win.isAnimatingWithSavedSurface()) {
3124 // If we're animating with a saved surface now, request client to report draw.
3125 // We still need to know when the real thing is drawn.
3126 result |= WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
3131 public void performDeferredDestroyWindow(Session session, IWindow client) {
3132 long origId = Binder.clearCallingIdentity();
3135 synchronized (mWindowMap) {
3136 WindowState win = windowForClientLocked(session, client, false);
3137 if (win == null || win.mWillReplaceWindow) {
3141 win.mWinAnimator.destroyDeferredSurfaceLocked();
3144 Binder.restoreCallingIdentity(origId);
3148 public boolean outOfMemoryWindow(Session session, IWindow client) {
3149 long origId = Binder.clearCallingIdentity();
3152 synchronized (mWindowMap) {
3153 WindowState win = windowForClientLocked(session, client, false);
3157 return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false);
3160 Binder.restoreCallingIdentity(origId);
3164 public void finishDrawingWindow(Session session, IWindow client) {
3165 final long origId = Binder.clearCallingIdentity();
3167 synchronized (mWindowMap) {
3168 WindowState win = windowForClientLocked(session, client, false);
3169 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "finishDrawingWindow: " + win + " mDrawState="
3170 + (win != null ? win.mWinAnimator.drawStateToString() : "null"));
3171 if (win != null && win.mWinAnimator.finishDrawingLocked()) {
3172 if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
3173 getDefaultDisplayContentLocked().pendingLayoutChanges |=
3174 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
3176 win.setDisplayLayoutNeeded();
3177 mWindowPlacerLocked.requestTraversal();
3181 Binder.restoreCallingIdentity(origId);
3185 private boolean applyAnimationLocked(AppWindowToken atoken, WindowManager.LayoutParams lp,
3186 int transit, boolean enter, boolean isVoiceInteraction) {
3187 // Only apply an animation if the display isn't frozen. If it is
3188 // frozen, there is no reason to animate and it can cause strange
3189 // artifacts when we unfreeze the display if some different animation
3191 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked");
3192 if (okToDisplay()) {
3193 DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
3194 final int width = displayInfo.appWidth;
3195 final int height = displayInfo.appHeight;
3196 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
3197 "applyAnimation: atoken=" + atoken);
3199 // Determine the visible rect to calculate the thumbnail clip
3200 final WindowState win = atoken.findMainWindow();
3201 final Rect frame = new Rect(0, 0, width, height);
3202 final Rect displayFrame = new Rect(0, 0,
3203 displayInfo.logicalWidth, displayInfo.logicalHeight);
3204 final Rect insets = new Rect();
3205 Rect surfaceInsets = null;
3206 final boolean freeform = win != null && win.inFreeformWorkspace();
3208 // Containing frame will usually cover the whole screen, including dialog windows.
3209 // For freeform workspace windows it will not cover the whole screen and it also
3210 // won't exactly match the final freeform window frame (e.g. when overlapping with
3211 // the status bar). In that case we need to use the final frame.
3213 frame.set(win.mFrame);
3215 frame.set(win.mContainingFrame);
3217 surfaceInsets = win.getAttrs().surfaceInsets;
3218 insets.set(win.mContentInsets);
3221 if (atoken.mLaunchTaskBehind) {
3222 // Differentiate the two animations. This one which is briefly on the screen
3223 // gets the !enter animation, and the other activity which remains on the
3224 // screen gets the enter animation. Both appear in the mOpeningApps set.
3227 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
3228 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
3229 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
3230 Animation a = mAppTransition.loadAnimation(lp, transit, enter, mCurConfiguration.uiMode,
3231 mCurConfiguration.orientation, frame, displayFrame, insets, surfaceInsets,
3232 isVoiceInteraction, freeform, atoken.mTask.mTaskId);
3234 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken);
3235 final int containingWidth = frame.width();
3236 final int containingHeight = frame.height();
3237 atoken.mAppAnimator.setAnimation(a, containingWidth, containingHeight,
3238 mAppTransition.canSkipFirstFrame(), mAppTransition.getAppStackClipMode());
3241 atoken.mAppAnimator.clearAnimation();
3243 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
3245 return atoken.mAppAnimator.animation != null;
3248 // -------------------------------------------------------------
3249 // Application Window Tokens
3250 // -------------------------------------------------------------
3252 public void validateAppTokens(int stackId, List<TaskGroup> tasks) {
3253 synchronized (mWindowMap) {
3254 int t = tasks.size() - 1;
3256 Slog.w(TAG_WM, "validateAppTokens: empty task list");
3260 TaskGroup task = tasks.get(0);
3261 int taskId = task.taskId;
3262 Task targetTask = mTaskIdToTask.get(taskId);
3263 DisplayContent displayContent = targetTask.getDisplayContent();
3264 if (displayContent == null) {
3265 Slog.w(TAG_WM, "validateAppTokens: no Display for taskId=" + taskId);
3269 final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks();
3271 for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) {
3272 AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens;
3273 task = tasks.get(t);
3274 List<IApplicationToken> tokens = task.tokens;
3276 DisplayContent lastDisplayContent = displayContent;
3277 displayContent = mTaskIdToTask.get(taskId).getDisplayContent();
3278 if (displayContent != lastDisplayContent) {
3279 Slog.w(TAG_WM, "validateAppTokens: displayContent changed in TaskGroup list!");
3285 for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1;
3286 tokenNdx >= 0 && v >= 0; ) {
3287 final AppWindowToken atoken = localTokens.get(tokenNdx);
3288 if (atoken.removed) {
3292 if (tokens.get(v) != atoken.token) {
3299 if (tokenNdx >= 0 || v >= 0) {
3304 if (taskNdx >= 0 || t >= 0) {
3305 Slog.w(TAG_WM, "validateAppTokens: Mismatch! ActivityManager=" + tasks);
3306 Slog.w(TAG_WM, "validateAppTokens: Mismatch! WindowManager=" + localTasks);
3307 Slog.w(TAG_WM, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4));
3312 public void validateStackOrder(Integer[] remoteStackIds) {
3316 private boolean checkCallingPermission(String permission, String func) {
3317 // Quick check: if the calling permission is me, it's all okay.
3318 if (Binder.getCallingPid() == Process.myPid()) {
3322 if (mContext.checkCallingPermission(permission)
3323 == PackageManager.PERMISSION_GRANTED) {
3326 String msg = "Permission Denial: " + func + " from pid="
3327 + Binder.getCallingPid()
3328 + ", uid=" + Binder.getCallingUid()
3329 + " requires " + permission;
3330 Slog.w(TAG_WM, msg);
3334 boolean okToDisplay() {
3335 return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn();
3338 AppWindowToken findAppWindowToken(IBinder token) {
3339 WindowToken wtoken = mTokenMap.get(token);
3340 if (wtoken == null) {
3343 return wtoken.appWindowToken;
3347 public void addWindowToken(IBinder token, int type) {
3348 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3349 "addWindowToken()")) {
3350 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3353 synchronized(mWindowMap) {
3354 WindowToken wtoken = mTokenMap.get(token);
3355 if (wtoken != null) {
3356 Slog.w(TAG_WM, "Attempted to add existing input method token: " + token);
3359 wtoken = new WindowToken(this, token, type, true);
3360 mTokenMap.put(token, wtoken);
3361 if (type == TYPE_WALLPAPER) {
3362 mWallpaperControllerLocked.addWallpaperToken(wtoken);
3368 public void removeWindowToken(IBinder token) {
3369 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3370 "removeWindowToken()")) {
3371 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3374 final long origId = Binder.clearCallingIdentity();
3375 synchronized(mWindowMap) {
3376 DisplayContent displayContent = null;
3377 WindowToken wtoken = mTokenMap.remove(token);
3378 if (wtoken != null) {
3379 boolean delayed = false;
3380 if (!wtoken.hidden) {
3381 final int N = wtoken.windows.size();
3382 boolean changed = false;
3384 for (int i=0; i<N; i++) {
3385 WindowState win = wtoken.windows.get(i);
3386 displayContent = win.getDisplayContent();
3388 if (win.mWinAnimator.isAnimationSet()) {
3392 if (win.isVisibleNow()) {
3393 win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
3395 //TODO (multidisplay): Magnification is supported only for the default
3396 if (mAccessibilityController != null && win.isDefaultDisplay()) {
3397 mAccessibilityController.onWindowTransitionLocked(win,
3398 WindowManagerPolicy.TRANSIT_EXIT);
3401 if (displayContent != null) {
3402 displayContent.layoutNeeded = true;
3407 wtoken.hidden = true;
3410 mWindowPlacerLocked.performSurfacePlacement();
3411 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
3412 false /*updateInputWindows*/);
3415 if (delayed && displayContent != null) {
3416 displayContent.mExitingTokens.add(wtoken);
3417 } else if (wtoken.windowType == TYPE_WALLPAPER) {
3418 mWallpaperControllerLocked.removeWallpaperToken(wtoken);
3420 } else if (wtoken.windowType == TYPE_WALLPAPER) {
3421 mWallpaperControllerLocked.removeWallpaperToken(wtoken);
3424 mInputMonitor.updateInputWindowsLw(true /*force*/);
3426 Slog.w(TAG_WM, "Attempted to remove non-existing token: " + token);
3429 Binder.restoreCallingIdentity(origId);
3432 private Task createTaskLocked(int taskId, int stackId, int userId, AppWindowToken atoken,
3433 Rect bounds, Configuration config) {
3434 if (DEBUG_STACK) Slog.i(TAG_WM, "createTaskLocked: taskId=" + taskId + " stackId=" + stackId
3435 + " atoken=" + atoken + " bounds=" + bounds);
3436 final TaskStack stack = mStackIdToStack.get(stackId);
3437 if (stack == null) {
3438 throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
3440 EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId);
3441 Task task = new Task(taskId, stack, userId, this, bounds, config);
3442 mTaskIdToTask.put(taskId, task);
3443 stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */, atoken.showForAllUsers);
3448 public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
3449 int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int userId,
3450 int configChanges, boolean voiceInteraction, boolean launchTaskBehind,
3451 Rect taskBounds, Configuration config, int taskResizeMode, boolean alwaysFocusable,
3452 boolean homeTask, int targetSdkVersion, int rotationAnimationHint) {
3453 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3455 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3458 // Get the dispatching timeout here while we are not holding any locks so that it
3459 // can be cached by the AppWindowToken. The timeout value is used later by the
3460 // input dispatcher in code that does hold locks. If we did not cache the value
3461 // here we would run the chance of introducing a deadlock between the window manager
3462 // (which holds locks while updating the input dispatcher state) and the activity manager
3463 // (which holds locks while querying the application token).
3464 long inputDispatchingTimeoutNanos;
3466 inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L;
3467 } catch (RemoteException ex) {
3468 Slog.w(TAG_WM, "Could not get dispatching timeout.", ex);
3469 inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
3472 synchronized(mWindowMap) {
3473 AppWindowToken atoken = findAppWindowToken(token.asBinder());
3474 if (atoken != null) {
3475 Slog.w(TAG_WM, "Attempted to add existing app token: " + token);
3478 atoken = new AppWindowToken(this, token, voiceInteraction);
3479 atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
3480 atoken.appFullscreen = fullscreen;
3481 atoken.showForAllUsers = showForAllUsers;
3482 atoken.targetSdk = targetSdkVersion;
3483 atoken.requestedOrientation = requestedOrientation;
3484 atoken.layoutConfigChanges = (configChanges &
3485 (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0;
3486 atoken.mLaunchTaskBehind = launchTaskBehind;
3487 atoken.mAlwaysFocusable = alwaysFocusable;
3488 if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken
3489 + " to stack=" + stackId + " task=" + taskId + " at " + addPos);
3490 atoken.mRotationAnimationHint = rotationAnimationHint;
3492 Task task = mTaskIdToTask.get(taskId);
3494 task = createTaskLocked(taskId, stackId, userId, atoken, taskBounds, config);
3496 task.addAppToken(addPos, atoken, taskResizeMode, homeTask);
3498 mTokenMap.put(token.asBinder(), atoken);
3500 // Application tokens start out hidden.
3501 atoken.hidden = true;
3502 atoken.hiddenRequested = true;
3507 public void setAppTask(IBinder token, int taskId, int stackId, Rect taskBounds,
3508 Configuration config, int taskResizeMode, boolean homeTask) {
3509 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3511 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3514 synchronized(mWindowMap) {
3515 final AppWindowToken atoken = findAppWindowToken(token);
3516 if (atoken == null) {
3517 Slog.w(TAG_WM, "Attempted to set task id of non-existing app token: " + token);
3520 final Task oldTask = atoken.mTask;
3521 oldTask.removeAppToken(atoken);
3523 Task newTask = mTaskIdToTask.get(taskId);
3524 if (newTask == null) {
3525 newTask = createTaskLocked(
3526 taskId, stackId, oldTask.mUserId, atoken, taskBounds, config);
3528 newTask.addAppToken(Integer.MAX_VALUE /* at top */, atoken, taskResizeMode, homeTask);
3532 public int getOrientationLocked() {
3533 if (mDisplayFrozen) {
3534 if (mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
3535 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3536 "Display is frozen, return " + mLastWindowForcedOrientation);
3537 // If the display is frozen, some activities may be in the middle
3538 // of restarting, and thus have removed their old window. If the
3539 // window has the flag to hide the lock screen, then the lock screen
3540 // can re-appear and inflict its own orientation on us. Keep the
3541 // orientation stable until this all settles down.
3542 return mLastWindowForcedOrientation;
3543 } else if (mPolicy.isKeyguardLocked()) {
3544 // Use the last orientation the while the display is frozen with the
3545 // keyguard locked. This could be the keyguard forced orientation or
3546 // from a SHOW_WHEN_LOCKED window. We don't want to check the show when
3547 // locked window directly though as things aren't stable while
3548 // the display is frozen, for example the window could be momentarily unavailable
3549 // due to activity relaunch.
3550 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, "
3551 + "return " + mLastOrientation);
3552 return mLastOrientation;
3555 // TODO(multidisplay): Change to the correct display.
3556 final WindowList windows = getDefaultWindowListLocked();
3557 for (int pos = windows.size() - 1; pos >= 0; --pos) {
3558 WindowState win = windows.get(pos);
3559 if (win.mAppToken != null) {
3560 // We hit an application window. so the orientation will be determined by the
3561 // app window. No point in continuing further.
3564 if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
3567 int req = win.mAttrs.screenOrientation;
3568 if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND) {
3572 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req);
3573 if (mPolicy.isKeyguardHostWindow(win.mAttrs)) {
3574 mLastKeyguardForcedOrientation = req;
3576 return (mLastWindowForcedOrientation = req);
3578 mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
3580 if (mPolicy.isKeyguardLocked()) {
3581 // The screen is locked and no top system window is requesting an orientation.
3582 // Return either the orientation of the show-when-locked app (if there is any) or
3583 // the orientation of the keyguard. No point in searching from the rest of apps.
3584 WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
3585 AppWindowToken appShowWhenLocked = winShowWhenLocked == null ?
3586 null : winShowWhenLocked.mAppToken;
3587 if (appShowWhenLocked != null) {
3588 int req = appShowWhenLocked.requestedOrientation;
3589 if (req == SCREEN_ORIENTATION_BEHIND) {
3590 req = mLastKeyguardForcedOrientation;
3592 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Done at " + appShowWhenLocked
3593 + " -- show when locked, return " + req);
3596 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3597 "No one is requesting an orientation when the screen is locked");
3598 return mLastKeyguardForcedOrientation;
3602 // Top system windows are not requesting an orientation. Start searching from apps.
3603 return getAppSpecifiedOrientation();
3606 private int getAppSpecifiedOrientation() {
3607 int lastOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
3608 boolean findingBehind = false;
3609 boolean lastFullscreen = false;
3610 DisplayContent displayContent = getDefaultDisplayContentLocked();
3611 final ArrayList<Task> tasks = displayContent.getTasks();
3612 final boolean inMultiWindow = isStackVisibleLocked(DOCKED_STACK_ID)
3613 || isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID);
3614 final boolean dockMinimized =
3615 getDefaultDisplayContentLocked().mDividerControllerLocked.isMinimizedDock();
3616 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
3617 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
3618 final int firstToken = tokens.size() - 1;
3619 for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) {
3620 final AppWindowToken atoken = tokens.get(tokenNdx);
3622 if (DEBUG_APP_ORIENTATION) Slog.v(TAG_WM, "Checking app orientation: " + atoken);
3624 // if we're about to tear down this window and not seek for
3625 // the behind activity, don't use it for orientation
3626 if (!findingBehind && !atoken.hidden && atoken.hiddenRequested) {
3627 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3628 "Skipping " + atoken + " -- going to hide");
3632 if (tokenNdx == firstToken) {
3633 // If we have hit a new Task, and the bottom of the previous group didn't
3634 // explicitly say to use the orientation behind it, and the last app was
3635 // full screen, then we'll stick with the user's orientation.
3636 if (lastOrientation != SCREEN_ORIENTATION_BEHIND && lastFullscreen) {
3637 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Done at " + atoken
3638 + " -- end of group, return " + lastOrientation);
3639 return lastOrientation;
3643 // We ignore any hidden applications on the top.
3644 if (atoken.hiddenRequested) {
3645 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3646 "Skipping " + atoken + " -- hidden on top");
3650 // No app except the home app may specify the screen orientation in multi-window,
3651 // and only if the docked stack is minimized to avoid weirdness when home task
3652 // temporarily gets moved to the front.
3653 if (inMultiWindow && (!atoken.mTask.isHomeTask() || !dockMinimized)) {
3657 if (tokenNdx == 0) {
3658 // Last token in this task.
3659 lastOrientation = atoken.requestedOrientation;
3662 int or = atoken.requestedOrientation;
3663 // If this application is fullscreen, and didn't explicitly say
3664 // to use the orientation behind it, then just take whatever
3665 // orientation it has and ignores whatever is under it.
3666 lastFullscreen = atoken.appFullscreen;
3667 if (lastFullscreen && or != SCREEN_ORIENTATION_BEHIND) {
3668 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3669 "Done at " + atoken + " -- full screen, return " + or);
3672 // If this application has requested an explicit orientation, then use it.
3673 if (or != SCREEN_ORIENTATION_UNSPECIFIED && or != SCREEN_ORIENTATION_BEHIND) {
3674 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3675 "Done at " + atoken + " -- explicitly set, return " + or);
3678 findingBehind |= (or == SCREEN_ORIENTATION_BEHIND);
3681 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3682 "No app is requesting an orientation, return " + mLastOrientation);
3683 // The next app has not been requested to be visible, so we keep the current orientation
3684 // to prevent freezing/unfreezing the display too early unless we are in multi-window, in
3685 // which we don't let the app customize the orientation unless it was the home task that
3686 // is handled above.
3687 return inMultiWindow ? SCREEN_ORIENTATION_UNSPECIFIED : mLastOrientation;
3691 public Configuration updateOrientationFromAppTokens(
3692 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3693 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3694 "updateOrientationFromAppTokens()")) {
3695 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3698 Configuration config = null;
3699 long ident = Binder.clearCallingIdentity();
3701 synchronized(mWindowMap) {
3702 config = updateOrientationFromAppTokensLocked(currentConfig,
3703 freezeThisOneIfNeeded);
3706 Binder.restoreCallingIdentity(ident);
3710 private Configuration updateOrientationFromAppTokensLocked(
3711 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3712 if (!mDisplayReady) {
3715 Configuration config = null;
3717 if (updateOrientationFromAppTokensLocked(false)) {
3718 if (freezeThisOneIfNeeded != null) {
3719 AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);
3720 if (atoken != null) {
3721 startAppFreezingScreenLocked(atoken);
3724 config = computeNewConfigurationLocked();
3726 } else if (currentConfig != null) {
3727 // No obvious action we need to take, but if our current
3728 // state mismatches the activity manager's, update it,
3729 // disregarding font scale, which should remain set to
3730 // the value of the previous configuration.
3731 mTempConfiguration.setToDefaults();
3732 mTempConfiguration.updateFrom(currentConfig);
3733 computeScreenConfigurationLocked(mTempConfiguration);
3734 if (currentConfig.diff(mTempConfiguration) != 0) {
3735 mWaitingForConfig = true;
3736 final DisplayContent displayContent = getDefaultDisplayContentLocked();
3737 displayContent.layoutNeeded = true;
3738 int anim[] = new int[2];
3739 if (displayContent.isDimming()) {
3740 anim[0] = anim[1] = 0;
3742 mPolicy.selectRotationAnimationLw(anim);
3744 startFreezingDisplayLocked(false, anim[0], anim[1]);
3745 config = new Configuration(mTempConfiguration);
3753 * Determine the new desired orientation of the display, returning
3754 * a non-null new Configuration if it has changed from the current
3755 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL
3756 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
3757 * SCREEN. This will typically be done for you if you call
3758 * sendNewConfiguration().
3760 * The orientation is computed from non-application windows first. If none of
3761 * the non-application windows specify orientation, the orientation is computed from
3762 * application tokens.
3763 * @see android.view.IWindowManager#updateOrientationFromAppTokens(
3764 * android.os.IBinder)
3766 boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
3767 long ident = Binder.clearCallingIdentity();
3769 int req = getOrientationLocked();
3770 if (req != mLastOrientation) {
3771 mLastOrientation = req;
3772 //send a message to Policy indicating orientation change to take
3773 //action like disabling/enabling sensors etc.,
3774 mPolicy.setCurrentOrientationLw(req);
3775 if (updateRotationUncheckedLocked(inTransaction)) {
3783 Binder.restoreCallingIdentity(ident);
3788 public int[] setNewConfiguration(Configuration config) {
3789 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3790 "setNewConfiguration()")) {
3791 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3794 synchronized(mWindowMap) {
3795 if (mWaitingForConfig) {
3796 mWaitingForConfig = false;
3797 mLastFinishedFreezeSource = "new-config";
3799 boolean configChanged = mCurConfiguration.diff(config) != 0;
3800 if (!configChanged) {
3803 prepareFreezingAllTaskBounds();
3804 mCurConfiguration = new Configuration(config);
3805 return onConfigurationChanged();
3810 public Rect getBoundsForNewConfiguration(int stackId) {
3811 synchronized(mWindowMap) {
3812 final TaskStack stack = mStackIdToStack.get(stackId);
3813 final Rect outBounds = new Rect();
3814 stack.getBoundsForNewConfiguration(outBounds);
3819 private void prepareFreezingAllTaskBounds() {
3820 for (int i = mDisplayContents.size() - 1; i >= 0; i--) {
3821 ArrayList<TaskStack> stacks = mDisplayContents.valueAt(i).getStacks();
3822 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
3823 final TaskStack stack = stacks.get(stackNdx);
3824 stack.prepareFreezingTaskBounds();
3829 private int[] onConfigurationChanged() {
3830 mPolicy.onConfigurationChanged();
3832 final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
3833 if (!mReconfigureOnConfigurationChanged.contains(defaultDisplayContent)) {
3834 // The default display size information is heavily dependent on the resources in the
3835 // current configuration, so we need to reconfigure it everytime the configuration
3836 // changes. See {@link PhoneWindowManager#setInitialDisplaySize}...sigh...
3837 mReconfigureOnConfigurationChanged.add(defaultDisplayContent);
3839 for (int i = mReconfigureOnConfigurationChanged.size() - 1; i >= 0; i--) {
3840 reconfigureDisplayLocked(mReconfigureOnConfigurationChanged.remove(i));
3843 defaultDisplayContent.getDockedDividerController().onConfigurationChanged();
3844 mChangedStackList.clear();
3845 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; stackNdx--) {
3846 final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
3847 if (stack.onConfigurationChanged()) {
3848 mChangedStackList.add(stack.mStackId);
3851 return mChangedStackList.isEmpty() ?
3852 null : ArrayUtils.convertToIntArray(mChangedStackList);
3856 public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
3857 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3858 "setAppOrientation()")) {
3859 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3862 synchronized(mWindowMap) {
3863 AppWindowToken atoken = findAppWindowToken(token.asBinder());
3864 if (atoken == null) {
3865 Slog.w(TAG_WM, "Attempted to set orientation of non-existing app token: " + token);
3869 atoken.requestedOrientation = requestedOrientation;
3874 public int getAppOrientation(IApplicationToken token) {
3875 synchronized(mWindowMap) {
3876 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3877 if (wtoken == null) {
3878 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3881 return wtoken.requestedOrientation;
3885 void setFocusTaskRegionLocked() {
3886 if (mFocusedApp != null) {
3887 final Task task = mFocusedApp.mTask;
3888 final DisplayContent displayContent = task.getDisplayContent();
3889 if (displayContent != null) {
3890 displayContent.setTouchExcludeRegion(task);
3896 public void setFocusedApp(IBinder token, boolean moveFocusNow) {
3897 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3898 "setFocusedApp()")) {
3899 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3902 synchronized(mWindowMap) {
3903 final AppWindowToken newFocus;
3904 if (token == null) {
3905 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Clearing focused app, was " + mFocusedApp);
3908 newFocus = findAppWindowToken(token);
3909 if (newFocus == null) {
3910 Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token);
3912 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Set focused app to: " + newFocus
3913 + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow);
3916 final boolean changed = mFocusedApp != newFocus;
3918 mFocusedApp = newFocus;
3919 mInputMonitor.setFocusedAppLw(newFocus);
3920 setFocusTaskRegionLocked();
3923 if (moveFocusNow && changed) {
3924 final long origId = Binder.clearCallingIdentity();
3925 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
3926 Binder.restoreCallingIdentity(origId);
3932 * @param transit What kind of transition is happening. Use one of the constants
3933 * AppTransition.TRANSIT_*.
3934 * @param alwaysKeepCurrent If true and a transition is already set, new transition will NOT
3938 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
3939 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3940 "prepareAppTransition()")) {
3941 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3943 synchronized(mWindowMap) {
3944 boolean prepared = mAppTransition.prepareAppTransitionLocked(
3945 transit, alwaysKeepCurrent);
3946 if (prepared && okToDisplay()) {
3947 mSkipAppTransitionAnimation = false;
3953 public int getPendingAppTransition() {
3954 return mAppTransition.getAppTransition();
3958 public void overridePendingAppTransition(String packageName,
3959 int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
3960 synchronized(mWindowMap) {
3961 mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim,
3967 public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
3969 synchronized(mWindowMap) {
3970 mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth,
3976 public void overridePendingAppTransitionClipReveal(int startX, int startY,
3977 int startWidth, int startHeight) {
3978 synchronized(mWindowMap) {
3979 mAppTransition.overridePendingAppTransitionClipReveal(startX, startY, startWidth,
3985 public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
3986 int startY, IRemoteCallback startedCallback, boolean scaleUp) {
3987 synchronized(mWindowMap) {
3988 mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY,
3989 startedCallback, scaleUp);
3994 public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
3995 int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
3997 synchronized(mWindowMap) {
3998 mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX, startY,
3999 targetWidth, targetHeight, startedCallback, scaleUp);
4004 public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
4005 IRemoteCallback onAnimationStartedCallback, IRemoteCallback onAnimationFinishedCallback,
4007 synchronized (mWindowMap) {
4008 mAppTransition.overridePendingAppTransitionMultiThumb(specs, onAnimationStartedCallback,
4009 onAnimationFinishedCallback, scaleUp);
4010 prolongAnimationsFromSpecs(specs, scaleUp);
4015 void prolongAnimationsFromSpecs(@NonNull AppTransitionAnimationSpec[] specs, boolean scaleUp) {
4016 // This is used by freeform <-> recents windows transition. We need to synchronize
4017 // the animation with the appearance of the content of recents, so we will make
4018 // animation stay on the first or last frame a little longer.
4019 mTmpTaskIds.clear();
4020 for (int i = specs.length - 1; i >= 0; i--) {
4021 mTmpTaskIds.put(specs[i].taskId, 0);
4023 for (final WindowState win : mWindowMap.values()) {
4024 final Task task = win.getTask();
4025 if (task != null && mTmpTaskIds.get(task.mTaskId, -1) != -1
4026 && task.inFreeformWorkspace()) {
4027 final AppWindowToken appToken = win.mAppToken;
4028 if (appToken != null && appToken.mAppAnimator != null) {
4029 appToken.mAppAnimator.startProlongAnimation(scaleUp ?
4030 PROLONG_ANIMATION_AT_START : PROLONG_ANIMATION_AT_END);
4037 public void overridePendingAppTransitionInPlace(String packageName, int anim) {
4038 synchronized(mWindowMap) {
4039 mAppTransition.overrideInPlaceAppTransition(packageName, anim);
4044 public void overridePendingAppTransitionMultiThumbFuture(
4045 IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback,
4047 synchronized(mWindowMap) {
4048 mAppTransition.overridePendingAppTransitionMultiThumbFuture(specsFuture, callback,
4054 public void endProlongedAnimations() {
4055 synchronized (mWindowMap) {
4056 for (final WindowState win : mWindowMap.values()) {
4057 final AppWindowToken appToken = win.mAppToken;
4058 if (appToken != null && appToken.mAppAnimator != null) {
4059 appToken.mAppAnimator.endProlongedAnimation();
4062 mAppTransition.notifyProlongedAnimationsEnded();
4067 public void executeAppTransition() {
4068 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4069 "executeAppTransition()")) {
4070 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4073 synchronized(mWindowMap) {
4074 if (DEBUG_APP_TRANSITIONS) Slog.w(TAG_WM, "Execute app transition: " + mAppTransition
4075 + " Callers=" + Debug.getCallers(5));
4076 if (mAppTransition.isTransitionSet()) {
4077 mAppTransition.setReady();
4078 final long origId = Binder.clearCallingIdentity();
4080 mWindowPlacerLocked.performSurfacePlacement();
4082 Binder.restoreCallingIdentity(origId);
4089 public boolean setAppStartingWindow(IBinder token, String pkg,
4090 int theme, CompatibilityInfo compatInfo,
4091 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo,
4092 int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
4093 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4094 "setAppStartingWindow()")) {
4095 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4098 synchronized(mWindowMap) {
4099 if (DEBUG_STARTING_WINDOW) Slog.v(
4100 TAG_WM, "setAppStartingWindow: token=" + token + " pkg=" + pkg
4101 + " transferFrom=" + transferFrom);
4103 AppWindowToken wtoken = findAppWindowToken(token);
4104 if (wtoken == null) {
4105 Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + token);
4109 // If the display is frozen, we won't do anything until the
4110 // actual window is displayed so there is no reason to put in
4111 // the starting window.
4112 if (!okToDisplay()) {
4116 if (wtoken.startingData != null) {
4120 // If this is a translucent window, then don't
4121 // show a starting window -- the current effect (a full-screen
4122 // opaque starting window that fades away to the real contents
4123 // when it is ready) does not work for this.
4124 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Checking theme of starting window: 0x"
4125 + Integer.toHexString(theme));
4127 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
4128 com.android.internal.R.styleable.Window, mCurrentUserId);
4130 // Whoops! App doesn't exist. Um. Okay. We'll just
4131 // pretend like we didn't see that.
4134 final boolean windowIsTranslucent = ent.array.getBoolean(
4135 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
4136 final boolean windowIsFloating = ent.array.getBoolean(
4137 com.android.internal.R.styleable.Window_windowIsFloating, false);
4138 final boolean windowShowWallpaper = ent.array.getBoolean(
4139 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
4140 final boolean windowDisableStarting = ent.array.getBoolean(
4141 com.android.internal.R.styleable.Window_windowDisablePreview, false);
4142 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Translucent=" + windowIsTranslucent
4143 + " Floating=" + windowIsFloating
4144 + " ShowWallpaper=" + windowShowWallpaper);
4145 if (windowIsTranslucent) {
4148 if (windowIsFloating || windowDisableStarting) {
4151 if (windowShowWallpaper) {
4152 if (mWallpaperControllerLocked.getWallpaperTarget() == null) {
4153 // If this theme is requesting a wallpaper, and the wallpaper
4154 // is not currently visible, then this effectively serves as
4155 // an opaque window and our starting window transition animation
4156 // can still work. We just need to make sure the starting window
4157 // is also showing the wallpaper.
4158 windowFlags |= FLAG_SHOW_WALLPAPER;
4165 if (transferStartingWindow(transferFrom, wtoken)) {
4169 // There is no existing starting window, and the caller doesn't
4170 // want us to create one, so that's it!
4171 if (!createIfNeeded) {
4175 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating StartingData");
4176 wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
4177 labelRes, icon, logo, windowFlags);
4178 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4179 // Note: we really want to do sendMessageAtFrontOfQueue() because we
4180 // want to process the message ASAP, before any other queued
4182 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING");
4183 mH.sendMessageAtFrontOfQueue(m);
4188 private boolean transferStartingWindow(IBinder transferFrom, AppWindowToken wtoken) {
4189 if (transferFrom == null) {
4192 AppWindowToken ttoken = findAppWindowToken(transferFrom);
4193 if (ttoken == null) {
4196 WindowState startingWindow = ttoken.startingWindow;
4197 if (startingWindow != null && ttoken.startingView != null) {
4198 // In this case, the starting icon has already been displayed, so start
4199 // letting windows get shown immediately without any more transitions.
4200 mSkipAppTransitionAnimation = true;
4202 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
4203 "Moving existing starting " + startingWindow + " from " + ttoken
4205 final long origId = Binder.clearCallingIdentity();
4207 // Transfer the starting window over to the new token.
4208 wtoken.startingData = ttoken.startingData;
4209 wtoken.startingView = ttoken.startingView;
4210 wtoken.startingDisplayed = ttoken.startingDisplayed;
4211 ttoken.startingDisplayed = false;
4212 wtoken.startingWindow = startingWindow;
4213 wtoken.reportedVisible = ttoken.reportedVisible;
4214 ttoken.startingData = null;
4215 ttoken.startingView = null;
4216 ttoken.startingWindow = null;
4217 ttoken.startingMoved = true;
4218 startingWindow.mToken = wtoken;
4219 startingWindow.mRootToken = wtoken;
4220 startingWindow.mAppToken = wtoken;
4222 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) {
4223 Slog.v(TAG_WM, "Removing starting window: " + startingWindow);
4225 startingWindow.getWindowList().remove(startingWindow);
4226 mWindowsChanged = true;
4227 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
4228 "Removing starting " + startingWindow + " from " + ttoken);
4229 ttoken.windows.remove(startingWindow);
4230 ttoken.allAppWindows.remove(startingWindow);
4231 addWindowToListInOrderLocked(startingWindow, true);
4233 // Propagate other interesting state between the
4234 // tokens. If the old token is displayed, we should
4235 // immediately force the new one to be displayed. If
4236 // it is animating, we need to move that animation to
4238 if (ttoken.allDrawn) {
4239 wtoken.allDrawn = true;
4240 wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn;
4242 if (ttoken.firstWindowDrawn) {
4243 wtoken.firstWindowDrawn = true;
4245 if (!ttoken.hidden) {
4246 wtoken.hidden = false;
4247 wtoken.hiddenRequested = false;
4249 if (wtoken.clientHidden != ttoken.clientHidden) {
4250 wtoken.clientHidden = ttoken.clientHidden;
4251 wtoken.sendAppVisibilityToClients();
4253 ttoken.mAppAnimator.transferCurrentAnimation(
4254 wtoken.mAppAnimator, startingWindow.mWinAnimator);
4256 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4257 true /*updateInputWindows*/);
4258 getDefaultDisplayContentLocked().layoutNeeded = true;
4259 mWindowPlacerLocked.performSurfacePlacement();
4260 Binder.restoreCallingIdentity(origId);
4262 } else if (ttoken.startingData != null) {
4263 // The previous app was getting ready to show a
4264 // starting window, but hasn't yet done so. Steal it!
4265 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving pending starting from " + ttoken
4267 wtoken.startingData = ttoken.startingData;
4268 ttoken.startingData = null;
4269 ttoken.startingMoved = true;
4270 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4271 // Note: we really want to do sendMessageAtFrontOfQueue() because we
4272 // want to process the message ASAP, before any other queued
4274 mH.sendMessageAtFrontOfQueue(m);
4277 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
4278 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
4279 if (tAppAnimator.thumbnail != null) {
4280 // The old token is animating with a thumbnail, transfer that to the new token.
4281 if (wAppAnimator.thumbnail != null) {
4282 wAppAnimator.thumbnail.destroy();
4284 wAppAnimator.thumbnail = tAppAnimator.thumbnail;
4285 wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer;
4286 wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
4287 tAppAnimator.thumbnail = null;
4292 public void removeAppStartingWindow(IBinder token) {
4293 synchronized (mWindowMap) {
4294 final AppWindowToken wtoken = mTokenMap.get(token).appWindowToken;
4295 scheduleRemoveStartingWindowLocked(wtoken);
4299 public void setAppFullscreen(IBinder token, boolean toOpaque) {
4300 synchronized (mWindowMap) {
4301 AppWindowToken atoken = findAppWindowToken(token);
4302 if (atoken != null) {
4303 atoken.appFullscreen = toOpaque;
4304 setWindowOpaqueLocked(token, toOpaque);
4305 mWindowPlacerLocked.requestTraversal();
4310 public void setWindowOpaque(IBinder token, boolean isOpaque) {
4311 synchronized (mWindowMap) {
4312 setWindowOpaqueLocked(token, isOpaque);
4316 public void setWindowOpaqueLocked(IBinder token, boolean isOpaque) {
4317 AppWindowToken wtoken = findAppWindowToken(token);
4318 if (wtoken != null) {
4319 WindowState win = wtoken.findMainWindow();
4321 win.mWinAnimator.setOpaqueLocked(isOpaque);
4326 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
4327 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
4328 boolean delayed = false;
4330 if (wtoken.clientHidden == visible) {
4331 wtoken.clientHidden = !visible;
4332 wtoken.sendAppVisibilityToClients();
4335 // Allow for state changes and animation to be applied if:
4336 // * token is transitioning visibility state
4337 // * or the token was marked as hidden and is exiting before we had a chance to play the
4338 // transition animation
4339 // * or this is an opening app and windows are being replaced.
4340 boolean visibilityChanged = false;
4341 if (wtoken.hidden == visible || (wtoken.hidden && wtoken.mIsExiting) ||
4342 (visible && wtoken.waitingForReplacement())) {
4343 boolean changed = false;
4344 if (DEBUG_APP_TRANSITIONS) Slog.v(
4345 TAG_WM, "Changing app " + wtoken + " hidden=" + wtoken.hidden
4346 + " performLayout=" + performLayout);
4348 boolean runningAppAnimation = false;
4350 if (transit != AppTransition.TRANSIT_UNSET) {
4351 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
4352 wtoken.mAppAnimator.setNullAnimation();
4354 if (applyAnimationLocked(wtoken, lp, transit, visible, isVoiceInteraction)) {
4355 delayed = runningAppAnimation = true;
4357 WindowState window = wtoken.findMainWindow();
4358 //TODO (multidisplay): Magnification is supported only for the default display.
4359 if (window != null && mAccessibilityController != null
4360 && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
4361 mAccessibilityController.onAppWindowTransitionLocked(window, transit);
4366 final int windowsCount = wtoken.allAppWindows.size();
4367 for (int i = 0; i < windowsCount; i++) {
4368 WindowState win = wtoken.allAppWindows.get(i);
4369 if (win == wtoken.startingWindow) {
4370 // Starting window that's exiting will be removed when the animation
4371 // finishes. Mark all relevant flags for that finishExit will proceed
4372 // all the way to actually remove it.
4373 if (!visible && win.isVisibleNow() && wtoken.mAppAnimator.isAnimating()) {
4374 win.mAnimatingExit = true;
4375 win.mRemoveOnExit = true;
4376 win.mWindowRemovalAllowed = true;
4381 //Slog.i(TAG_WM, "Window " + win + ": vis=" + win.isVisible());
4384 if (!win.isVisibleNow()) {
4385 if (!runningAppAnimation) {
4386 win.mWinAnimator.applyAnimationLocked(
4387 WindowManagerPolicy.TRANSIT_ENTER, true);
4388 //TODO (multidisplay): Magnification is supported only for the default
4389 if (mAccessibilityController != null
4390 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4391 mAccessibilityController.onWindowTransitionLocked(win,
4392 WindowManagerPolicy.TRANSIT_ENTER);
4396 win.setDisplayLayoutNeeded();
4398 } else if (win.isVisibleNow()) {
4399 if (!runningAppAnimation) {
4400 win.mWinAnimator.applyAnimationLocked(
4401 WindowManagerPolicy.TRANSIT_EXIT, false);
4402 //TODO (multidisplay): Magnification is supported only for the default
4403 if (mAccessibilityController != null
4404 && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4405 mAccessibilityController.onWindowTransitionLocked(win,
4406 WindowManagerPolicy.TRANSIT_EXIT);
4410 win.setDisplayLayoutNeeded();
4414 wtoken.hidden = wtoken.hiddenRequested = !visible;
4415 visibilityChanged = true;
4417 unsetAppFreezingScreenLocked(wtoken, true, true);
4419 // If we are being set visible, and the starting window is
4420 // not yet displayed, then make sure it doesn't get displayed.
4421 WindowState swin = wtoken.startingWindow;
4422 if (swin != null && !swin.isDrawnLw()) {
4423 swin.mPolicyVisibility = false;
4424 swin.mPolicyVisibilityAfterAnim = false;
4428 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setTokenVisibilityLocked: " + wtoken
4429 + ": hidden=" + wtoken.hidden + " hiddenRequested="
4430 + wtoken.hiddenRequested);
4433 mInputMonitor.setUpdateInputWindowsNeededLw();
4434 if (performLayout) {
4435 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4436 false /*updateInputWindows*/);
4437 mWindowPlacerLocked.performSurfacePlacement();
4439 mInputMonitor.updateInputWindowsLw(false /*force*/);
4443 if (wtoken.mAppAnimator.animation != null) {
4447 for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) {
4448 if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimationSet()) {
4453 if (visibilityChanged) {
4454 if (visible && !delayed) {
4455 // The token was made immediately visible, there will be no entrance animation.
4456 // We need to inform the client the enter animation was finished.
4457 wtoken.mEnteringAnimation = true;
4458 mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(wtoken.token);
4461 if (!mClosingApps.contains(wtoken) && !mOpeningApps.contains(wtoken)) {
4462 // The token is not closing nor opening, so even if there is an animation set, that
4463 // doesn't mean that it goes through the normal app transition cycle so we have
4464 // to inform the docked controller about visibility change.
4465 getDefaultDisplayContentLocked().getDockedDividerController()
4466 .notifyAppVisibilityChanged();
4473 void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) {
4474 if (transit != AppTransition.TRANSIT_UNSET) {
4475 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
4476 wtoken.mAppAnimator.setNullAnimation();
4478 applyAnimationLocked(wtoken, null, transit, false, false);
4483 public void notifyAppResumed(IBinder token, boolean wasStopped, boolean allowSavedSurface) {
4484 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4485 "notifyAppResumed()")) {
4486 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4489 synchronized(mWindowMap) {
4490 final AppWindowToken wtoken;
4491 wtoken = findAppWindowToken(token);
4492 if (wtoken == null) {
4493 Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: " + token);
4496 wtoken.notifyAppResumed(wasStopped, allowSavedSurface);
4501 public void notifyAppStopped(IBinder token) {
4502 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4503 "notifyAppStopped()")) {
4504 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4507 synchronized(mWindowMap) {
4508 final AppWindowToken wtoken;
4509 wtoken = findAppWindowToken(token);
4510 if (wtoken == null) {
4511 Slog.w(TAG_WM, "Attempted to notify stopped of non-existing app token: " + token);
4514 wtoken.notifyAppStopped();
4519 public void setAppVisibility(IBinder token, boolean visible) {
4520 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4521 "setAppVisibility()")) {
4522 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4525 AppWindowToken wtoken;
4527 synchronized(mWindowMap) {
4528 wtoken = findAppWindowToken(token);
4529 if (wtoken == null) {
4530 Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: " + token);
4534 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG_WM, "setAppVisibility(" +
4535 token + ", visible=" + visible + "): " + mAppTransition +
4536 " hidden=" + wtoken.hidden + " hiddenRequested=" +
4537 wtoken.hiddenRequested + " Callers=" + Debug.getCallers(6));
4539 mOpeningApps.remove(wtoken);
4540 mClosingApps.remove(wtoken);
4541 wtoken.waitingToShow = false;
4542 wtoken.hiddenRequested = !visible;
4545 // If the app is dead while it was visible, we kept its dead window on screen.
4546 // Now that the app is going invisible, we can remove it. It will be restarted
4547 // if made visible again.
4548 wtoken.removeAllDeadWindows();
4549 wtoken.setVisibleBeforeClientHidden();
4550 } else if (visible) {
4551 if (!mAppTransition.isTransitionSet() && mAppTransition.isReady()) {
4552 // Add the app mOpeningApps if transition is unset but ready. This means
4553 // we're doing a screen freeze, and the unfreeze will wait for all opening
4554 // apps to be ready.
4555 mOpeningApps.add(wtoken);
4557 wtoken.startingMoved = false;
4558 // If the token is currently hidden (should be the common case), or has been
4559 // stopped, then we need to set up to wait for its windows to be ready.
4560 if (wtoken.hidden || wtoken.mAppStopped) {
4561 wtoken.clearAllDrawn();
4563 // If the app was already visible, don't reset the waitingToShow state.
4564 if (wtoken.hidden) {
4565 wtoken.waitingToShow = true;
4568 if (wtoken.clientHidden) {
4569 // In the case where we are making an app visible
4570 // but holding off for a transition, we still need
4571 // to tell the client to make its windows visible so
4572 // they get drawn. Otherwise, we will wait on
4573 // performing the transition until all windows have
4574 // been drawn, they never will be, and we are sad.
4575 wtoken.clientHidden = false;
4576 wtoken.sendAppVisibilityToClients();
4579 wtoken.requestUpdateWallpaperIfNeeded();
4581 if (DEBUG_ADD_REMOVE) Slog.v(
4582 TAG_WM, "No longer Stopped: " + wtoken);
4583 wtoken.mAppStopped = false;
4586 // If we are preparing an app transition, then delay changing
4587 // the visibility of this token until we execute that transition.
4588 if (okToDisplay() && mAppTransition.isTransitionSet()) {
4589 // A dummy animation is a placeholder animation which informs others that an
4590 // animation is going on (in this case an application transition). If the animation
4591 // was transferred from another application/animator, no dummy animator should be
4592 // created since an animation is already in progress.
4593 if (wtoken.mAppAnimator.usingTransferredAnimation
4594 && wtoken.mAppAnimator.animation == null) {
4595 Slog.wtf(TAG_WM, "Will NOT set dummy animation on: " + wtoken
4596 + ", using null transfered animation!");
4598 if (!wtoken.mAppAnimator.usingTransferredAnimation &&
4599 (!wtoken.startingDisplayed || mSkipAppTransitionAnimation)) {
4600 if (DEBUG_APP_TRANSITIONS) Slog.v(
4601 TAG_WM, "Setting dummy animation on: " + wtoken);
4602 wtoken.mAppAnimator.setDummyAnimation();
4604 wtoken.inPendingTransaction = true;
4606 mOpeningApps.add(wtoken);
4607 wtoken.mEnteringAnimation = true;
4609 mClosingApps.add(wtoken);
4610 wtoken.mEnteringAnimation = false;
4612 if (mAppTransition.getAppTransition() == AppTransition.TRANSIT_TASK_OPEN_BEHIND) {
4613 // We're launchingBehind, add the launching activity to mOpeningApps.
4614 final WindowState win =
4615 findFocusedWindowLocked(getDefaultDisplayContentLocked());
4617 final AppWindowToken focusedToken = win.mAppToken;
4618 if (focusedToken != null) {
4619 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, " +
4620 " adding " + focusedToken + " to mOpeningApps");
4621 // Force animation to be loaded.
4622 focusedToken.hidden = true;
4623 mOpeningApps.add(focusedToken);
4630 final long origId = Binder.clearCallingIdentity();
4631 wtoken.inPendingTransaction = false;
4632 setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET,
4633 true, wtoken.voiceInteraction);
4634 wtoken.updateReportedVisibilityLocked();
4635 Binder.restoreCallingIdentity(origId);
4639 void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
4640 boolean unfreezeSurfaceNow, boolean force) {
4641 if (wtoken.mAppAnimator.freezingScreen) {
4642 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + wtoken
4643 + " force=" + force);
4644 final int N = wtoken.allAppWindows.size();
4645 boolean unfrozeWindows = false;
4646 for (int i=0; i<N; i++) {
4647 WindowState w = wtoken.allAppWindows.get(i);
4648 if (w.mAppFreezing) {
4649 w.mAppFreezing = false;
4650 if (w.mHasSurface && !w.mOrientationChanging
4651 && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
4652 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "set mOrientationChanging of " + w);
4653 w.mOrientationChanging = true;
4654 mWindowPlacerLocked.mOrientationChangeComplete = false;
4656 w.mLastFreezeDuration = 0;
4657 unfrozeWindows = true;
4658 w.setDisplayLayoutNeeded();
4661 if (force || unfrozeWindows) {
4662 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + wtoken);
4663 wtoken.mAppAnimator.freezingScreen = false;
4664 wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime()
4665 - mDisplayFreezeTime);
4666 mAppsFreezingScreen--;
4667 mLastFinishedFreezeSource = wtoken;
4669 if (unfreezeSurfaceNow) {
4670 if (unfrozeWindows) {
4671 mWindowPlacerLocked.performSurfacePlacement();
4673 stopFreezingDisplayLocked();
4678 private void startAppFreezingScreenLocked(AppWindowToken wtoken) {
4679 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + wtoken.appToken + ": hidden="
4680 + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
4681 if (!wtoken.hiddenRequested) {
4682 if (!wtoken.mAppAnimator.freezingScreen) {
4683 wtoken.mAppAnimator.freezingScreen = true;
4684 wtoken.mAppAnimator.lastFreezeDuration = 0;
4685 mAppsFreezingScreen++;
4686 if (mAppsFreezingScreen == 1) {
4687 startFreezingDisplayLocked(false, 0, 0);
4688 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
4689 mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
4692 final int N = wtoken.allAppWindows.size();
4693 for (int i=0; i<N; i++) {
4694 WindowState w = wtoken.allAppWindows.get(i);
4695 w.mAppFreezing = true;
4701 public void startAppFreezingScreen(IBinder token, int configChanges) {
4702 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4703 "setAppFreezingScreen()")) {
4704 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4707 synchronized(mWindowMap) {
4708 if (configChanges == 0 && okToDisplay()) {
4709 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + token);
4713 AppWindowToken wtoken = findAppWindowToken(token);
4714 if (wtoken == null || wtoken.appToken == null) {
4715 Slog.w(TAG_WM, "Attempted to freeze screen with non-existing app token: " + wtoken);
4718 final long origId = Binder.clearCallingIdentity();
4719 startAppFreezingScreenLocked(wtoken);
4720 Binder.restoreCallingIdentity(origId);
4725 public void stopAppFreezingScreen(IBinder token, boolean force) {
4726 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4727 "setAppFreezingScreen()")) {
4728 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4731 synchronized(mWindowMap) {
4732 AppWindowToken wtoken = findAppWindowToken(token);
4733 if (wtoken == null || wtoken.appToken == null) {
4736 final long origId = Binder.clearCallingIdentity();
4737 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + token
4738 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
4739 unsetAppFreezingScreenLocked(wtoken, true, force);
4740 Binder.restoreCallingIdentity(origId);
4745 public void removeAppToken(IBinder token) {
4746 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4747 "removeAppToken()")) {
4748 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4751 AppWindowToken wtoken = null;
4752 AppWindowToken startingToken = null;
4753 boolean delayed = false;
4755 final long origId = Binder.clearCallingIdentity();
4756 synchronized(mWindowMap) {
4757 WindowToken basewtoken = mTokenMap.remove(token);
4758 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
4759 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + wtoken);
4760 delayed = setTokenVisibilityLocked(wtoken, null, false,
4761 AppTransition.TRANSIT_UNSET, true, wtoken.voiceInteraction);
4762 wtoken.inPendingTransaction = false;
4763 mOpeningApps.remove(wtoken);
4764 wtoken.waitingToShow = false;
4765 if (mClosingApps.contains(wtoken)) {
4767 } else if (mAppTransition.isTransitionSet()) {
4768 mClosingApps.add(wtoken);
4771 if (DEBUG_APP_TRANSITIONS) Slog.v(
4772 TAG_WM, "Removing app " + wtoken + " delayed=" + delayed
4773 + " animation=" + wtoken.mAppAnimator.animation
4774 + " animating=" + wtoken.mAppAnimator.animating);
4775 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
4776 + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
4777 final TaskStack stack = wtoken.mTask.mStack;
4778 if (delayed && !wtoken.allAppWindows.isEmpty()) {
4779 // set the token aside because it has an active animation to be finished
4780 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
4781 "removeAppToken make exiting: " + wtoken);
4782 stack.mExitingAppTokens.add(wtoken);
4783 wtoken.mIsExiting = true;
4785 // Make sure there is no animation running on this token,
4786 // so any windows associated with it will be removed as
4787 // soon as their animations are complete
4788 wtoken.mAppAnimator.clearAnimation();
4789 wtoken.mAppAnimator.animating = false;
4790 wtoken.removeAppFromTaskLocked();
4793 wtoken.removed = true;
4794 if (wtoken.startingData != null) {
4795 startingToken = wtoken;
4797 unsetAppFreezingScreenLocked(wtoken, true, true);
4798 if (mFocusedApp == wtoken) {
4799 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + wtoken);
4801 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
4802 mInputMonitor.setFocusedAppLw(null);
4805 Slog.w(TAG_WM, "Attempted to remove non-existing app token: " + token);
4808 if (!delayed && wtoken != null) {
4809 wtoken.updateReportedVisibilityLocked();
4812 // Will only remove if startingToken non null.
4813 scheduleRemoveStartingWindowLocked(startingToken);
4815 Binder.restoreCallingIdentity(origId);
4819 void scheduleRemoveStartingWindowLocked(AppWindowToken wtoken) {
4820 if (wtoken == null) {
4823 if (mH.hasMessages(H.REMOVE_STARTING, wtoken)) {
4824 // Already scheduled.
4828 if (wtoken.startingWindow == null) {
4829 if (wtoken.startingData != null) {
4830 // Starting window has not been added yet, but it is scheduled to be added.
4831 // Go ahead and cancel the request.
4832 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
4833 "Clearing startingData for token=" + wtoken);
4834 wtoken.startingData = null;
4839 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, Debug.getCallers(1) +
4840 ": Schedule remove starting " + wtoken + (wtoken != null ?
4841 " startingWindow=" + wtoken.startingWindow : ""));
4842 Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken);
4846 void dumpAppTokensLocked() {
4847 final int numStacks = mStackIdToStack.size();
4848 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
4849 final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
4850 Slog.v(TAG_WM, " Stack #" + stack.mStackId + " tasks from bottom to top:");
4851 final ArrayList<Task> tasks = stack.getTasks();
4852 final int numTasks = tasks.size();
4853 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4854 final Task task = tasks.get(taskNdx);
4855 Slog.v(TAG_WM, " Task #" + task.mTaskId + " activities from bottom to top:");
4856 AppTokenList tokens = task.mAppTokens;
4857 final int numTokens = tokens.size();
4858 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
4859 Slog.v(TAG_WM, " activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token);
4865 void dumpWindowsLocked() {
4866 final int numDisplays = mDisplayContents.size();
4867 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4868 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
4869 Slog.v(TAG_WM, " Display #" + displayContent.getDisplayId());
4870 final WindowList windows = displayContent.getWindowList();
4871 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
4872 Slog.v(TAG_WM, " #" + winNdx + ": " + windows.get(winNdx));
4877 private final int reAddWindowLocked(int index, WindowState win) {
4878 final WindowList windows = win.getWindowList();
4879 // Adding child windows relies on mChildWindows being ordered by mSubLayer.
4880 final int NCW = win.mChildWindows.size();
4881 boolean winAdded = false;
4882 for (int j=0; j<NCW; j++) {
4883 WindowState cwin = win.mChildWindows.get(j);
4884 if (!winAdded && cwin.mSubLayer >= 0) {
4885 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding child window at "
4886 + index + ": " + cwin);
4887 win.mRebuilding = false;
4888 windows.add(index, win);
4892 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding window at "
4893 + index + ": " + cwin);
4894 cwin.mRebuilding = false;
4895 windows.add(index, cwin);
4899 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding window at "
4900 + index + ": " + win);
4901 win.mRebuilding = false;
4902 windows.add(index, win);
4905 mWindowsChanged = true;
4909 private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index,
4910 WindowToken token) {
4911 final int NW = token.windows.size();
4912 for (int i=0; i<NW; i++) {
4913 final WindowState win = token.windows.get(i);
4914 final DisplayContent winDisplayContent = win.getDisplayContent();
4915 if (winDisplayContent == displayContent || winDisplayContent == null) {
4916 win.mDisplayContent = displayContent;
4917 index = reAddWindowLocked(index, win);
4924 void moveStackWindowsLocked(DisplayContent displayContent) {
4925 final WindowList windows = displayContent.getWindowList();
4926 mTmpWindows.addAll(windows);
4928 rebuildAppWindowListLocked(displayContent);
4930 // Set displayContent.layoutNeeded if window order changed.
4931 final int tmpSize = mTmpWindows.size();
4932 final int winSize = windows.size();
4933 int tmpNdx = 0, winNdx = 0;
4934 while (tmpNdx < tmpSize && winNdx < winSize) {
4935 // Skip over all exiting windows, they've been moved out of order.
4938 tmp = mTmpWindows.get(tmpNdx++);
4939 } while (tmpNdx < tmpSize && tmp.mAppToken != null && tmp.mAppToken.mIsExiting);
4943 win = windows.get(winNdx++);
4944 } while (winNdx < winSize && win.mAppToken != null && win.mAppToken.mIsExiting);
4947 // Window order changed.
4948 displayContent.layoutNeeded = true;
4952 if (tmpNdx != winNdx) {
4953 // One list was different from the other.
4954 displayContent.layoutNeeded = true;
4956 mTmpWindows.clear();
4958 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4959 false /*updateInputWindows*/)) {
4960 mLayersController.assignLayersLocked(displayContent.getWindowList());
4963 mInputMonitor.setUpdateInputWindowsNeededLw();
4964 mWindowPlacerLocked.performSurfacePlacement();
4965 mInputMonitor.updateInputWindowsLw(false /*force*/);
4969 public void moveTaskToTop(int taskId) {
4970 final long origId = Binder.clearCallingIdentity();
4972 synchronized(mWindowMap) {
4973 Task task = mTaskIdToTask.get(taskId);
4975 // Normal behavior, addAppToken will be called next and task will be created.
4978 final TaskStack stack = task.mStack;
4979 final DisplayContent displayContent = task.getDisplayContent();
4980 displayContent.moveStack(stack, true);
4981 if (displayContent.isDefaultDisplay) {
4982 final TaskStack homeStack = displayContent.getHomeStack();
4983 if (homeStack != stack) {
4984 // When a non-home stack moves to the top, the home stack moves to the
4986 displayContent.moveStack(homeStack, false);
4989 stack.moveTaskToTop(task);
4990 if (mAppTransition.isTransitionSet()) {
4991 task.setSendingToBottom(false);
4993 moveStackWindowsLocked(displayContent);
4996 Binder.restoreCallingIdentity(origId);
5000 public void moveTaskToBottom(int taskId) {
5001 final long origId = Binder.clearCallingIdentity();
5003 synchronized(mWindowMap) {
5004 Task task = mTaskIdToTask.get(taskId);
5006 Slog.e(TAG_WM, "moveTaskToBottom: taskId=" + taskId
5007 + " not found in mTaskIdToTask");
5010 final TaskStack stack = task.mStack;
5011 stack.moveTaskToBottom(task);
5012 if (mAppTransition.isTransitionSet()) {
5013 task.setSendingToBottom(true);
5015 moveStackWindowsLocked(stack.getDisplayContent());
5018 Binder.restoreCallingIdentity(origId);
5022 boolean isStackVisibleLocked(int stackId) {
5023 final TaskStack stack = mStackIdToStack.get(stackId);
5024 return (stack != null && stack.isVisibleLocked());
5027 public void setDockedStackCreateState(int mode, Rect bounds) {
5028 synchronized (mWindowMap) {
5029 setDockedStackCreateStateLocked(mode, bounds);
5033 void setDockedStackCreateStateLocked(int mode, Rect bounds) {
5034 mDockedStackCreateMode = mode;
5035 mDockedStackCreateBounds = bounds;
5039 * Create a new TaskStack and place it on a DisplayContent.
5040 * @param stackId The unique identifier of the new stack.
5041 * @param displayId The unique identifier of the DisplayContent.
5042 * @param onTop If true the stack will be place at the top of the display,
5043 * else at the bottom
5044 * @return The initial bounds the stack was created with. null means fullscreen.
5046 public Rect attachStack(int stackId, int displayId, boolean onTop) {
5047 final long origId = Binder.clearCallingIdentity();
5049 synchronized (mWindowMap) {
5050 final DisplayContent displayContent = mDisplayContents.get(displayId);
5051 boolean attachedToDisplay = false;
5052 if (displayContent != null) {
5053 TaskStack stack = mStackIdToStack.get(stackId);
5054 if (stack == null) {
5055 if (DEBUG_STACK) Slog.d(TAG_WM, "attachStack: stackId=" + stackId);
5057 stack = displayContent.getStackById(stackId);
5058 if (stack != null) {
5059 // It's already attached to the display. Detach and re-attach
5060 // because onTop might change, and be sure to clear mDeferDetach!
5061 displayContent.detachStack(stack);
5062 stack.mDeferDetach = false;
5063 attachedToDisplay = true;
5065 stack = new TaskStack(this, stackId);
5068 mStackIdToStack.put(stackId, stack);
5069 if (stackId == DOCKED_STACK_ID) {
5070 getDefaultDisplayContentLocked().mDividerControllerLocked
5071 .notifyDockedStackExistsChanged(true);
5074 if (!attachedToDisplay) {
5075 stack.attachDisplayContent(displayContent);
5077 displayContent.attachStack(stack, onTop);
5078 if (stack.getRawFullscreen()) {
5081 Rect bounds = new Rect();
5082 stack.getRawBounds(bounds);
5087 Binder.restoreCallingIdentity(origId);
5092 void detachStackLocked(DisplayContent displayContent, TaskStack stack) {
5093 displayContent.detachStack(stack);
5094 stack.detachDisplay();
5095 if (stack.mStackId == DOCKED_STACK_ID) {
5096 getDefaultDisplayContentLocked().mDividerControllerLocked
5097 .notifyDockedStackExistsChanged(false);
5101 public void detachStack(int stackId) {
5102 synchronized (mWindowMap) {
5103 TaskStack stack = mStackIdToStack.get(stackId);
5104 if (stack != null) {
5105 final DisplayContent displayContent = stack.getDisplayContent();
5106 if (displayContent != null) {
5107 if (stack.isAnimating()) {
5108 stack.mDeferDetach = true;
5111 detachStackLocked(displayContent, stack);
5117 public void removeStack(int stackId) {
5118 synchronized (mWindowMap) {
5119 mStackIdToStack.remove(stackId);
5123 public void removeTask(int taskId) {
5124 synchronized (mWindowMap) {
5125 Task task = mTaskIdToTask.get(taskId);
5127 if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + taskId);
5130 task.removeLocked();
5135 public void cancelTaskWindowTransition(int taskId) {
5136 synchronized (mWindowMap) {
5137 Task task = mTaskIdToTask.get(taskId);
5139 task.cancelTaskWindowTransition();
5145 public void cancelTaskThumbnailTransition(int taskId) {
5146 synchronized (mWindowMap) {
5147 Task task = mTaskIdToTask.get(taskId);
5149 task.cancelTaskThumbnailTransition();
5154 public void addTask(int taskId, int stackId, boolean toTop) {
5155 synchronized (mWindowMap) {
5156 if (DEBUG_STACK) Slog.i(TAG_WM, "addTask: adding taskId=" + taskId
5157 + " to " + (toTop ? "top" : "bottom"));
5158 Task task = mTaskIdToTask.get(taskId);
5160 if (DEBUG_STACK) Slog.i(TAG_WM, "addTask: could not find taskId=" + taskId);
5163 TaskStack stack = mStackIdToStack.get(stackId);
5164 stack.addTask(task, toTop);
5165 final DisplayContent displayContent = stack.getDisplayContent();
5166 displayContent.layoutNeeded = true;
5167 mWindowPlacerLocked.performSurfacePlacement();
5171 public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
5172 synchronized (mWindowMap) {
5173 if (DEBUG_STACK) Slog.i(TAG_WM, "moveTaskToStack: moving taskId=" + taskId
5174 + " to stackId=" + stackId + " at " + (toTop ? "top" : "bottom"));
5175 Task task = mTaskIdToTask.get(taskId);
5177 if (DEBUG_STACK) Slog.i(TAG_WM, "moveTaskToStack: could not find taskId=" + taskId);
5180 TaskStack stack = mStackIdToStack.get(stackId);
5181 if (stack == null) {
5182 if (DEBUG_STACK) Slog.i(TAG_WM, "moveTaskToStack: could not find stackId=" + stackId);
5185 task.moveTaskToStack(stack, toTop);
5186 final DisplayContent displayContent = stack.getDisplayContent();
5187 displayContent.layoutNeeded = true;
5188 mWindowPlacerLocked.performSurfacePlacement();
5192 public void getStackDockedModeBounds(int stackId, Rect bounds, boolean ignoreVisibility) {
5193 synchronized (mWindowMap) {
5194 final TaskStack stack = mStackIdToStack.get(stackId);
5195 if (stack != null) {
5196 stack.getStackDockedModeBoundsLocked(bounds, ignoreVisibility);
5204 public void getStackBounds(int stackId, Rect bounds) {
5205 synchronized (mWindowMap) {
5206 final TaskStack stack = mStackIdToStack.get(stackId);
5207 if (stack != null) {
5208 stack.getBounds(bounds);
5216 * Re-sizes a stack and its containing tasks.
5217 * @param stackId Id of stack to resize.
5218 * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen.
5219 * @param configs Configurations for tasks in the resized stack, keyed by task id.
5220 * @param taskBounds Bounds for tasks in the resized stack, keyed by task id.
5221 * @return True if the stack is now fullscreen.
5223 public boolean resizeStack(int stackId, Rect bounds,
5224 SparseArray<Configuration> configs, SparseArray<Rect> taskBounds,
5225 SparseArray<Rect> taskTempInsetBounds) {
5226 synchronized (mWindowMap) {
5227 final TaskStack stack = mStackIdToStack.get(stackId);
5228 if (stack == null) {
5229 throw new IllegalArgumentException("resizeStack: stackId " + stackId
5232 if (stack.setBounds(bounds, configs, taskBounds, taskTempInsetBounds)
5233 && stack.isVisibleLocked()) {
5234 stack.getDisplayContent().layoutNeeded = true;
5235 mWindowPlacerLocked.performSurfacePlacement();
5237 return stack.getRawFullscreen();
5241 public void prepareFreezingTaskBounds(int stackId) {
5242 synchronized (mWindowMap) {
5243 final TaskStack stack = mStackIdToStack.get(stackId);
5244 if (stack == null) {
5245 throw new IllegalArgumentException("prepareFreezingTaskBounds: stackId " + stackId
5248 stack.prepareFreezingTaskBounds();
5252 public void positionTaskInStack(int taskId, int stackId, int position, Rect bounds,
5253 Configuration config) {
5254 synchronized (mWindowMap) {
5255 if (DEBUG_STACK) Slog.i(TAG_WM, "positionTaskInStack: positioning taskId=" + taskId
5256 + " in stackId=" + stackId + " at " + position);
5257 Task task = mTaskIdToTask.get(taskId);
5259 if (DEBUG_STACK) Slog.i(TAG_WM,
5260 "positionTaskInStack: could not find taskId=" + taskId);
5263 TaskStack stack = mStackIdToStack.get(stackId);
5264 if (stack == null) {
5265 if (DEBUG_STACK) Slog.i(TAG_WM,
5266 "positionTaskInStack: could not find stackId=" + stackId);
5269 task.positionTaskInStack(stack, position, bounds, config);
5270 final DisplayContent displayContent = stack.getDisplayContent();
5271 displayContent.layoutNeeded = true;
5272 mWindowPlacerLocked.performSurfacePlacement();
5277 * Re-sizes the specified task and its containing windows.
5278 * Returns a {@link Configuration} object that contains configurations settings
5279 * that should be overridden due to the operation.
5281 public void resizeTask(int taskId, Rect bounds, Configuration configuration,
5282 boolean relayout, boolean forced) {
5283 synchronized (mWindowMap) {
5284 Task task = mTaskIdToTask.get(taskId);
5286 throw new IllegalArgumentException("resizeTask: taskId " + taskId
5290 if (task.resizeLocked(bounds, configuration, forced) && relayout) {
5291 task.getDisplayContent().layoutNeeded = true;
5292 mWindowPlacerLocked.performSurfacePlacement();
5298 * Puts a specific task into docked drag resizing mode. See {@link DragResizeMode}.
5300 * @param taskId The id of the task to put into drag resize mode.
5301 * @param resizing Whether to put the task into drag resize mode.
5303 public void setTaskDockedResizing(int taskId, boolean resizing) {
5304 synchronized (mWindowMap) {
5305 Task task = mTaskIdToTask.get(taskId);
5307 Slog.w(TAG, "setTaskDockedResizing: taskId " + taskId + " not found.");
5310 task.setDragResizing(resizing, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
5314 public void scrollTask(int taskId, Rect bounds) {
5315 synchronized (mWindowMap) {
5316 Task task = mTaskIdToTask.get(taskId);
5318 throw new IllegalArgumentException("scrollTask: taskId " + taskId
5322 if (task.scrollLocked(bounds)) {
5323 task.getDisplayContent().layoutNeeded = true;
5324 mInputMonitor.setUpdateInputWindowsNeededLw();
5325 mWindowPlacerLocked.performSurfacePlacement();
5330 * Starts deferring layout passes. Useful when doing multiple changes but to optimize
5331 * performance, only one layout pass should be done. This can be called multiple times, and
5332 * layouting will be resumed once the last caller has called {@link #continueSurfaceLayout}
5334 public void deferSurfaceLayout() {
5335 synchronized (mWindowMap) {
5336 mWindowPlacerLocked.deferLayout();
5341 * Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()}
5343 public void continueSurfaceLayout() {
5344 synchronized (mWindowMap) {
5345 mWindowPlacerLocked.continueLayout();
5349 public void getTaskBounds(int taskId, Rect bounds) {
5350 synchronized (mWindowMap) {
5351 Task task = mTaskIdToTask.get(taskId);
5353 task.getBounds(bounds);
5360 /** Return true if the input task id represents a valid window manager task. */
5361 public boolean isValidTaskId(int taskId) {
5362 synchronized (mWindowMap) {
5363 return mTaskIdToTask.get(taskId) != null;
5367 // -------------------------------------------------------------
5368 // Misc IWindowSession methods
5369 // -------------------------------------------------------------
5372 public void startFreezingScreen(int exitAnim, int enterAnim) {
5373 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5374 "startFreezingScreen()")) {
5375 throw new SecurityException("Requires FREEZE_SCREEN permission");
5378 synchronized(mWindowMap) {
5379 if (!mClientFreezingScreen) {
5380 mClientFreezingScreen = true;
5381 final long origId = Binder.clearCallingIdentity();
5383 startFreezingDisplayLocked(false, exitAnim, enterAnim);
5384 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
5385 mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
5387 Binder.restoreCallingIdentity(origId);
5394 public void stopFreezingScreen() {
5395 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5396 "stopFreezingScreen()")) {
5397 throw new SecurityException("Requires FREEZE_SCREEN permission");
5400 synchronized(mWindowMap) {
5401 if (mClientFreezingScreen) {
5402 mClientFreezingScreen = false;
5403 mLastFinishedFreezeSource = "client";
5404 final long origId = Binder.clearCallingIdentity();
5406 stopFreezingDisplayLocked();
5408 Binder.restoreCallingIdentity(origId);
5415 public void disableKeyguard(IBinder token, String tag) {
5416 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5417 != PackageManager.PERMISSION_GRANTED) {
5418 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5420 // If this isn't coming from the system then don't allow disabling the lockscreen
5421 // to bypass security.
5422 if (Binder.getCallingUid() != Process.SYSTEM_UID && isKeyguardSecure()) {
5423 Log.d(TAG_WM, "current mode is SecurityMode, ignore disableKeyguard");
5427 // If this isn't coming from the current user, ignore it.
5428 if (Binder.getCallingUserHandle().getIdentifier() != mCurrentUserId) {
5429 Log.d(TAG_WM, "non-current user, ignore disableKeyguard");
5433 if (token == null) {
5434 throw new IllegalArgumentException("token == null");
5437 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5438 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
5442 public void reenableKeyguard(IBinder token) {
5443 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5444 != PackageManager.PERMISSION_GRANTED) {
5445 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5448 if (token == null) {
5449 throw new IllegalArgumentException("token == null");
5452 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5453 KeyguardDisableHandler.KEYGUARD_REENABLE, token));
5457 * @see android.app.KeyguardManager#exitKeyguardSecurely
5460 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
5461 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5462 != PackageManager.PERMISSION_GRANTED) {
5463 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5466 if (callback == null) {
5467 throw new IllegalArgumentException("callback == null");
5470 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
5472 public void onKeyguardExitResult(boolean success) {
5474 callback.onKeyguardExitResult(success);
5475 } catch (RemoteException e) {
5476 // Client has died, we don't care.
5483 public boolean inKeyguardRestrictedInputMode() {
5484 return mPolicy.inKeyguardRestrictedKeyInputMode();
5488 public boolean isKeyguardLocked() {
5489 return mPolicy.isKeyguardLocked();
5493 public boolean isKeyguardSecure() {
5494 int userId = UserHandle.getCallingUserId();
5495 long origId = Binder.clearCallingIdentity();
5497 return mPolicy.isKeyguardSecure(userId);
5499 Binder.restoreCallingIdentity(origId);
5504 public void dismissKeyguard() {
5505 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5506 != PackageManager.PERMISSION_GRANTED) {
5507 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5509 synchronized(mWindowMap) {
5510 mPolicy.dismissKeyguardLw();
5515 public void keyguardGoingAway(int flags) {
5516 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5517 != PackageManager.PERMISSION_GRANTED) {
5518 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5520 if (DEBUG_KEYGUARD) Slog.d(TAG_WM,
5521 "keyguardGoingAway: flags=0x" + Integer.toHexString(flags));
5522 synchronized (mWindowMap) {
5523 mAnimator.mKeyguardGoingAway = true;
5524 mAnimator.mKeyguardGoingAwayFlags = flags;
5525 mWindowPlacerLocked.requestTraversal();
5529 public void keyguardWaitingForActivityDrawn() {
5530 if (DEBUG_KEYGUARD) Slog.d(TAG_WM, "keyguardWaitingForActivityDrawn");
5531 synchronized (mWindowMap) {
5532 mKeyguardWaitingForActivityDrawn = true;
5536 public void notifyActivityDrawnForKeyguard() {
5537 if (DEBUG_KEYGUARD) Slog.d(TAG_WM, "notifyActivityDrawnForKeyguard: waiting="
5538 + mKeyguardWaitingForActivityDrawn + " Callers=" + Debug.getCallers(5));
5539 synchronized (mWindowMap) {
5540 if (mKeyguardWaitingForActivityDrawn) {
5541 mPolicy.notifyActivityDrawnForKeyguardLw();
5542 mKeyguardWaitingForActivityDrawn = false;
5547 void showGlobalActions() {
5548 mPolicy.showGlobalActions();
5552 public void closeSystemDialogs(String reason) {
5553 synchronized(mWindowMap) {
5554 final int numDisplays = mDisplayContents.size();
5555 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5556 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5557 final int numWindows = windows.size();
5558 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5559 final WindowState w = windows.get(winNdx);
5560 if (w.mHasSurface) {
5562 w.mClient.closeSystemDialogs(reason);
5563 } catch (RemoteException e) {
5571 static float fixScale(float scale) {
5572 if (scale < 0) scale = 0;
5573 else if (scale > 20) scale = 20;
5574 return Math.abs(scale);
5578 public void setAnimationScale(int which, float scale) {
5579 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5580 "setAnimationScale()")) {
5581 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5584 scale = fixScale(scale);
5586 case 0: mWindowAnimationScaleSetting = scale; break;
5587 case 1: mTransitionAnimationScaleSetting = scale; break;
5588 case 2: mAnimatorDurationScaleSetting = scale; break;
5592 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5596 public void setAnimationScales(float[] scales) {
5597 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5598 "setAnimationScale()")) {
5599 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5602 if (scales != null) {
5603 if (scales.length >= 1) {
5604 mWindowAnimationScaleSetting = fixScale(scales[0]);
5606 if (scales.length >= 2) {
5607 mTransitionAnimationScaleSetting = fixScale(scales[1]);
5609 if (scales.length >= 3) {
5610 mAnimatorDurationScaleSetting = fixScale(scales[2]);
5611 dispatchNewAnimatorScaleLocked(null);
5616 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5619 private void setAnimatorDurationScale(float scale) {
5620 mAnimatorDurationScaleSetting = scale;
5621 ValueAnimator.setDurationScale(scale);
5624 public float getWindowAnimationScaleLocked() {
5625 return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting;
5628 public float getTransitionAnimationScaleLocked() {
5629 return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting;
5633 public float getAnimationScale(int which) {
5635 case 0: return mWindowAnimationScaleSetting;
5636 case 1: return mTransitionAnimationScaleSetting;
5637 case 2: return mAnimatorDurationScaleSetting;
5643 public float[] getAnimationScales() {
5644 return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting,
5645 mAnimatorDurationScaleSetting };
5649 public float getCurrentAnimatorScale() {
5650 synchronized(mWindowMap) {
5651 return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting;
5655 void dispatchNewAnimatorScaleLocked(Session session) {
5656 mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget();
5660 public void registerPointerEventListener(PointerEventListener listener) {
5661 mPointerEventDispatcher.registerInputEventListener(listener);
5665 public void unregisterPointerEventListener(PointerEventListener listener) {
5666 mPointerEventDispatcher.unregisterInputEventListener(listener);
5669 // Called by window manager policy. Not exposed externally.
5671 public int getLidState() {
5672 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5673 InputManagerService.SW_LID);
5675 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5677 } else if (sw == 0) {
5678 // Switch state: AKEY_STATE_UP.
5681 // Switch state: AKEY_STATE_UNKNOWN.
5686 // Called by window manager policy. Not exposed externally.
5688 public void lockDeviceNow() {
5692 // Called by window manager policy. Not exposed externally.
5694 public int getCameraLensCoverState() {
5695 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5696 InputManagerService.SW_CAMERA_LENS_COVER);
5698 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5699 return CAMERA_LENS_COVERED;
5700 } else if (sw == 0) {
5701 // Switch state: AKEY_STATE_UP.
5702 return CAMERA_LENS_UNCOVERED;
5704 // Switch state: AKEY_STATE_UNKNOWN.
5705 return CAMERA_LENS_COVER_ABSENT;
5709 // Called by window manager policy. Not exposed externally.
5711 public void switchInputMethod(boolean forwardDirection) {
5712 final InputMethodManagerInternal inputMethodManagerInternal =
5713 LocalServices.getService(InputMethodManagerInternal.class);
5714 if (inputMethodManagerInternal != null) {
5715 inputMethodManagerInternal.switchInputMethod(forwardDirection);
5719 // Called by window manager policy. Not exposed externally.
5721 public void shutdown(boolean confirm) {
5722 ShutdownThread.shutdown(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
5725 // Called by window manager policy. Not exposed externally.
5727 public void reboot(boolean confirm) {
5728 ShutdownThread.reboot(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
5731 // Called by window manager policy. Not exposed externally.
5733 public void rebootSafeMode(boolean confirm) {
5734 ShutdownThread.rebootSafeMode(mContext, confirm);
5737 public void setCurrentProfileIds(final int[] currentProfileIds) {
5738 synchronized (mWindowMap) {
5739 mCurrentProfileIds = currentProfileIds;
5743 public void setCurrentUser(final int newUserId, final int[] currentProfileIds) {
5744 synchronized (mWindowMap) {
5745 mCurrentUserId = newUserId;
5746 mCurrentProfileIds = currentProfileIds;
5747 mAppTransition.setCurrentUser(newUserId);
5748 mPolicy.setCurrentUserLw(newUserId);
5750 // If keyguard was disabled, re-enable it
5751 // TODO: Keep track of keyguardEnabled state per user and use here...
5752 // e.g. enabled = mKeyguardDisableHandler.getEnabledStateForUser(newUserId);
5753 mPolicy.enableKeyguard(true);
5755 // Hide windows that should not be seen by the new user.
5756 final int numDisplays = mDisplayContents.size();
5757 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5758 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
5759 displayContent.switchUserStacks();
5760 rebuildAppWindowListLocked(displayContent);
5762 mWindowPlacerLocked.performSurfacePlacement();
5764 // Notify whether the docked stack exists for the current user
5765 final DisplayContent displayContent = getDefaultDisplayContentLocked();
5766 displayContent.mDividerControllerLocked
5767 .notifyDockedStackExistsChanged(hasDockedTasksForUser(newUserId));
5769 // If the display is already prepared, update the density.
5770 // Otherwise, we'll update it when it's prepared.
5771 if (mDisplayReady) {
5772 final int forcedDensity = getForcedDisplayDensityForUserLocked(newUserId);
5773 final int targetDensity = forcedDensity != 0 ? forcedDensity
5774 : displayContent.mInitialDisplayDensity;
5775 setForcedDisplayDensityLocked(displayContent, targetDensity);
5781 * Returns whether there is a docked task for the current user.
5783 boolean hasDockedTasksForUser(int userId) {
5784 final TaskStack stack = mStackIdToStack.get(DOCKED_STACK_ID);
5785 if (stack == null) {
5789 final ArrayList<Task> tasks = stack.getTasks();
5790 boolean hasUserTask = false;
5791 for (int i = tasks.size() - 1; i >= 0 && !hasUserTask; i--) {
5792 final Task task = tasks.get(i);
5793 hasUserTask = (task.mUserId == userId);
5798 /* Called by WindowState */
5799 boolean isCurrentProfileLocked(int userId) {
5800 if (userId == mCurrentUserId) return true;
5801 for (int i = 0; i < mCurrentProfileIds.length; i++) {
5802 if (mCurrentProfileIds[i] == userId) return true;
5807 public void enableScreenAfterBoot() {
5808 synchronized(mWindowMap) {
5810 RuntimeException here = new RuntimeException("here");
5811 here.fillInStackTrace();
5812 Slog.i(TAG_WM, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
5813 + " mForceDisplayEnabled=" + mForceDisplayEnabled
5814 + " mShowingBootMessages=" + mShowingBootMessages
5815 + " mSystemBooted=" + mSystemBooted, here);
5817 if (mSystemBooted) {
5820 mSystemBooted = true;
5821 hideBootMessagesLocked();
5822 // If the screen still doesn't come up after 30 seconds, give
5823 // up and turn it on.
5824 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
5827 mPolicy.systemBooted();
5829 performEnableScreen();
5833 public void enableScreenIfNeeded() {
5834 synchronized (mWindowMap) {
5835 enableScreenIfNeededLocked();
5839 void enableScreenIfNeededLocked() {
5841 RuntimeException here = new RuntimeException("here");
5842 here.fillInStackTrace();
5843 Slog.i(TAG_WM, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
5844 + " mForceDisplayEnabled=" + mForceDisplayEnabled
5845 + " mShowingBootMessages=" + mShowingBootMessages
5846 + " mSystemBooted=" + mSystemBooted, here);
5848 if (mDisplayEnabled) {
5851 if (!mSystemBooted && !mShowingBootMessages) {
5854 mH.sendEmptyMessage(H.ENABLE_SCREEN);
5857 public void performBootTimeout() {
5858 synchronized(mWindowMap) {
5859 if (mDisplayEnabled) {
5862 Slog.w(TAG_WM, "***** BOOT TIMEOUT: forcing display enabled");
5863 mForceDisplayEnabled = true;
5865 performEnableScreen();
5868 private boolean checkWaitingForWindowsLocked() {
5870 boolean haveBootMsg = false;
5871 boolean haveApp = false;
5872 // if the wallpaper service is disabled on the device, we're never going to have
5873 // wallpaper, don't bother waiting for it
5874 boolean haveWallpaper = false;
5875 boolean wallpaperEnabled = mContext.getResources().getBoolean(
5876 com.android.internal.R.bool.config_enableWallpaperService)
5878 boolean haveKeyguard = true;
5879 // TODO(multidisplay): Expand to all displays?
5880 final WindowList windows = getDefaultWindowListLocked();
5881 final int N = windows.size();
5882 for (int i=0; i<N; i++) {
5883 WindowState w = windows.get(i);
5884 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
5887 if (w.isDrawnLw()) {
5888 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
5890 } else if (w.mAttrs.type == TYPE_APPLICATION
5891 || w.mAttrs.type == TYPE_DRAWN_APPLICATION) {
5893 } else if (w.mAttrs.type == TYPE_WALLPAPER) {
5894 haveWallpaper = true;
5895 } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
5896 haveKeyguard = mPolicy.isKeyguardDrawnLw();
5901 if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
5902 Slog.i(TAG_WM, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
5903 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
5904 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
5905 + " haveKeyguard=" + haveKeyguard);
5908 // If we are turning on the screen to show the boot message,
5909 // don't do it until the boot message is actually displayed.
5910 if (!mSystemBooted && !haveBootMsg) {
5914 // If we are turning on the screen after the boot is completed
5915 // normally, don't do so until we have the application and
5917 if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
5918 (wallpaperEnabled && !haveWallpaper))) {
5925 public void performEnableScreen() {
5926 synchronized(mWindowMap) {
5927 if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
5928 + " mForceDisplayEnabled=" + mForceDisplayEnabled
5929 + " mShowingBootMessages=" + mShowingBootMessages
5930 + " mSystemBooted=" + mSystemBooted
5931 + " mOnlyCore=" + mOnlyCore,
5932 new RuntimeException("here").fillInStackTrace());
5933 if (mDisplayEnabled) {
5936 if (!mSystemBooted && !mShowingBootMessages) {
5940 // Don't enable the screen until all existing windows have been drawn.
5941 if (!mForceDisplayEnabled && checkWaitingForWindowsLocked()) {
5945 if (!mBootAnimationStopped) {
5946 // Do this one time.
5947 Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
5949 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
5950 if (surfaceFlinger != null) {
5951 //Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
5952 Parcel data = Parcel.obtain();
5953 data.writeInterfaceToken("android.ui.ISurfaceComposer");
5954 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
5958 } catch (RemoteException ex) {
5959 Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!");
5961 mBootAnimationStopped = true;
5964 if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {
5965 if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: Waiting for anim complete");
5969 EventLog.writeEvent(EventLogTags.WM_BOOT_ANIMATION_DONE, SystemClock.uptimeMillis());
5970 Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
5971 mDisplayEnabled = true;
5972 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, "******************** ENABLING SCREEN!");
5974 // Enable input dispatch.
5975 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
5979 mActivityManager.bootAnimationComplete();
5980 } catch (RemoteException e) {
5983 mPolicy.enableScreenAfterBoot();
5985 // Make sure the last requested orientation has been applied.
5986 updateRotationUnchecked(false, false);
5989 private boolean checkBootAnimationCompleteLocked() {
5990 if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) {
5991 mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED);
5992 mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED,
5993 BOOT_ANIMATION_POLL_INTERVAL);
5994 if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Waiting for anim complete");
5997 if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Animation complete!");
6001 public void showBootMessage(final CharSequence msg, final boolean always) {
6002 boolean first = false;
6003 synchronized(mWindowMap) {
6005 RuntimeException here = new RuntimeException("here");
6006 here.fillInStackTrace();
6007 Slog.i(TAG_WM, "showBootMessage: msg=" + msg + " always=" + always
6008 + " mAllowBootMessages=" + mAllowBootMessages
6009 + " mShowingBootMessages=" + mShowingBootMessages
6010 + " mSystemBooted=" + mSystemBooted, here);
6012 if (!mAllowBootMessages) {
6015 if (!mShowingBootMessages) {
6021 if (mSystemBooted) {
6024 mShowingBootMessages = true;
6025 mPolicy.showBootMessage(msg, always);
6028 performEnableScreen();
6032 public void hideBootMessagesLocked() {
6034 RuntimeException here = new RuntimeException("here");
6035 here.fillInStackTrace();
6036 Slog.i(TAG_WM, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
6037 + " mForceDisplayEnabled=" + mForceDisplayEnabled
6038 + " mShowingBootMessages=" + mShowingBootMessages
6039 + " mSystemBooted=" + mSystemBooted, here);
6041 if (mShowingBootMessages) {
6042 mShowingBootMessages = false;
6043 mPolicy.hideBootMessages();
6048 public void setInTouchMode(boolean mode) {
6049 synchronized(mWindowMap) {
6050 mInTouchMode = mode;
6054 private void updateCircularDisplayMaskIfNeeded() {
6055 // we're fullscreen and not hosted in an ActivityView
6056 if (mContext.getResources().getConfiguration().isScreenRound()
6057 && mContext.getResources().getBoolean(
6058 com.android.internal.R.bool.config_windowShowCircularMask)) {
6059 final int currentUserId;
6060 synchronized(mWindowMap) {
6061 currentUserId = mCurrentUserId;
6063 // Device configuration calls for a circular display mask, but we only enable the mask
6064 // if the accessibility color inversion feature is disabled, as the inverted mask
6065 // causes artifacts.
6066 int inversionState = Settings.Secure.getIntForUser(mContext.getContentResolver(),
6067 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, currentUserId);
6068 int showMask = (inversionState == 1) ? 0 : 1;
6069 Message m = mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK);
6075 public void showEmulatorDisplayOverlayIfNeeded() {
6076 if (mContext.getResources().getBoolean(
6077 com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay)
6078 && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false)
6079 && Build.IS_EMULATOR) {
6080 mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY));
6084 public void showCircularMask(boolean visible) {
6085 synchronized(mWindowMap) {
6087 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
6088 ">>> OPEN TRANSACTION showCircularMask(visible=" + visible + ")");
6089 SurfaceControl.openTransaction();
6092 // TODO(multi-display): support multiple displays
6093 if (mCircularDisplayMask == null) {
6094 int screenOffset = mContext.getResources().getInteger(
6095 com.android.internal.R.integer.config_windowOutsetBottom);
6096 int maskThickness = mContext.getResources().getDimensionPixelSize(
6097 com.android.internal.R.dimen.circular_display_mask_thickness);
6099 mCircularDisplayMask = new CircularDisplayMask(
6100 getDefaultDisplayContentLocked().getDisplay(),
6102 mPolicy.windowTypeToLayerLw(
6103 WindowManager.LayoutParams.TYPE_POINTER)
6104 * TYPE_LAYER_MULTIPLIER + 10, screenOffset, maskThickness);
6106 mCircularDisplayMask.setVisibility(true);
6107 } else if (mCircularDisplayMask != null) {
6108 mCircularDisplayMask.setVisibility(false);
6109 mCircularDisplayMask = null;
6112 SurfaceControl.closeTransaction();
6113 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
6114 "<<< CLOSE TRANSACTION showCircularMask(visible=" + visible + ")");
6119 public void showEmulatorDisplayOverlay() {
6120 synchronized(mWindowMap) {
6122 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
6123 ">>> OPEN TRANSACTION showEmulatorDisplayOverlay");
6124 SurfaceControl.openTransaction();
6126 if (mEmulatorDisplayOverlay == null) {
6127 mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(
6129 getDefaultDisplayContentLocked().getDisplay(),
6131 mPolicy.windowTypeToLayerLw(
6132 WindowManager.LayoutParams.TYPE_POINTER)
6133 * TYPE_LAYER_MULTIPLIER + 10);
6135 mEmulatorDisplayOverlay.setVisibility(true);
6137 SurfaceControl.closeTransaction();
6138 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
6139 "<<< CLOSE TRANSACTION showEmulatorDisplayOverlay");
6144 // TODO: more accounting of which pid(s) turned it on, keep count,
6145 // only allow disables from pids which have count on, etc.
6147 public void showStrictModeViolation(boolean on) {
6148 int pid = Binder.getCallingPid();
6149 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
6152 private void showStrictModeViolation(int arg, int pid) {
6153 final boolean on = arg != 0;
6154 synchronized(mWindowMap) {
6155 // Ignoring requests to enable the red border from clients
6156 // which aren't on screen. (e.g. Broadcast Receivers in
6157 // the background..)
6159 boolean isVisible = false;
6160 final int numDisplays = mDisplayContents.size();
6161 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6162 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
6163 final int numWindows = windows.size();
6164 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
6165 final WindowState ws = windows.get(winNdx);
6166 if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
6177 if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
6178 ">>> OPEN TRANSACTION showStrictModeViolation");
6179 SurfaceControl.openTransaction();
6181 // TODO(multi-display): support multiple displays
6182 if (mStrictModeFlash == null) {
6183 mStrictModeFlash = new StrictModeFlash(
6184 getDefaultDisplayContentLocked().getDisplay(), mFxSession);
6186 mStrictModeFlash.setVisibility(on);
6188 SurfaceControl.closeTransaction();
6189 if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
6190 "<<< CLOSE TRANSACTION showStrictModeViolation");
6196 public void setStrictModeVisualIndicatorPreference(String value) {
6197 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
6200 private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) {
6201 if (rot == Surface.ROTATION_90) {
6202 final int tmp = crop.top;
6203 crop.top = dw - crop.right;
6204 crop.right = crop.bottom;
6205 crop.bottom = dw - crop.left;
6207 } else if (rot == Surface.ROTATION_180) {
6209 crop.top = dh - crop.bottom;
6210 crop.bottom = dh - tmp;
6212 crop.right = dw - crop.left;
6213 crop.left = dw - tmp;
6214 } else if (rot == Surface.ROTATION_270) {
6215 final int tmp = crop.top;
6216 crop.top = crop.left;
6217 crop.left = dh - crop.bottom;
6218 crop.bottom = crop.right;
6219 crop.right = dh - tmp;
6224 public Bitmap screenshotWallpaper() {
6225 if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
6226 "screenshotWallpaper()")) {
6227 throw new SecurityException("Requires READ_FRAME_BUFFER permission");
6230 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper");
6231 return screenshotApplicationsInner(null, Display.DEFAULT_DISPLAY, -1, -1, true, 1f,
6232 Bitmap.Config.ARGB_8888, true);
6234 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
6239 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
6240 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
6241 * of the target image.
6244 public boolean requestAssistScreenshot(final IAssistScreenshotReceiver receiver) {
6245 if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
6246 "requestAssistScreenshot()")) {
6247 throw new SecurityException("Requires READ_FRAME_BUFFER permission");
6250 FgThread.getHandler().post(new Runnable() {
6253 Bitmap bm = screenshotApplicationsInner(null, Display.DEFAULT_DISPLAY, -1, -1,
6254 true, 1f, Bitmap.Config.ARGB_8888, false);
6257 } catch (RemoteException e) {
6266 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
6267 * In portrait mode, it grabs the full screenshot.
6269 * @param displayId the Display to take a screenshot of.
6270 * @param width the width of the target bitmap
6271 * @param height the height of the target bitmap
6272 * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
6275 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height,
6277 if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
6278 "screenshotApplications()")) {
6279 throw new SecurityException("Requires READ_FRAME_BUFFER permission");
6282 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotApplications");
6283 return screenshotApplicationsInner(appToken, displayId, width, height, false,
6284 frameScale, Bitmap.Config.RGB_565, false);
6286 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
6291 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
6292 * In portrait mode, it grabs the full screenshot.
6294 * @param displayId the Display to take a screenshot of.
6295 * @param width the width of the target bitmap
6296 * @param height the height of the target bitmap
6297 * @param includeFullDisplay true if the screen should not be cropped before capture
6298 * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
6299 * @param config of the output bitmap
6300 * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
6302 Bitmap screenshotApplicationsInner(IBinder appToken, int displayId, int width, int height,
6303 boolean includeFullDisplay, float frameScale, Bitmap.Config config,
6304 boolean wallpaperOnly) {
6305 final DisplayContent displayContent;
6306 synchronized(mWindowMap) {
6307 displayContent = getDisplayContentLocked(displayId);
6308 if (displayContent == null) {
6309 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
6310 + ": returning null. No Display for displayId=" + displayId);
6314 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6315 int dw = displayInfo.logicalWidth;
6316 int dh = displayInfo.logicalHeight;
6317 if (dw == 0 || dh == 0) {
6318 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
6319 + ": returning null. logical widthxheight=" + dw + "x" + dh);
6326 final Rect frame = new Rect();
6327 final Rect stackBounds = new Rect();
6329 boolean screenshotReady;
6331 if (appToken == null && !wallpaperOnly) {
6332 screenshotReady = true;
6335 screenshotReady = false;
6336 minLayer = Integer.MAX_VALUE;
6339 WindowState appWin = null;
6341 boolean includeImeInScreenshot;
6342 synchronized(mWindowMap) {
6343 final AppWindowToken imeTargetAppToken =
6344 mInputMethodTarget != null ? mInputMethodTarget.mAppToken : null;
6345 // We only include the Ime in the screenshot if the app we are screenshoting is the IME
6346 // target and isn't in multi-window mode. We don't screenshot the IME in multi-window
6347 // mode because the frame of the IME might not overlap with that of the app.
6348 // E.g. IME target app at the top in split-screen mode and the IME at the bottom
6349 // overlapping with the bottom app.
6350 includeImeInScreenshot = imeTargetAppToken != null
6351 && imeTargetAppToken.appToken != null
6352 && imeTargetAppToken.appToken.asBinder() == appToken
6353 && !mInputMethodTarget.isInMultiWindowMode();
6356 final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1)
6357 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
6359 synchronized(mWindowMap) {
6360 // Figure out the part of the screen that is actually the app.
6362 final WindowList windows = displayContent.getWindowList();
6363 for (int i = windows.size() - 1; i >= 0; i--) {
6364 WindowState ws = windows.get(i);
6365 if (!ws.mHasSurface) {
6368 if (ws.mLayer >= aboveAppLayer) {
6371 if (wallpaperOnly && !ws.mIsWallpaper) {
6374 if (ws.mIsImWindow) {
6375 if (!includeImeInScreenshot) {
6378 } else if (ws.mIsWallpaper) {
6379 // If this is the wallpaper layer and we're only looking for the wallpaper layer
6380 // then the target window state is this one.
6381 if (wallpaperOnly) {
6385 if (appWin == null) {
6386 // We have not ran across the target window yet, so it is probably
6387 // behind the wallpaper. This can happen when the keyguard is up and
6388 // all windows are moved behind the wallpaper. We don't want to
6389 // include the wallpaper layer in the screenshot as it will coverup
6390 // the layer of the target window.
6393 // Fall through. The target window is in front of the wallpaper. For this
6394 // case we want to include the wallpaper layer in the screenshot because
6395 // the target window might have some transparent areas.
6396 } else if (appToken != null) {
6397 if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
6398 // This app window is of no interest if it is not associated with the
6405 // Include this window.
6407 final WindowStateAnimator winAnim = ws.mWinAnimator;
6408 int layer = winAnim.mSurfaceController.getLayer();
6409 if (maxLayer < layer) {
6412 if (minLayer > layer) {
6416 // Don't include wallpaper in bounds calculation
6417 if (!includeFullDisplay && !ws.mIsWallpaper) {
6418 final Rect wf = ws.mFrame;
6419 final Rect cr = ws.mContentInsets;
6420 int left = wf.left + cr.left;
6421 int top = wf.top + cr.top;
6422 int right = wf.right - cr.right;
6423 int bottom = wf.bottom - cr.bottom;
6424 frame.union(left, top, right, bottom);
6425 ws.getVisibleBounds(stackBounds);
6426 if (!Rect.intersects(frame, stackBounds)) {
6427 // Set frame empty if there's no intersection.
6432 final boolean foundTargetWs =
6433 (ws.mAppToken != null && ws.mAppToken.token == appToken)
6434 || (appWin != null && wallpaperOnly);
6435 if (foundTargetWs && ws.isDisplayedLw() && winAnim.getShown()) {
6436 screenshotReady = true;
6439 if (ws.isObscuringFullscreen(displayInfo)){
6444 if (appToken != null && appWin == null) {
6445 // Can't find a window to snapshot.
6446 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM,
6447 "Screenshot: Couldn't find a surface matching " + appToken);
6451 if (!screenshotReady) {
6452 Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken +
6453 " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" +
6454 appWin.mWinAnimator.mDrawState)));
6458 // Screenshot is ready to be taken. Everything from here below will continue
6459 // through the bottom of the loop and return a value. We only stay in the loop
6460 // because we don't want to release the mWindowMap lock until the screenshot is
6463 if (maxLayer == 0) {
6464 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
6465 + ": returning null maxLayer=" + maxLayer);
6469 if (!includeFullDisplay) {
6470 // Constrain frame to the screen size.
6471 if (!frame.intersect(0, 0, dw, dh)) {
6475 // Caller just wants entire display.
6476 frame.set(0, 0, dw, dh);
6478 if (frame.isEmpty()) {
6483 width = (int) (frame.width() * frameScale);
6486 height = (int) (frame.height() * frameScale);
6489 // Tell surface flinger what part of the image to crop. Take the top
6490 // right part of the application, and crop the larger dimension to fit.
6491 Rect crop = new Rect(frame);
6492 if (width / (float) frame.width() < height / (float) frame.height()) {
6493 int cropWidth = (int)((float)width / (float)height * frame.height());
6494 crop.right = crop.left + cropWidth;
6496 int cropHeight = (int)((float)height / (float)width * frame.width());
6497 crop.bottom = crop.top + cropHeight;
6500 // The screenshot API does not apply the current screen rotation.
6501 int rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
6503 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
6504 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
6507 // Surfaceflinger is not aware of orientation, so convert our logical
6508 // crop to surfaceflinger's portrait orientation.
6509 convertCropForSurfaceFlinger(crop, rot, dw, dh);
6511 if (DEBUG_SCREENSHOT) {
6512 Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
6513 + maxLayer + " appToken=" + appToken);
6514 for (int i = 0; i < windows.size(); i++) {
6515 WindowState win = windows.get(i);
6516 WindowSurfaceController controller = win.mWinAnimator.mSurfaceController;
6517 Slog.i(TAG_WM, win + ": " + win.mLayer
6518 + " animLayer=" + win.mWinAnimator.mAnimLayer
6519 + " surfaceLayer=" + ((controller == null)
6520 ? "null" : controller.getLayer()));
6524 ScreenRotationAnimation screenRotationAnimation =
6525 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6526 final boolean inRotation = screenRotationAnimation != null &&
6527 screenRotationAnimation.isAnimating();
6528 if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM,
6529 "Taking screenshot while rotating");
6531 // We force pending transactions to flush before taking
6532 // the screenshot by pushing an empty synchronous transaction.
6533 SurfaceControl.openTransaction();
6534 SurfaceControl.closeTransactionSync();
6536 bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
6539 Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh
6540 + ") to layer " + maxLayer);
6545 if (DEBUG_SCREENSHOT) {
6546 // TEST IF IT's ALL BLACK
6547 int[] buffer = new int[bm.getWidth() * bm.getHeight()];
6548 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
6549 boolean allBlack = true;
6550 final int firstColor = buffer[0];
6551 for (int i = 0; i < buffer.length; i++) {
6552 if (buffer[i] != firstColor) {
6558 Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" +
6559 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
6561 appWin.mWinAnimator.mSurfaceController.getLayer() : "null") +
6562 " minLayer=" + minLayer + " maxLayer=" + maxLayer);
6566 // Create a copy of the screenshot that is immutable and backed in ashmem.
6567 // This greatly reduces the overhead of passing the bitmap between processes.
6568 Bitmap ret = bm.createAshmemBitmap(config);
6574 * Freeze rotation changes. (Enable "rotation lock".)
6575 * Persists across reboots.
6576 * @param rotation The desired rotation to freeze to, or -1 to use the
6580 public void freezeRotation(int rotation) {
6581 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
6582 "freezeRotation()")) {
6583 throw new SecurityException("Requires SET_ORIENTATION permission");
6585 if (rotation < -1 || rotation > Surface.ROTATION_270) {
6586 throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
6587 + "rotation constant.");
6590 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "freezeRotation: mRotation=" + mRotation);
6592 long origId = Binder.clearCallingIdentity();
6594 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
6595 rotation == -1 ? mRotation : rotation);
6597 Binder.restoreCallingIdentity(origId);
6600 updateRotationUnchecked(false, false);
6604 * Thaw rotation changes. (Disable "rotation lock".)
6605 * Persists across reboots.
6608 public void thawRotation() {
6609 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
6610 "thawRotation()")) {
6611 throw new SecurityException("Requires SET_ORIENTATION permission");
6614 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "thawRotation: mRotation=" + mRotation);
6616 long origId = Binder.clearCallingIdentity();
6618 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
6619 777); // rot not used
6621 Binder.restoreCallingIdentity(origId);
6624 updateRotationUnchecked(false, false);
6628 * Recalculate the current rotation.
6630 * Called by the window manager policy whenever the state of the system changes
6631 * such that the current rotation might need to be updated, such as when the
6632 * device is docked or rotated into a new posture.
6635 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
6636 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
6640 * Temporarily pauses rotation changes until resumed.
6642 * This can be used to prevent rotation changes from occurring while the user is
6643 * performing certain operations, such as drag and drop.
6645 * This call nests and must be matched by an equal number of calls to
6646 * {@link #resumeRotationLocked}.
6648 void pauseRotationLocked() {
6649 mDeferredRotationPauseCount += 1;
6653 * Resumes normal rotation changes after being paused.
6655 void resumeRotationLocked() {
6656 if (mDeferredRotationPauseCount > 0) {
6657 mDeferredRotationPauseCount -= 1;
6658 if (mDeferredRotationPauseCount == 0) {
6659 boolean changed = updateRotationUncheckedLocked(false);
6661 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6667 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
6668 if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked("
6669 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
6671 long origId = Binder.clearCallingIdentity();
6673 synchronized(mWindowMap) {
6674 changed = updateRotationUncheckedLocked(false);
6675 if (!changed || forceRelayout) {
6676 getDefaultDisplayContentLocked().layoutNeeded = true;
6677 mWindowPlacerLocked.performSurfacePlacement();
6681 if (changed || alwaysSendConfiguration) {
6682 sendNewConfiguration();
6685 Binder.restoreCallingIdentity(origId);
6689 // TODO(multidisplay): Rotate any display?
6691 * Updates the current rotation.
6693 * Returns true if the rotation has been changed. In this case YOU
6694 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
6696 public boolean updateRotationUncheckedLocked(boolean inTransaction) {
6697 if (mDeferredRotationPauseCount > 0) {
6698 // Rotation updates have been paused temporarily. Defer the update until
6699 // updates have been resumed.
6700 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused.");
6704 ScreenRotationAnimation screenRotationAnimation =
6705 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6706 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
6707 // Rotation updates cannot be performed while the previous rotation change
6708 // animation is still in progress. Skip this update. We will try updating
6709 // again after the animation is finished and the display is unfrozen.
6710 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress.");
6714 if (!mDisplayEnabled) {
6715 // No point choosing a rotation if the display is not enabled.
6716 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled.");
6720 // TODO: Implement forced rotation changes.
6721 // Set mAltOrientation to indicate that the application is receiving
6722 // an orientation that has different metrics than it expected.
6723 // eg. Portrait instead of Landscape.
6725 int rotation = mPolicy.rotationForOrientationLw(mLastOrientation, mRotation);
6726 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
6727 mLastOrientation, rotation);
6729 if (DEBUG_ORIENTATION) {
6730 Slog.v(TAG_WM, "Selected orientation "
6731 + mLastOrientation + ", got rotation " + rotation
6732 + " which has " + (altOrientation ? "incompatible" : "compatible")
6736 if (mRotation == rotation && mAltOrientation == altOrientation) {
6741 if (DEBUG_ORIENTATION) {
6743 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
6744 + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
6745 + ", lastOrientation=" + mLastOrientation);
6748 int oldRotation = mRotation;
6750 mRotation = rotation;
6751 mAltOrientation = altOrientation;
6752 mPolicy.setRotationLw(mRotation);
6754 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
6755 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
6756 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
6757 mWaitingForConfig = true;
6758 final DisplayContent displayContent = getDefaultDisplayContentLocked();
6759 displayContent.layoutNeeded = true;
6760 final int[] anim = new int[2];
6761 if (displayContent.isDimming()) {
6762 anim[0] = anim[1] = 0;
6764 mPolicy.selectRotationAnimationLw(anim);
6766 boolean rotateSeamlessly = mPolicy.shouldRotateSeamlessly(oldRotation, mRotation);
6767 final WindowList windows = displayContent.getWindowList();
6768 // We can't rotate seamlessly while an existing seamless rotation is still
6769 // waiting on windows to finish drawing.
6770 if (rotateSeamlessly) {
6771 for (int i = windows.size() - 1; i >= 0; i--) {
6772 WindowState w = windows.get(i);
6773 if (w.mSeamlesslyRotated) {
6774 rotateSeamlessly = false;
6777 // In what can only be called an unfortunate workaround we require
6778 // seamlessly rotated child windows to have the TRANSFORM_TO_DISPLAY_INVERSE
6779 // flag. Due to limitations in the client API, there is no way for
6780 // the client to set this flag in a race free fashion. If we seamlessly rotate
6781 // a window which does not have this flag, but then gains it, we will get
6782 // an incorrect visual result (rotated viewfinder). This means if we want to
6783 // support seamlessly rotating windows which could gain this flag, we can't
6784 // rotate windows without it. This limits seamless rotation in N to camera framework
6785 // users, windows without children, and native code. This is unfortunate but
6786 // having the camera work is our primary goal.
6787 if (w.isChildWindow() & w.isVisibleNow() &&
6788 !w.mWinAnimator.mSurfaceController.getTransformToDisplayInverse()) {
6789 rotateSeamlessly = false;
6794 if (!rotateSeamlessly) {
6795 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
6796 // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
6797 screenRotationAnimation =
6798 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6800 // The screen rotation animation uses a screenshot to freeze the screen
6801 // while windows resize underneath.
6802 // When we are rotating seamlessly, we allow the elements to transition
6803 // to their rotated state independently and without a freeze required.
6804 screenRotationAnimation = null;
6807 // We need to update our screen size information to match the new rotation. If the rotation
6808 // has actually changed then this method will return true and, according to the comment at
6809 // the top of the method, the caller is obligated to call computeNewConfigurationLocked().
6810 // By updating the Display info here it will be available to
6811 // computeScreenConfigurationLocked later.
6812 updateDisplayAndOrientationLocked(mCurConfiguration.uiMode);
6814 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6815 if (!inTransaction) {
6816 if (SHOW_TRANSACTIONS) {
6817 Slog.i(TAG_WM, ">>> OPEN TRANSACTION setRotationUnchecked");
6819 SurfaceControl.openTransaction();
6822 // NOTE: We disable the rotation in the emulator because
6823 // it doesn't support hardware OpenGL emulation yet.
6824 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
6825 && screenRotationAnimation.hasScreenshot()) {
6826 if (screenRotationAnimation.setRotationInTransaction(
6827 rotation, mFxSession,
6828 MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(),
6829 displayInfo.logicalWidth, displayInfo.logicalHeight)) {
6830 scheduleAnimationLocked();
6834 if (rotateSeamlessly) {
6835 for (int i = windows.size() - 1; i >= 0; i--) {
6836 WindowState w = windows.get(i);
6837 w.mWinAnimator.seamlesslyRotateWindow(oldRotation, mRotation);
6841 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
6843 if (!inTransaction) {
6844 SurfaceControl.closeTransaction();
6845 if (SHOW_LIGHT_TRANSACTIONS) {
6846 Slog.i(TAG_WM, "<<< CLOSE TRANSACTION setRotationUnchecked");
6851 for (int i = windows.size() - 1; i >= 0; i--) {
6852 WindowState w = windows.get(i);
6853 // Discard surface after orientation change, these can't be reused.
6854 if (w.mAppToken != null) {
6855 w.mAppToken.destroySavedSurfaces();
6857 if (w.mHasSurface && !rotateSeamlessly) {
6858 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
6859 w.mOrientationChanging = true;
6860 mWindowPlacerLocked.mOrientationChangeComplete = false;
6861 w.mLastFreezeDuration = 0;
6864 if (rotateSeamlessly) {
6865 mH.removeMessages(H.SEAMLESS_ROTATION_TIMEOUT);
6866 mH.sendEmptyMessageDelayed(H.SEAMLESS_ROTATION_TIMEOUT, SEAMLESS_ROTATION_TIMEOUT_DURATION);
6869 for (int i=mRotationWatchers.size()-1; i>=0; i--) {
6871 mRotationWatchers.get(i).watcher.onRotationChanged(rotation);
6872 } catch (RemoteException e) {
6876 // TODO (multidisplay): Magnification is supported only for the default display.
6877 // Announce rotation only if we will not animate as we already have the
6878 // windows in final state. Otherwise, we make this call at the rotation end.
6879 if (screenRotationAnimation == null && mAccessibilityController != null
6880 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
6881 mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(),
6889 public int getRotation() {
6894 public boolean isRotationFrozen() {
6895 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
6899 public int watchRotation(IRotationWatcher watcher) {
6900 final IBinder watcherBinder = watcher.asBinder();
6901 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
6903 public void binderDied() {
6904 synchronized (mWindowMap) {
6905 for (int i=0; i<mRotationWatchers.size(); i++) {
6906 if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) {
6907 RotationWatcher removed = mRotationWatchers.remove(i);
6908 IBinder binder = removed.watcher.asBinder();
6909 if (binder != null) {
6910 binder.unlinkToDeath(this, 0);
6919 synchronized (mWindowMap) {
6921 watcher.asBinder().linkToDeath(dr, 0);
6922 mRotationWatchers.add(new RotationWatcher(watcher, dr));
6923 } catch (RemoteException e) {
6924 // Client died, no cleanup needed.
6932 public void removeRotationWatcher(IRotationWatcher watcher) {
6933 final IBinder watcherBinder = watcher.asBinder();
6934 synchronized (mWindowMap) {
6935 for (int i=0; i<mRotationWatchers.size(); i++) {
6936 RotationWatcher rotationWatcher = mRotationWatchers.get(i);
6937 if (watcherBinder == rotationWatcher.watcher.asBinder()) {
6938 RotationWatcher removed = mRotationWatchers.remove(i);
6939 IBinder binder = removed.watcher.asBinder();
6940 if (binder != null) {
6941 binder.unlinkToDeath(removed.deathRecipient, 0);
6950 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
6951 * theme attribute) on devices that feature a physical options menu key attempt to position
6952 * their menu panel window along the edge of the screen nearest the physical menu key.
6953 * This lowers the travel distance between invoking the menu panel and selecting
6956 * This method helps control where that menu is placed. Its current implementation makes
6957 * assumptions about the menu key and its relationship to the screen based on whether
6958 * the device's natural orientation is portrait (width < height) or landscape.
6960 * The menu key is assumed to be located along the bottom edge of natural-portrait
6961 * devices and along the right edge of natural-landscape devices. If these assumptions
6962 * do not hold for the target device, this method should be changed to reflect that.
6964 * @return A {@link Gravity} value for placing the options menu window
6967 public int getPreferredOptionsPanelGravity() {
6968 synchronized (mWindowMap) {
6969 final int rotation = getRotation();
6971 // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
6972 final DisplayContent displayContent = getDefaultDisplayContentLocked();
6973 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
6974 // On devices with a natural orientation of portrait
6977 case Surface.ROTATION_0:
6978 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6979 case Surface.ROTATION_90:
6980 return Gravity.RIGHT | Gravity.BOTTOM;
6981 case Surface.ROTATION_180:
6982 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6983 case Surface.ROTATION_270:
6984 return Gravity.START | Gravity.BOTTOM;
6988 // On devices with a natural orientation of landscape
6991 case Surface.ROTATION_0:
6992 return Gravity.RIGHT | Gravity.BOTTOM;
6993 case Surface.ROTATION_90:
6994 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6995 case Surface.ROTATION_180:
6996 return Gravity.START | Gravity.BOTTOM;
6997 case Surface.ROTATION_270:
6998 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
7004 * Starts the view server on the specified port.
7006 * @param port The port to listener to.
7008 * @return True if the server was successfully started, false otherwise.
7010 * @see com.android.server.wm.ViewServer
7011 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
7014 public boolean startViewServer(int port) {
7015 if (isSystemSecure()) {
7019 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
7027 if (mViewServer != null) {
7028 if (!mViewServer.isRunning()) {
7030 return mViewServer.start();
7031 } catch (IOException e) {
7032 Slog.w(TAG_WM, "View server did not start");
7039 mViewServer = new ViewServer(this, port);
7040 return mViewServer.start();
7041 } catch (IOException e) {
7042 Slog.w(TAG_WM, "View server did not start");
7047 private boolean isSystemSecure() {
7048 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
7049 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
7053 * Stops the view server if it exists.
7055 * @return True if the server stopped, false if it wasn't started or
7056 * couldn't be stopped.
7058 * @see com.android.server.wm.ViewServer
7061 public boolean stopViewServer() {
7062 if (isSystemSecure()) {
7066 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
7070 if (mViewServer != null) {
7071 return mViewServer.stop();
7077 * Indicates whether the view server is running.
7079 * @return True if the server is running, false otherwise.
7081 * @see com.android.server.wm.ViewServer
7084 public boolean isViewServerRunning() {
7085 if (isSystemSecure()) {
7089 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
7093 return mViewServer != null && mViewServer.isRunning();
7097 * Lists all availble windows in the system. The listing is written in the
7098 * specified Socket's output stream with the following syntax:
7099 * windowHashCodeInHexadecimal windowName
7100 * Each line of the ouput represents a different window.
7102 * @param client The remote client to send the listing to.
7103 * @return False if an error occured, true otherwise.
7105 boolean viewServerListWindows(Socket client) {
7106 if (isSystemSecure()) {
7110 boolean result = true;
7112 WindowList windows = new WindowList();
7113 synchronized (mWindowMap) {
7114 //noinspection unchecked
7115 final int numDisplays = mDisplayContents.size();
7116 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
7117 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
7118 windows.addAll(displayContent.getWindowList());
7122 BufferedWriter out = null;
7124 // Any uncaught exception will crash the system process
7126 OutputStream clientStream = client.getOutputStream();
7127 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
7129 final int count = windows.size();
7130 for (int i = 0; i < count; i++) {
7131 final WindowState w = windows.get(i);
7132 out.write(Integer.toHexString(System.identityHashCode(w)));
7134 out.append(w.mAttrs.getTitle());
7138 out.write("DONE.\n");
7140 } catch (Exception e) {
7146 } catch (IOException e) {
7155 // TODO(multidisplay): Extend to multiple displays.
7157 * Returns the focused window in the following format:
7158 * windowHashCodeInHexadecimal windowName
7160 * @param client The remote client to send the listing to.
7161 * @return False if an error occurred, true otherwise.
7163 boolean viewServerGetFocusedWindow(Socket client) {
7164 if (isSystemSecure()) {
7168 boolean result = true;
7170 WindowState focusedWindow = getFocusedWindow();
7172 BufferedWriter out = null;
7174 // Any uncaught exception will crash the system process
7176 OutputStream clientStream = client.getOutputStream();
7177 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
7179 if(focusedWindow != null) {
7180 out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
7182 out.append(focusedWindow.mAttrs.getTitle());
7186 } catch (Exception e) {
7192 } catch (IOException e) {
7202 * Sends a command to a target window. The result of the command, if any, will be
7203 * written in the output stream of the specified socket.
7205 * The parameters must follow this syntax:
7206 * windowHashcode extra
7208 * Where XX is the length in characeters of the windowTitle.
7210 * The first parameter is the target window. The window with the specified hashcode
7211 * will be the target. If no target can be found, nothing happens. The extra parameters
7212 * will be delivered to the target window and as parameters to the command itself.
7214 * @param client The remote client to sent the result, if any, to.
7215 * @param command The command to execute.
7216 * @param parameters The command parameters.
7218 * @return True if the command was successfully delivered, false otherwise. This does
7219 * not indicate whether the command itself was successful.
7221 boolean viewServerWindowCommand(Socket client, String command, String parameters) {
7222 if (isSystemSecure()) {
7226 boolean success = true;
7228 Parcel reply = null;
7230 BufferedWriter out = null;
7232 // Any uncaught exception will crash the system process
7234 // Find the hashcode of the window
7235 int index = parameters.indexOf(' ');
7237 index = parameters.length();
7239 final String code = parameters.substring(0, index);
7240 int hashCode = (int) Long.parseLong(code, 16);
7242 // Extract the command's parameter after the window description
7243 if (index < parameters.length()) {
7244 parameters = parameters.substring(index + 1);
7249 final WindowState window = findWindow(hashCode);
7250 if (window == null) {
7254 data = Parcel.obtain();
7255 data.writeInterfaceToken("android.view.IWindow");
7256 data.writeString(command);
7257 data.writeString(parameters);
7259 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
7261 reply = Parcel.obtain();
7263 final IBinder binder = window.mClient.asBinder();
7264 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
7265 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
7267 reply.readException();
7269 if (!client.isOutputShutdown()) {
7270 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
7271 out.write("DONE\n");
7275 } catch (Exception e) {
7276 Slog.w(TAG_WM, "Could not send command " + command + " with parameters " + parameters, e);
7282 if (reply != null) {
7288 } catch (IOException e) {
7297 public void addWindowChangeListener(WindowChangeListener listener) {
7298 synchronized(mWindowMap) {
7299 mWindowChangeListeners.add(listener);
7303 public void removeWindowChangeListener(WindowChangeListener listener) {
7304 synchronized(mWindowMap) {
7305 mWindowChangeListeners.remove(listener);
7309 private void notifyWindowsChanged() {
7310 WindowChangeListener[] windowChangeListeners;
7311 synchronized(mWindowMap) {
7312 if(mWindowChangeListeners.isEmpty()) {
7315 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
7316 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
7318 int N = windowChangeListeners.length;
7319 for(int i = 0; i < N; i++) {
7320 windowChangeListeners[i].windowsChanged();
7324 private void notifyFocusChanged() {
7325 WindowChangeListener[] windowChangeListeners;
7326 synchronized(mWindowMap) {
7327 if(mWindowChangeListeners.isEmpty()) {
7330 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
7331 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
7333 int N = windowChangeListeners.length;
7334 for(int i = 0; i < N; i++) {
7335 windowChangeListeners[i].focusChanged();
7339 private WindowState findWindow(int hashCode) {
7340 if (hashCode == -1) {
7341 // TODO(multidisplay): Extend to multiple displays.
7342 return getFocusedWindow();
7345 synchronized (mWindowMap) {
7346 final int numDisplays = mDisplayContents.size();
7347 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
7348 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
7349 final int numWindows = windows.size();
7350 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
7351 final WindowState w = windows.get(winNdx);
7352 if (System.identityHashCode(w) == hashCode) {
7363 * Instruct the Activity Manager to fetch the current configuration and broadcast
7364 * that to config-changed listeners if appropriate.
7366 void sendNewConfiguration() {
7368 mActivityManager.updateConfiguration(null);
7369 } catch (RemoteException e) {
7373 public Configuration computeNewConfiguration() {
7374 synchronized (mWindowMap) {
7375 return computeNewConfigurationLocked();
7379 private Configuration computeNewConfigurationLocked() {
7380 if (!mDisplayReady) {
7383 Configuration config = new Configuration();
7384 config.fontScale = 0;
7385 computeScreenConfigurationLocked(config);
7389 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int uiMode,
7391 // TODO: Multidisplay: for now only use with default display.
7392 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode);
7393 if (width < displayInfo.smallestNominalAppWidth) {
7394 displayInfo.smallestNominalAppWidth = width;
7396 if (width > displayInfo.largestNominalAppWidth) {
7397 displayInfo.largestNominalAppWidth = width;
7399 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode);
7400 if (height < displayInfo.smallestNominalAppHeight) {
7401 displayInfo.smallestNominalAppHeight = height;
7403 if (height > displayInfo.largestNominalAppHeight) {
7404 displayInfo.largestNominalAppHeight = height;
7408 private int reduceConfigLayout(int curLayout, int rotation, float density,
7409 int dw, int dh, int uiMode) {
7410 // TODO: Multidisplay: for now only use with default display.
7411 // Get the app screen size at this rotation.
7412 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode);
7413 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode);
7415 // Compute the screen layout size class for this rotation.
7418 if (longSize < shortSize) {
7420 longSize = shortSize;
7423 longSize = (int)(longSize/density);
7424 shortSize = (int)(shortSize/density);
7425 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
7428 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
7429 int uiMode, int dw, int dh, float density, Configuration outConfig) {
7430 // TODO: Multidisplay: for now only use with default display.
7432 // We need to determine the smallest width that will occur under normal
7433 // operation. To this, start with the base screen size and compute the
7434 // width under the different possible rotations. We need to un-rotate
7435 // the current screen dimensions before doing this.
7436 int unrotDw, unrotDh;
7444 displayInfo.smallestNominalAppWidth = 1<<30;
7445 displayInfo.smallestNominalAppHeight = 1<<30;
7446 displayInfo.largestNominalAppWidth = 0;
7447 displayInfo.largestNominalAppHeight = 0;
7448 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, uiMode, unrotDw, unrotDh);
7449 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, uiMode, unrotDh, unrotDw);
7450 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, uiMode, unrotDw, unrotDh);
7451 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, uiMode, unrotDh, unrotDw);
7452 int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
7453 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode);
7454 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode);
7455 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode);
7456 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode);
7457 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
7458 outConfig.screenLayout = sl;
7461 private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode,
7462 DisplayMetrics dm, int dw, int dh) {
7463 // TODO: Multidisplay: for now only use with default display.
7464 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode);
7465 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode);
7466 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
7467 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
7468 if (curSize == 0 || size < curSize) {
7474 private int computeCompatSmallestWidth(boolean rotated, int uiMode, DisplayMetrics dm, int dw, int dh) {
7475 // TODO: Multidisplay: for now only use with default display.
7476 mTmpDisplayMetrics.setTo(dm);
7477 final DisplayMetrics tmpDm = mTmpDisplayMetrics;
7478 final int unrotDw, unrotDh;
7486 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw, unrotDh);
7487 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh, unrotDw);
7488 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw, unrotDh);
7489 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh, unrotDw);
7493 /** Do not call if mDisplayReady == false */
7494 DisplayInfo updateDisplayAndOrientationLocked(int uiMode) {
7495 // TODO(multidisplay): For now, apply Configuration to main screen only.
7496 final DisplayContent displayContent = getDefaultDisplayContentLocked();
7498 // Use the effective "visual" dimensions based on current rotation
7499 final boolean rotated = (mRotation == Surface.ROTATION_90
7500 || mRotation == Surface.ROTATION_270);
7501 final int realdw = rotated ?
7502 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
7503 final int realdh = rotated ?
7504 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
7508 if (mAltOrientation) {
7509 if (realdw > realdh) {
7510 // Turn landscape into portrait.
7511 int maxw = (int)(realdh/1.3f);
7512 if (maxw < realdw) {
7516 // Turn portrait into landscape.
7517 int maxh = (int)(realdw/1.3f);
7518 if (maxh < realdh) {
7524 // Update application display metrics.
7525 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode);
7526 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode);
7527 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7528 displayInfo.rotation = mRotation;
7529 displayInfo.logicalWidth = dw;
7530 displayInfo.logicalHeight = dh;
7531 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
7532 displayInfo.appWidth = appWidth;
7533 displayInfo.appHeight = appHeight;
7534 displayInfo.getLogicalMetrics(mRealDisplayMetrics,
7535 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
7536 displayInfo.getAppMetrics(mDisplayMetrics);
7537 if (displayContent.mDisplayScalingDisabled) {
7538 displayInfo.flags |= Display.FLAG_SCALING_DISABLED;
7540 displayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;
7543 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
7544 displayContent.getDisplayId(), displayInfo);
7546 displayContent.mBaseDisplayRect.set(0, 0, dw, dh);
7548 Slog.i(TAG_WM, "Set app display size: " + appWidth + " x " + appHeight);
7551 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,
7552 mCompatDisplayMetrics);
7556 /** Do not call if mDisplayReady == false */
7557 void computeScreenConfigurationLocked(Configuration config) {
7558 final DisplayInfo displayInfo = updateDisplayAndOrientationLocked(
7561 final int dw = displayInfo.logicalWidth;
7562 final int dh = displayInfo.logicalHeight;
7563 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
7564 Configuration.ORIENTATION_LANDSCAPE;
7565 config.screenWidthDp =
7566 (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation, config.uiMode) /
7567 mDisplayMetrics.density);
7568 config.screenHeightDp =
7569 (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation, config.uiMode) /
7570 mDisplayMetrics.density);
7571 final boolean rotated = (mRotation == Surface.ROTATION_90
7572 || mRotation == Surface.ROTATION_270);
7574 computeSizeRangesAndScreenLayout(displayInfo, rotated, config.uiMode, dw, dh,
7575 mDisplayMetrics.density, config);
7577 config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK)
7578 | ((displayInfo.flags & Display.FLAG_ROUND) != 0
7579 ? Configuration.SCREENLAYOUT_ROUND_YES
7580 : Configuration.SCREENLAYOUT_ROUND_NO);
7582 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
7583 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
7584 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode,
7585 mDisplayMetrics, dw, dh);
7586 config.densityDpi = displayInfo.logicalDensityDpi;
7588 // Update the configuration based on available input devices, lid switch,
7589 // and platform configuration.
7590 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
7591 config.keyboard = Configuration.KEYBOARD_NOKEYS;
7592 config.navigation = Configuration.NAVIGATION_NONAV;
7594 int keyboardPresence = 0;
7595 int navigationPresence = 0;
7596 final InputDevice[] devices = mInputManager.getInputDevices();
7597 final int len = devices.length;
7598 for (int i = 0; i < len; i++) {
7599 InputDevice device = devices[i];
7600 if (!device.isVirtual()) {
7601 final int sources = device.getSources();
7602 final int presenceFlag = device.isExternal() ?
7603 WindowManagerPolicy.PRESENCE_EXTERNAL :
7604 WindowManagerPolicy.PRESENCE_INTERNAL;
7606 if (mIsTouchDevice) {
7607 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
7608 InputDevice.SOURCE_TOUCHSCREEN) {
7609 config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
7612 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
7615 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
7616 config.navigation = Configuration.NAVIGATION_TRACKBALL;
7617 navigationPresence |= presenceFlag;
7618 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
7619 && config.navigation == Configuration.NAVIGATION_NONAV) {
7620 config.navigation = Configuration.NAVIGATION_DPAD;
7621 navigationPresence |= presenceFlag;
7624 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
7625 config.keyboard = Configuration.KEYBOARD_QWERTY;
7626 keyboardPresence |= presenceFlag;
7631 if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) {
7632 config.navigation = Configuration.NAVIGATION_DPAD;
7633 navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;
7636 // Determine whether a hard keyboard is available and enabled.
7637 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
7638 if (hardKeyboardAvailable != mHardKeyboardAvailable) {
7639 mHardKeyboardAvailable = hardKeyboardAvailable;
7640 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
7641 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
7644 // Let the policy update hidden states.
7645 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
7646 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
7647 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
7648 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
7651 void notifyHardKeyboardStatusChange() {
7652 final boolean available;
7653 final WindowManagerInternal.OnHardKeyboardStatusChangeListener listener;
7654 synchronized (mWindowMap) {
7655 listener = mHardKeyboardStatusChangeListener;
7656 available = mHardKeyboardAvailable;
7658 if (listener != null) {
7659 listener.onHardKeyboardStatusChange(available);
7663 boolean startMovingTask(IWindow window, float startX, float startY) {
7664 WindowState win = null;
7665 synchronized (mWindowMap) {
7666 win = windowForClientLocked(null, window, false);
7667 // win shouldn't be null here, pass it down to startPositioningLocked
7668 // to get warning if it's null.
7669 if (!startPositioningLocked(win, false /*resize*/, startX, startY)) {
7674 mActivityManager.setFocusedTask(win.getTask().mTaskId);
7675 } catch(RemoteException e) {}
7679 private void startScrollingTask(DisplayContent displayContent, int startX, int startY) {
7680 if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM,
7681 "startScrollingTask: " + "{" + startX + ", " + startY + "}");
7684 synchronized (mWindowMap) {
7685 int taskId = displayContent.taskIdFromPoint(startX, startY);
7687 task = mTaskIdToTask.get(taskId);
7689 if (task == null || !task.isDockedInEffect() || !startPositioningLocked(
7690 task.getTopVisibleAppMainWindow(), false /*resize*/, startX, startY)) {
7695 mActivityManager.setFocusedTask(task.mTaskId);
7696 } catch(RemoteException e) {}
7699 private void handleTapOutsideTask(DisplayContent displayContent, int x, int y) {
7701 synchronized (mWindowMap) {
7702 final Task task = displayContent.findTaskForControlPoint(x, y);
7704 if (!startPositioningLocked(
7705 task.getTopVisibleAppMainWindow(), true /*resize*/, x, y)) {
7708 taskId = task.mTaskId;
7710 taskId = displayContent.taskIdFromPoint(x, y);
7715 mActivityManager.setFocusedTask(taskId);
7716 } catch(RemoteException e) {}
7720 private boolean startPositioningLocked(
7721 WindowState win, boolean resize, float startX, float startY) {
7722 if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "startPositioningLocked: "
7723 + "win=" + win + ", resize=" + resize + ", {" + startX + ", " + startY + "}");
7725 if (win == null || win.getAppToken() == null) {
7726 Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win);
7729 if (win.mInputChannel == null) {
7730 Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, "
7731 + " probably being removed");
7735 final DisplayContent displayContent = win.getDisplayContent();
7736 if (displayContent == null) {
7737 Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win);
7741 Display display = displayContent.getDisplay();
7742 mTaskPositioner = new TaskPositioner(this);
7743 mTaskPositioner.register(display);
7744 mInputMonitor.updateInputWindowsLw(true /*force*/);
7746 // We need to grab the touch focus so that the touch events during the
7747 // resizing/scrolling are not sent to the app. 'win' is the main window
7748 // of the app, it may not have focus since there might be other windows
7749 // on top (eg. a dialog window).
7750 WindowState transferFocusFromWin = win;
7751 if (mCurrentFocus != null && mCurrentFocus != win
7752 && mCurrentFocus.mAppToken == win.mAppToken) {
7753 transferFocusFromWin = mCurrentFocus;
7755 if (!mInputManager.transferTouchFocus(
7756 transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) {
7757 Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
7758 mTaskPositioner.unregister();
7759 mTaskPositioner = null;
7760 mInputMonitor.updateInputWindowsLw(true /*force*/);
7764 mTaskPositioner.startDragLocked(win, resize, startX, startY);
7768 private void finishPositioning() {
7769 if (DEBUG_TASK_POSITIONING) {
7770 Slog.d(TAG_WM, "finishPositioning");
7772 synchronized (mWindowMap) {
7773 if (mTaskPositioner != null) {
7774 mTaskPositioner.unregister();
7775 mTaskPositioner = null;
7776 mInputMonitor.updateInputWindowsLw(true /*force*/);
7781 void adjustForImeIfNeeded(final DisplayContent displayContent) {
7782 final WindowState imeWin = mInputMethodWindow;
7783 final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
7784 && !displayContent.mDividerControllerLocked.isImeHideRequested();
7785 final boolean dockVisible = isStackVisibleLocked(DOCKED_STACK_ID);
7786 final TaskStack imeTargetStack = getImeFocusStackLocked();
7787 final int imeDockSide = (dockVisible && imeTargetStack != null) ?
7788 imeTargetStack.getDockSide() : DOCKED_INVALID;
7789 final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
7790 final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
7791 final boolean dockMinimized = displayContent.mDividerControllerLocked.isMinimizedDock();
7792 final int imeHeight = mPolicy.getInputMethodWindowVisibleHeightLw();
7793 final boolean imeHeightChanged = imeVisible &&
7794 imeHeight != displayContent.mDividerControllerLocked.getImeHeightAdjustedFor();
7796 // The divider could be adjusted for IME position, or be thinner than usual,
7797 // or both. There are three possible cases:
7798 // - If IME is visible, and focus is on top, divider is not moved for IME but thinner.
7799 // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner.
7800 // - If IME is not visible, divider is not moved and is normal width.
7802 if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
7803 final ArrayList<TaskStack> stacks = displayContent.getStacks();
7804 for (int i = stacks.size() - 1; i >= 0; --i) {
7805 final TaskStack stack = stacks.get(i);
7806 final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
7807 if (stack.isVisibleLocked() && (imeOnBottom || isDockedOnBottom)) {
7808 stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
7810 stack.resetAdjustedForIme(false);
7813 displayContent.mDividerControllerLocked.setAdjustedForIme(
7814 imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
7816 final ArrayList<TaskStack> stacks = displayContent.getStacks();
7817 for (int i = stacks.size() - 1; i >= 0; --i) {
7818 final TaskStack stack = stacks.get(i);
7819 stack.resetAdjustedForIme(!dockVisible);
7821 displayContent.mDividerControllerLocked.setAdjustedForIme(
7822 false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight);
7826 // -------------------------------------------------------------
7828 // -------------------------------------------------------------
7830 IBinder prepareDragSurface(IWindow window, SurfaceSession session,
7831 int flags, int width, int height, Surface outSurface) {
7833 Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height
7834 + " flags=" + Integer.toHexString(flags) + " win=" + window
7835 + " asbinder=" + window.asBinder());
7838 final int callerPid = Binder.getCallingPid();
7839 final int callerUid = Binder.getCallingUid();
7840 final long origId = Binder.clearCallingIdentity();
7841 IBinder token = null;
7844 synchronized (mWindowMap) {
7846 if (mDragState == null) {
7847 // TODO(multi-display): support other displays
7848 final DisplayContent displayContent = getDefaultDisplayContentLocked();
7849 final Display display = displayContent.getDisplay();
7851 SurfaceControl surface = new SurfaceControl(session, "drag surface",
7852 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
7853 surface.setLayerStack(display.getLayerStack());
7855 if ((flags & View.DRAG_FLAG_OPAQUE) == 0) {
7856 alpha = DRAG_SHADOW_ALPHA_TRANSPARENT;
7858 surface.setAlpha(alpha);
7860 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " DRAG "
7861 + surface + ": CREATE");
7862 outSurface.copyFrom(surface);
7863 final IBinder winBinder = window.asBinder();
7864 token = new Binder();
7865 mDragState = new DragState(this, token, surface, flags, winBinder);
7866 mDragState.mPid = callerPid;
7867 mDragState.mUid = callerUid;
7868 mDragState.mOriginalAlpha = alpha;
7869 token = mDragState.mToken = new Binder();
7871 // 5 second timeout for this window to actually begin the drag
7872 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
7873 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
7874 mH.sendMessageDelayed(msg, 5000);
7876 Slog.w(TAG_WM, "Drag already in progress");
7878 } catch (OutOfResourcesException e) {
7879 Slog.e(TAG_WM, "Can't allocate drag surface w=" + width + " h=" + height, e);
7880 if (mDragState != null) {
7887 Binder.restoreCallingIdentity(origId);
7893 // -------------------------------------------------------------
7894 // Input Events and Focus Management
7895 // -------------------------------------------------------------
7897 final InputMonitor mInputMonitor = new InputMonitor(this);
7898 private boolean mEventDispatchingEnabled;
7901 public void pauseKeyDispatching(IBinder _token) {
7902 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7903 "pauseKeyDispatching()")) {
7904 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7907 synchronized (mWindowMap) {
7908 WindowToken token = mTokenMap.get(_token);
7909 if (token != null) {
7910 mInputMonitor.pauseDispatchingLw(token);
7916 public void resumeKeyDispatching(IBinder _token) {
7917 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7918 "resumeKeyDispatching()")) {
7919 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7922 synchronized (mWindowMap) {
7923 WindowToken token = mTokenMap.get(_token);
7924 if (token != null) {
7925 mInputMonitor.resumeDispatchingLw(token);
7931 public void setEventDispatching(boolean enabled) {
7932 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7933 "setEventDispatching()")) {
7934 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7937 synchronized (mWindowMap) {
7938 mEventDispatchingEnabled = enabled;
7939 if (mDisplayEnabled) {
7940 mInputMonitor.setEventDispatchingLw(enabled);
7945 private WindowState getFocusedWindow() {
7946 synchronized (mWindowMap) {
7947 return getFocusedWindowLocked();
7951 private WindowState getFocusedWindowLocked() {
7952 return mCurrentFocus;
7955 TaskStack getImeFocusStackLocked() {
7956 // Don't use mCurrentFocus.getStack() because it returns home stack for system windows.
7957 // Also don't use mInputMethodTarget's stack, because some window with FLAG_NOT_FOCUSABLE
7958 // and FLAG_ALT_FOCUSABLE_IM flags both set might be set to IME target so they're moved
7959 // to make room for IME, but the window is not the focused window that's taking input.
7960 return (mFocusedApp != null && mFocusedApp.mTask != null) ?
7961 mFocusedApp.mTask.mStack : null;
7964 private void showAuditSafeModeNotification() {
7965 PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
7966 new Intent(Intent.ACTION_VIEW,
7967 Uri.parse("https://support.google.com/nexus/answer/2852139")), 0);
7969 String title = mContext.getString(R.string.audit_safemode_notification);
7971 Notification notification = new Notification.Builder(mContext)
7972 .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning)
7977 .setPriority(Notification.PRIORITY_HIGH)
7978 .setVisibility(Notification.VISIBILITY_PUBLIC)
7979 .setColor(mContext.getColor(
7980 com.android.internal.R.color.system_notification_accent_color))
7981 .setContentTitle(title)
7982 .setContentText(mContext.getString(R.string.audit_safemode_notification_details))
7983 .setContentIntent(pendingIntent)
7986 NotificationManager notificationManager = (NotificationManager) mContext
7987 .getSystemService(Context.NOTIFICATION_SERVICE);
7989 notificationManager.notifyAsUser(null, R.string.audit_safemode_notification, notification,
7993 public boolean detectSafeMode() {
7994 if (!mInputMonitor.waitForInputDevicesReady(
7995 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
7996 Slog.w(TAG_WM, "Devices still not ready after waiting "
7997 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
7998 + " milliseconds before attempting to detect safe mode.");
8001 if (Settings.Global.getInt(
8002 mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) {
8006 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
8007 KeyEvent.KEYCODE_MENU);
8008 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
8009 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
8010 KeyEvent.KEYCODE_DPAD_CENTER);
8011 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
8012 InputManagerService.BTN_MOUSE);
8013 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
8014 KeyEvent.KEYCODE_VOLUME_DOWN);
8015 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
8016 || volumeDownState > 0;
8018 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0
8019 || SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) != 0) {
8020 int auditSafeMode = SystemProperties.getInt(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, 0);
8022 if (auditSafeMode == 0) {
8024 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
8026 // stay in safe mode until we have updated to a newer build
8027 int buildDate = SystemProperties.getInt(PROPERTY_BUILD_DATE_UTC, 0);
8029 if (auditSafeMode >= buildDate) {
8031 showAuditSafeModeNotification();
8033 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
8034 SystemProperties.set(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, "");
8038 } catch (IllegalArgumentException e) {
8041 Log.i(TAG_WM, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
8042 + " dpad=" + dpadState + " trackball=" + trackballState + ")");
8043 SystemProperties.set(ShutdownThread.RO_SAFEMODE_PROPERTY, "1");
8045 Log.i(TAG_WM, "SAFE MODE not enabled");
8047 mPolicy.setSafeMode(mSafeMode);
8051 public void displayReady() {
8052 for (Display display : mDisplays) {
8053 displayReady(display.getDisplayId());
8056 synchronized(mWindowMap) {
8057 final DisplayContent displayContent = getDefaultDisplayContentLocked();
8058 readForcedDisplayPropertiesLocked(displayContent);
8059 mDisplayReady = true;
8063 mActivityManager.updateConfiguration(null);
8064 } catch (RemoteException e) {
8067 synchronized(mWindowMap) {
8068 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
8069 PackageManager.FEATURE_TOUCHSCREEN);
8070 configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
8074 mActivityManager.updateConfiguration(null);
8075 } catch (RemoteException e) {
8078 updateCircularDisplayMaskIfNeeded();
8081 private void displayReady(int displayId) {
8082 synchronized(mWindowMap) {
8083 final DisplayContent displayContent = getDisplayContentLocked(displayId);
8084 if (displayContent != null) {
8085 mAnimator.addDisplayLocked(displayId);
8086 displayContent.initializeDisplayBaseInfo();
8087 if (displayContent.mTapDetector != null) {
8088 displayContent.mTapDetector.init();
8094 public void systemReady() {
8095 mPolicy.systemReady();
8098 // -------------------------------------------------------------
8100 // -------------------------------------------------------------
8102 final class H extends Handler {
8103 public static final int REPORT_FOCUS_CHANGE = 2;
8104 public static final int REPORT_LOSING_FOCUS = 3;
8105 public static final int DO_TRAVERSAL = 4;
8106 public static final int ADD_STARTING = 5;
8107 public static final int REMOVE_STARTING = 6;
8108 public static final int FINISHED_STARTING = 7;
8109 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
8110 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
8111 public static final int WINDOW_FREEZE_TIMEOUT = 11;
8113 public static final int APP_TRANSITION_TIMEOUT = 13;
8114 public static final int PERSIST_ANIMATION_SCALE = 14;
8115 public static final int FORCE_GC = 15;
8116 public static final int ENABLE_SCREEN = 16;
8117 public static final int APP_FREEZE_TIMEOUT = 17;
8118 public static final int SEND_NEW_CONFIGURATION = 18;
8119 public static final int REPORT_WINDOWS_CHANGE = 19;
8120 public static final int DRAG_START_TIMEOUT = 20;
8121 public static final int DRAG_END_TIMEOUT = 21;
8122 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
8123 public static final int BOOT_TIMEOUT = 23;
8124 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
8125 public static final int SHOW_STRICT_MODE_VIOLATION = 25;
8126 public static final int DO_ANIMATION_CALLBACK = 26;
8128 public static final int DO_DISPLAY_ADDED = 27;
8129 public static final int DO_DISPLAY_REMOVED = 28;
8130 public static final int DO_DISPLAY_CHANGED = 29;
8132 public static final int CLIENT_FREEZE_TIMEOUT = 30;
8133 public static final int TAP_OUTSIDE_TASK = 31;
8134 public static final int NOTIFY_ACTIVITY_DRAWN = 32;
8136 public static final int ALL_WINDOWS_DRAWN = 33;
8138 public static final int NEW_ANIMATOR_SCALE = 34;
8140 public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35;
8141 public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36;
8143 public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37;
8144 public static final int RESET_ANR_MESSAGE = 38;
8145 public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39;
8147 public static final int FINISH_TASK_POSITIONING = 40;
8149 public static final int UPDATE_DOCKED_STACK_DIVIDER = 41;
8151 public static final int RESIZE_STACK = 42;
8152 public static final int RESIZE_TASK = 43;
8154 public static final int TWO_FINGER_SCROLL_START = 44;
8156 public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
8158 public static final int NOTIFY_APP_TRANSITION_STARTING = 47;
8159 public static final int NOTIFY_APP_TRANSITION_CANCELLED = 48;
8160 public static final int NOTIFY_APP_TRANSITION_FINISHED = 49;
8161 public static final int NOTIFY_STARTING_WINDOW_DRAWN = 50;
8162 public static final int UPDATE_ANIMATION_SCALE = 51;
8163 public static final int WINDOW_REMOVE_TIMEOUT = 52;
8164 public static final int NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED = 53;
8165 public static final int SEAMLESS_ROTATION_TIMEOUT = 54;
8168 * Used to denote that an integer field in a message will not be used.
8170 public static final int UNUSED = 0;
8173 public void handleMessage(Message msg) {
8174 if (DEBUG_WINDOW_TRACE) {
8175 Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what);
8178 case REPORT_FOCUS_CHANGE: {
8179 WindowState lastFocus;
8180 WindowState newFocus;
8182 AccessibilityController accessibilityController = null;
8184 synchronized(mWindowMap) {
8185 // TODO(multidisplay): Accessibility supported only of default desiplay.
8186 if (mAccessibilityController != null && getDefaultDisplayContentLocked()
8187 .getDisplayId() == Display.DEFAULT_DISPLAY) {
8188 accessibilityController = mAccessibilityController;
8191 lastFocus = mLastFocus;
8192 newFocus = mCurrentFocus;
8193 if (lastFocus == newFocus) {
8194 // Focus is not changing, so nothing to do.
8197 mLastFocus = newFocus;
8198 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Focus moving from " + lastFocus +
8200 if (newFocus != null && lastFocus != null
8201 && !newFocus.isDisplayedLw()) {
8202 //Slog.i(TAG_WM, "Delaying loss of focus...");
8203 mLosingFocus.add(lastFocus);
8208 // First notify the accessibility manager for the change so it has
8209 // the windows before the newly focused one starts firing eventgs.
8210 if (accessibilityController != null) {
8211 accessibilityController.onWindowFocusChangedNotLocked();
8214 //System.out.println("Changing focus from " + lastFocus
8215 // + " to " + newFocus);
8216 if (newFocus != null) {
8217 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Gaining focus: " + newFocus);
8218 newFocus.reportFocusChangedSerialized(true, mInTouchMode);
8219 notifyFocusChanged();
8222 if (lastFocus != null) {
8223 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing focus: " + lastFocus);
8224 lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
8228 case REPORT_LOSING_FOCUS: {
8229 ArrayList<WindowState> losers;
8231 synchronized(mWindowMap) {
8232 losers = mLosingFocus;
8233 mLosingFocus = new ArrayList<WindowState>();
8236 final int N = losers.size();
8237 for (int i=0; i<N; i++) {
8238 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing delayed focus: " +
8240 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
8244 case DO_TRAVERSAL: {
8245 synchronized(mWindowMap) {
8246 mWindowPlacerLocked.performSurfacePlacement();
8250 case ADD_STARTING: {
8251 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8252 final StartingData sd = wtoken.startingData;
8255 // Animation has been canceled... do nothing.
8259 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting "
8260 + wtoken + ": pkg=" + sd.pkg);
8264 final Configuration overrideConfig = wtoken != null && wtoken.mTask != null
8265 ? wtoken.mTask.mOverrideConfig : null;
8266 view = mPolicy.addStartingWindow(wtoken.token, sd.pkg, sd.theme,
8267 sd.compatInfo, sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo,
8268 sd.windowFlags, overrideConfig);
8269 } catch (Exception e) {
8270 Slog.w(TAG_WM, "Exception when adding starting window", e);
8274 boolean abort = false;
8276 synchronized(mWindowMap) {
8277 if (wtoken.removed || wtoken.startingData == null) {
8278 // If the window was successfully added, then
8279 // we need to remove it.
8280 if (wtoken.startingWindow != null) {
8281 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
8282 "Aborted starting " + wtoken
8283 + ": removed=" + wtoken.removed
8284 + " startingData=" + wtoken.startingData);
8285 wtoken.startingWindow = null;
8286 wtoken.startingData = null;
8290 wtoken.startingView = view;
8292 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM,
8293 "Added starting " + wtoken
8294 + ": startingWindow="
8295 + wtoken.startingWindow + " startingView="
8296 + wtoken.startingView);
8301 mPolicy.removeStartingWindow(wtoken.token, view);
8302 } catch (Exception e) {
8303 Slog.w(TAG_WM, "Exception when removing starting window", e);
8309 case REMOVE_STARTING: {
8310 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8311 IBinder token = null;
8313 synchronized (mWindowMap) {
8314 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Remove starting "
8315 + wtoken + ": startingWindow="
8316 + wtoken.startingWindow + " startingView="
8317 + wtoken.startingView);
8318 if (wtoken.startingWindow != null) {
8319 view = wtoken.startingView;
8320 token = wtoken.token;
8321 wtoken.startingData = null;
8322 wtoken.startingView = null;
8323 wtoken.startingWindow = null;
8324 wtoken.startingDisplayed = false;
8329 mPolicy.removeStartingWindow(token, view);
8330 } catch (Exception e) {
8331 Slog.w(TAG_WM, "Exception when removing starting window", e);
8336 case FINISHED_STARTING: {
8337 IBinder token = null;
8340 synchronized (mWindowMap) {
8341 final int N = mFinishedStarting.size();
8345 AppWindowToken wtoken = mFinishedStarting.remove(N-1);
8347 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
8348 "Finished starting " + wtoken
8349 + ": startingWindow=" + wtoken.startingWindow
8350 + " startingView=" + wtoken.startingView);
8352 if (wtoken.startingWindow == null) {
8356 view = wtoken.startingView;
8357 token = wtoken.token;
8358 wtoken.startingData = null;
8359 wtoken.startingView = null;
8360 wtoken.startingWindow = null;
8361 wtoken.startingDisplayed = false;
8365 mPolicy.removeStartingWindow(token, view);
8366 } catch (Exception e) {
8367 Slog.w(TAG_WM, "Exception when removing starting window", e);
8372 case REPORT_APPLICATION_TOKEN_DRAWN: {
8373 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8376 if (DEBUG_VISIBILITY) Slog.v(
8377 TAG_WM, "Reporting drawn in " + wtoken);
8378 wtoken.appToken.windowsDrawn();
8379 } catch (RemoteException ex) {
8383 case REPORT_APPLICATION_TOKEN_WINDOWS: {
8384 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8386 boolean nowVisible = msg.arg1 != 0;
8387 boolean nowGone = msg.arg2 != 0;
8390 if (DEBUG_VISIBILITY) Slog.v(
8391 TAG_WM, "Reporting visible in " + wtoken
8392 + " visible=" + nowVisible
8393 + " gone=" + nowGone);
8395 wtoken.appToken.windowsVisible();
8397 wtoken.appToken.windowsGone();
8399 } catch (RemoteException ex) {
8403 case WINDOW_FREEZE_TIMEOUT: {
8404 // TODO(multidisplay): Can non-default displays rotate?
8405 synchronized (mWindowMap) {
8406 Slog.w(TAG_WM, "Window freeze timeout expired.");
8407 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
8408 final WindowList windows = getDefaultWindowListLocked();
8409 int i = windows.size();
8412 WindowState w = windows.get(i);
8413 if (w.mOrientationChanging) {
8414 w.mOrientationChanging = false;
8415 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
8416 - mDisplayFreezeTime);
8417 Slog.w(TAG_WM, "Force clearing orientation change: " + w);
8420 mWindowPlacerLocked.performSurfacePlacement();
8425 case APP_TRANSITION_TIMEOUT: {
8426 synchronized (mWindowMap) {
8427 if (mAppTransition.isTransitionSet() || !mOpeningApps.isEmpty()
8428 || !mClosingApps.isEmpty()) {
8429 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "*** APP TRANSITION TIMEOUT."
8430 + " isTransitionSet()=" + mAppTransition.isTransitionSet()
8431 + " mOpeningApps.size()=" + mOpeningApps.size()
8432 + " mClosingApps.size()=" + mClosingApps.size());
8433 mAppTransition.setTimeout();
8434 mWindowPlacerLocked.performSurfacePlacement();
8440 case PERSIST_ANIMATION_SCALE: {
8441 Settings.Global.putFloat(mContext.getContentResolver(),
8442 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
8443 Settings.Global.putFloat(mContext.getContentResolver(),
8444 Settings.Global.TRANSITION_ANIMATION_SCALE,
8445 mTransitionAnimationScaleSetting);
8446 Settings.Global.putFloat(mContext.getContentResolver(),
8447 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting);
8451 case UPDATE_ANIMATION_SCALE: {
8452 @UpdateAnimationScaleMode
8453 final int mode = msg.arg1;
8455 case WINDOW_ANIMATION_SCALE: {
8456 mWindowAnimationScaleSetting = Settings.Global.getFloat(
8457 mContext.getContentResolver(),
8458 Settings.Global.WINDOW_ANIMATION_SCALE,
8459 mWindowAnimationScaleSetting);
8462 case TRANSITION_ANIMATION_SCALE: {
8463 mTransitionAnimationScaleSetting = Settings.Global.getFloat(
8464 mContext.getContentResolver(),
8465 Settings.Global.TRANSITION_ANIMATION_SCALE,
8466 mTransitionAnimationScaleSetting);
8469 case ANIMATION_DURATION_SCALE: {
8470 mAnimatorDurationScaleSetting = Settings.Global.getFloat(
8471 mContext.getContentResolver(),
8472 Settings.Global.ANIMATOR_DURATION_SCALE,
8473 mAnimatorDurationScaleSetting);
8474 dispatchNewAnimatorScaleLocked(null);
8482 synchronized (mWindowMap) {
8483 // Since we're holding both mWindowMap and mAnimator we don't need to
8484 // hold mAnimator.mLayoutToAnim.
8485 if (mAnimator.isAnimating() || mAnimationScheduled) {
8486 // If we are animating, don't do the gc now but
8487 // delay a bit so we don't interrupt the animation.
8488 sendEmptyMessageDelayed(H.FORCE_GC, 2000);
8491 // If we are currently rotating the display, it will
8492 // schedule a new message when done.
8493 if (mDisplayFrozen) {
8497 Runtime.getRuntime().gc();
8501 case ENABLE_SCREEN: {
8502 performEnableScreen();
8506 case APP_FREEZE_TIMEOUT: {
8507 synchronized (mWindowMap) {
8508 Slog.w(TAG_WM, "App freeze timeout expired.");
8509 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
8510 final int numStacks = mStackIdToStack.size();
8511 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8512 final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
8513 final ArrayList<Task> tasks = stack.getTasks();
8514 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
8515 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8516 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
8517 AppWindowToken tok = tokens.get(tokenNdx);
8518 if (tok.mAppAnimator.freezingScreen) {
8519 Slog.w(TAG_WM, "Force clearing freeze: " + tok);
8520 unsetAppFreezingScreenLocked(tok, true, true);
8529 case CLIENT_FREEZE_TIMEOUT: {
8530 synchronized (mWindowMap) {
8531 if (mClientFreezingScreen) {
8532 mClientFreezingScreen = false;
8533 mLastFinishedFreezeSource = "client-timeout";
8534 stopFreezingDisplayLocked();
8540 case SEND_NEW_CONFIGURATION: {
8541 removeMessages(SEND_NEW_CONFIGURATION);
8542 sendNewConfiguration();
8546 case REPORT_WINDOWS_CHANGE: {
8547 if (mWindowsChanged) {
8548 synchronized (mWindowMap) {
8549 mWindowsChanged = false;
8551 notifyWindowsChanged();
8556 case DRAG_START_TIMEOUT: {
8557 IBinder win = (IBinder)msg.obj;
8559 Slog.w(TAG_WM, "Timeout starting drag by win " + win);
8561 synchronized (mWindowMap) {
8562 // !!! TODO: ANR the app that has failed to start the drag in time
8563 if (mDragState != null) {
8564 mDragState.unregister();
8565 mInputMonitor.updateInputWindowsLw(true /*force*/);
8573 case DRAG_END_TIMEOUT: {
8574 IBinder win = (IBinder)msg.obj;
8576 Slog.w(TAG_WM, "Timeout ending drag to win " + win);
8578 synchronized (mWindowMap) {
8579 // !!! TODO: ANR the drag-receiving app
8580 if (mDragState != null) {
8581 mDragState.mDragResult = false;
8582 mDragState.endDragLw();
8588 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
8589 notifyHardKeyboardStatusChange();
8593 case BOOT_TIMEOUT: {
8594 performBootTimeout();
8598 case WAITING_FOR_DRAWN_TIMEOUT: {
8599 Runnable callback = null;
8600 synchronized (mWindowMap) {
8601 Slog.w(TAG_WM, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
8602 mWaitingForDrawn.clear();
8603 callback = mWaitingForDrawnCallback;
8604 mWaitingForDrawnCallback = null;
8606 if (callback != null) {
8612 case SHOW_STRICT_MODE_VIOLATION: {
8613 showStrictModeViolation(msg.arg1, msg.arg2);
8617 case SHOW_CIRCULAR_DISPLAY_MASK: {
8618 showCircularMask(msg.arg1 == 1);
8622 case SHOW_EMULATOR_DISPLAY_OVERLAY: {
8623 showEmulatorDisplayOverlay();
8627 case DO_ANIMATION_CALLBACK: {
8629 ((IRemoteCallback)msg.obj).sendResult(null);
8630 } catch (RemoteException e) {
8635 case DO_DISPLAY_ADDED:
8636 handleDisplayAdded(msg.arg1);
8639 case DO_DISPLAY_REMOVED:
8640 synchronized (mWindowMap) {
8641 handleDisplayRemovedLocked(msg.arg1);
8645 case DO_DISPLAY_CHANGED:
8646 synchronized (mWindowMap) {
8647 handleDisplayChangedLocked(msg.arg1);
8651 case TWO_FINGER_SCROLL_START: {
8652 startScrollingTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
8656 case TAP_OUTSIDE_TASK: {
8657 handleTapOutsideTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
8661 case FINISH_TASK_POSITIONING: {
8662 finishPositioning();
8666 case NOTIFY_ACTIVITY_DRAWN:
8668 mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
8669 } catch (RemoteException e) {
8672 case ALL_WINDOWS_DRAWN: {
8674 synchronized (mWindowMap) {
8675 callback = mWaitingForDrawnCallback;
8676 mWaitingForDrawnCallback = null;
8678 if (callback != null) {
8682 case NEW_ANIMATOR_SCALE: {
8683 float scale = getCurrentAnimatorScale();
8684 ValueAnimator.setDurationScale(scale);
8685 Session session = (Session)msg.obj;
8686 if (session != null) {
8688 session.mCallback.onAnimatorScaleChanged(scale);
8689 } catch (RemoteException e) {
8692 ArrayList<IWindowSessionCallback> callbacks
8693 = new ArrayList<IWindowSessionCallback>();
8694 synchronized (mWindowMap) {
8695 for (int i=0; i<mSessions.size(); i++) {
8696 callbacks.add(mSessions.valueAt(i).mCallback);
8700 for (int i=0; i<callbacks.size(); i++) {
8702 callbacks.get(i).onAnimatorScaleChanged(scale);
8703 } catch (RemoteException e) {
8709 case CHECK_IF_BOOT_ANIMATION_FINISHED: {
8710 final boolean bootAnimationComplete;
8711 synchronized (mWindowMap) {
8712 if (DEBUG_BOOT) Slog.i(TAG_WM, "CHECK_IF_BOOT_ANIMATION_FINISHED:");
8713 bootAnimationComplete = checkBootAnimationCompleteLocked();
8715 if (bootAnimationComplete) {
8716 performEnableScreen();
8720 case RESET_ANR_MESSAGE: {
8721 synchronized (mWindowMap) {
8722 mLastANRState = null;
8726 case WALLPAPER_DRAW_PENDING_TIMEOUT: {
8727 synchronized (mWindowMap) {
8728 if (mWallpaperControllerLocked.processWallpaperDrawPendingTimeout()) {
8729 mWindowPlacerLocked.performSurfacePlacement();
8733 case UPDATE_DOCKED_STACK_DIVIDER: {
8734 synchronized (mWindowMap) {
8735 final DisplayContent displayContent = getDefaultDisplayContentLocked();
8736 displayContent.getDockedDividerController().reevaluateVisibility(false);
8737 adjustForImeIfNeeded(displayContent);
8743 mActivityManager.resizeTask(msg.arg1, (Rect) msg.obj, msg.arg2);
8744 } catch (RemoteException e) {
8745 // This will not happen since we are in the same process.
8749 case RESIZE_STACK: {
8751 mActivityManager.resizeStack(
8752 msg.arg1, (Rect) msg.obj, msg.arg2 == 1, false, false, -1);
8753 } catch (RemoteException e) {
8754 // This will not happen since we are in the same process.
8758 case WINDOW_REPLACEMENT_TIMEOUT: {
8759 synchronized (mWindowMap) {
8760 for (int i = mReplacingWindowTimeouts.size() - 1; i >= 0; i--) {
8761 final AppWindowToken token = mReplacingWindowTimeouts.get(i);
8762 token.clearTimedoutReplacesLocked();
8764 mReplacingWindowTimeouts.clear();
8767 case NOTIFY_APP_TRANSITION_STARTING: {
8768 mAmInternal.notifyAppTransitionStarting(msg.arg1);
8771 case NOTIFY_APP_TRANSITION_CANCELLED: {
8772 mAmInternal.notifyAppTransitionCancelled();
8775 case NOTIFY_APP_TRANSITION_FINISHED: {
8776 mAmInternal.notifyAppTransitionFinished();
8779 case NOTIFY_STARTING_WINDOW_DRAWN: {
8780 mAmInternal.notifyStartingWindowDrawn();
8783 case WINDOW_REMOVE_TIMEOUT: {
8784 final WindowState window = (WindowState) msg.obj;
8785 synchronized(mWindowMap) {
8786 // TODO: This is all about fixing b/21693547
8787 // where partially initialized Toasts get stuck
8788 // around and keep the screen on. We'd like
8789 // to just remove the toast...but this can cause clients
8790 // who miss the timeout due to normal circumstances (e.g.
8791 // running under debugger) to crash (b/29105388). The windows will
8792 // eventually be removed when the client process finishes.
8793 // The best we can do for now is remove the FLAG_KEEP_SCREEN_ON
8794 // and prevent the symptoms of b/21693547.
8795 window.mAttrs.flags &= ~FLAG_KEEP_SCREEN_ON;
8796 window.setDisplayLayoutNeeded();
8797 mWindowPlacerLocked.performSurfacePlacement();
8801 case NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED: {
8802 mAmInternal.notifyDockedStackMinimizedChanged(msg.arg1 == 1);
8805 case SEAMLESS_ROTATION_TIMEOUT: {
8806 // Rotation only supported on primary display.
8807 // TODO(multi-display)
8808 synchronized(mWindowMap) {
8809 final DisplayContent displayContent = getDefaultDisplayContentLocked();
8810 final WindowList windows = displayContent.getWindowList();
8811 boolean layoutNeeded = false;
8812 for (int i = windows.size() - 1; i >= 0; i--) {
8813 WindowState w = windows.get(i);
8814 if (w.mSeamlesslyRotated) {
8815 layoutNeeded = true;
8816 w.setDisplayLayoutNeeded();
8818 w.mSeamlesslyRotated = false;
8821 mWindowPlacerLocked.performSurfacePlacement();
8827 if (DEBUG_WINDOW_TRACE) {
8828 Slog.v(TAG_WM, "handleMessage: exit");
8833 void destroyPreservedSurfaceLocked() {
8834 for (int i = mDestroyPreservedSurface.size() - 1; i >= 0 ; i--) {
8835 final WindowState w = mDestroyPreservedSurface.get(i);
8836 w.mWinAnimator.destroyPreservedSurfaceLocked();
8838 mDestroyPreservedSurface.clear();
8841 void stopUsingSavedSurfaceLocked() {
8842 for (int i = mFinishedEarlyAnim.size() - 1; i >= 0 ; i--) {
8843 final AppWindowToken wtoken = mFinishedEarlyAnim.get(i);
8844 wtoken.stopUsingSavedSurfaceLocked();
8846 mFinishedEarlyAnim.clear();
8849 // -------------------------------------------------------------
8850 // IWindowManager API
8851 // -------------------------------------------------------------
8854 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
8855 IInputContext inputContext) {
8856 if (client == null) throw new IllegalArgumentException("null client");
8857 if (inputContext == null) throw new IllegalArgumentException("null inputContext");
8858 Session session = new Session(this, callback, client, inputContext);
8863 public boolean inputMethodClientHasFocus(IInputMethodClient client) {
8864 synchronized (mWindowMap) {
8865 // The focus for the client is the window immediately below
8866 // where we would place the input method window.
8867 int idx = findDesiredInputMethodWindowIndexLocked(false);
8869 // TODO(multidisplay): IMEs are only supported on the default display.
8870 WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
8871 if (DEBUG_INPUT_METHOD) {
8872 Slog.i(TAG_WM, "Desired input method target: " + imFocus);
8873 Slog.i(TAG_WM, "Current focus: " + mCurrentFocus);
8874 Slog.i(TAG_WM, "Last focus: " + mLastFocus);
8876 if (imFocus != null) {
8877 // This may be a starting window, in which case we still want
8878 // to count it as okay.
8879 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING
8880 && imFocus.mAppToken != null) {
8881 // The client has definitely started, so it really should
8882 // have a window in this app token. Let's look for it.
8883 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
8884 WindowState w = imFocus.mAppToken.windows.get(i);
8886 Log.i(TAG_WM, "Switching to real app window: " + w);
8892 if (DEBUG_INPUT_METHOD) {
8893 Slog.i(TAG_WM, "IM target client: " + imFocus.mSession.mClient);
8894 if (imFocus.mSession.mClient != null) {
8895 Slog.i(TAG_WM, "IM target client binder: "
8896 + imFocus.mSession.mClient.asBinder());
8897 Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder());
8900 if (imFocus.mSession.mClient != null &&
8901 imFocus.mSession.mClient.asBinder() == client.asBinder()) {
8907 // Okay, how about this... what is the current focus?
8908 // It seems in some cases we may not have moved the IM
8909 // target window, such as when it was in a pop-up window,
8910 // so let's also look at the current focus. (An example:
8911 // go to Gmail, start searching so the keyboard goes up,
8912 // press home. Sometimes the IME won't go down.)
8913 // Would be nice to fix this more correctly, but it's
8914 // way at the end of a release, and this should be good enough.
8915 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
8916 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
8924 public void getInitialDisplaySize(int displayId, Point size) {
8925 synchronized (mWindowMap) {
8926 final DisplayContent displayContent = getDisplayContentLocked(displayId);
8927 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8928 size.x = displayContent.mInitialDisplayWidth;
8929 size.y = displayContent.mInitialDisplayHeight;
8935 public void getBaseDisplaySize(int displayId, Point size) {
8936 synchronized (mWindowMap) {
8937 final DisplayContent displayContent = getDisplayContentLocked(displayId);
8938 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8939 size.x = displayContent.mBaseDisplayWidth;
8940 size.y = displayContent.mBaseDisplayHeight;
8946 public void setForcedDisplaySize(int displayId, int width, int height) {
8947 if (mContext.checkCallingOrSelfPermission(
8948 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8949 PackageManager.PERMISSION_GRANTED) {
8950 throw new SecurityException("Must hold permission " +
8951 android.Manifest.permission.WRITE_SECURE_SETTINGS);
8953 if (displayId != Display.DEFAULT_DISPLAY) {
8954 throw new IllegalArgumentException("Can only set the default display");
8956 final long ident = Binder.clearCallingIdentity();
8958 synchronized(mWindowMap) {
8959 // Set some sort of reasonable bounds on the size of the display that we
8960 // will try to emulate.
8961 final int MIN_WIDTH = 200;
8962 final int MIN_HEIGHT = 200;
8963 final int MAX_SCALE = 2;
8964 final DisplayContent displayContent = getDisplayContentLocked(displayId);
8965 if (displayContent != null) {
8966 width = Math.min(Math.max(width, MIN_WIDTH),
8967 displayContent.mInitialDisplayWidth * MAX_SCALE);
8968 height = Math.min(Math.max(height, MIN_HEIGHT),
8969 displayContent.mInitialDisplayHeight * MAX_SCALE);
8970 setForcedDisplaySizeLocked(displayContent, width, height);
8971 Settings.Global.putString(mContext.getContentResolver(),
8972 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
8976 Binder.restoreCallingIdentity(ident);
8981 public void setForcedDisplayScalingMode(int displayId, int mode) {
8982 if (mContext.checkCallingOrSelfPermission(
8983 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8984 PackageManager.PERMISSION_GRANTED) {
8985 throw new SecurityException("Must hold permission " +
8986 android.Manifest.permission.WRITE_SECURE_SETTINGS);
8988 if (displayId != Display.DEFAULT_DISPLAY) {
8989 throw new IllegalArgumentException("Can only set the default display");
8991 final long ident = Binder.clearCallingIdentity();
8993 synchronized(mWindowMap) {
8994 final DisplayContent displayContent = getDisplayContentLocked(displayId);
8995 if (displayContent != null) {
8996 if (mode < 0 || mode > 1) {
8999 setForcedDisplayScalingModeLocked(displayContent, mode);
9000 Settings.Global.putInt(mContext.getContentResolver(),
9001 Settings.Global.DISPLAY_SCALING_FORCE, mode);
9005 Binder.restoreCallingIdentity(ident);
9009 private void setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode) {
9010 Slog.i(TAG_WM, "Using display scaling mode: " + (mode == 0 ? "auto" : "off"));
9011 displayContent.mDisplayScalingDisabled = (mode != 0);
9012 reconfigureDisplayLocked(displayContent);
9015 private void readForcedDisplayPropertiesLocked(final DisplayContent displayContent) {
9017 String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
9018 Settings.Global.DISPLAY_SIZE_FORCED);
9019 if (sizeStr == null || sizeStr.length() == 0) {
9020 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
9022 if (sizeStr != null && sizeStr.length() > 0) {
9023 final int pos = sizeStr.indexOf(',');
9024 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
9027 width = Integer.parseInt(sizeStr.substring(0, pos));
9028 height = Integer.parseInt(sizeStr.substring(pos+1));
9029 if (displayContent.mBaseDisplayWidth != width
9030 || displayContent.mBaseDisplayHeight != height) {
9031 Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
9032 displayContent.mBaseDisplayWidth = width;
9033 displayContent.mBaseDisplayHeight = height;
9035 } catch (NumberFormatException ex) {
9041 final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId);
9043 displayContent.mBaseDisplayDensity = density;
9046 // Display scaling mode.
9047 int mode = Settings.Global.getInt(mContext.getContentResolver(),
9048 Settings.Global.DISPLAY_SCALING_FORCE, 0);
9050 Slog.i(TAG_WM, "FORCED DISPLAY SCALING DISABLED");
9051 displayContent.mDisplayScalingDisabled = true;
9055 // displayContent must not be null
9056 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
9057 Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
9058 displayContent.mBaseDisplayWidth = width;
9059 displayContent.mBaseDisplayHeight = height;
9060 reconfigureDisplayLocked(displayContent);
9064 public void clearForcedDisplaySize(int displayId) {
9065 if (mContext.checkCallingOrSelfPermission(
9066 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
9067 PackageManager.PERMISSION_GRANTED) {
9068 throw new SecurityException("Must hold permission " +
9069 android.Manifest.permission.WRITE_SECURE_SETTINGS);
9071 if (displayId != Display.DEFAULT_DISPLAY) {
9072 throw new IllegalArgumentException("Can only set the default display");
9074 final long ident = Binder.clearCallingIdentity();
9076 synchronized(mWindowMap) {
9077 final DisplayContent displayContent = getDisplayContentLocked(displayId);
9078 if (displayContent != null) {
9079 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
9080 displayContent.mInitialDisplayHeight);
9081 Settings.Global.putString(mContext.getContentResolver(),
9082 Settings.Global.DISPLAY_SIZE_FORCED, "");
9086 Binder.restoreCallingIdentity(ident);
9091 public int getInitialDisplayDensity(int displayId) {
9092 synchronized (mWindowMap) {
9093 final DisplayContent displayContent = getDisplayContentLocked(displayId);
9094 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
9095 return displayContent.mInitialDisplayDensity;
9102 public int getBaseDisplayDensity(int displayId) {
9103 synchronized (mWindowMap) {
9104 final DisplayContent displayContent = getDisplayContentLocked(displayId);
9105 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
9106 return displayContent.mBaseDisplayDensity;
9113 public void setForcedDisplayDensity(int displayId, int density) {
9114 if (mContext.checkCallingOrSelfPermission(
9115 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
9116 PackageManager.PERMISSION_GRANTED) {
9117 throw new SecurityException("Must hold permission " +
9118 android.Manifest.permission.WRITE_SECURE_SETTINGS);
9120 if (displayId != Display.DEFAULT_DISPLAY) {
9121 throw new IllegalArgumentException("Can only set the default display");
9123 final long ident = Binder.clearCallingIdentity();
9125 synchronized(mWindowMap) {
9126 final DisplayContent displayContent = getDisplayContentLocked(displayId);
9127 if (displayContent != null) {
9128 setForcedDisplayDensityLocked(displayContent, density);
9129 Settings.Secure.putStringForUser(mContext.getContentResolver(),
9130 Settings.Secure.DISPLAY_DENSITY_FORCED,
9131 Integer.toString(density), mCurrentUserId);
9135 Binder.restoreCallingIdentity(ident);
9140 public void clearForcedDisplayDensity(int displayId) {
9141 if (mContext.checkCallingOrSelfPermission(
9142 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
9143 PackageManager.PERMISSION_GRANTED) {
9144 throw new SecurityException("Must hold permission " +
9145 android.Manifest.permission.WRITE_SECURE_SETTINGS);
9147 if (displayId != Display.DEFAULT_DISPLAY) {
9148 throw new IllegalArgumentException("Can only set the default display");
9150 final long ident = Binder.clearCallingIdentity();
9152 synchronized(mWindowMap) {
9153 final DisplayContent displayContent = getDisplayContentLocked(displayId);
9154 if (displayContent != null) {
9155 setForcedDisplayDensityLocked(displayContent,
9156 displayContent.mInitialDisplayDensity);
9157 Settings.Secure.putStringForUser(mContext.getContentResolver(),
9158 Settings.Secure.DISPLAY_DENSITY_FORCED, "", mCurrentUserId);
9162 Binder.restoreCallingIdentity(ident);
9167 * @param userId the ID of the user
9168 * @return the forced display density for the specified user, if set, or
9169 * {@code 0} if not set
9171 private int getForcedDisplayDensityForUserLocked(int userId) {
9172 String densityStr = Settings.Secure.getStringForUser(mContext.getContentResolver(),
9173 Settings.Secure.DISPLAY_DENSITY_FORCED, userId);
9174 if (densityStr == null || densityStr.length() == 0) {
9175 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
9177 if (densityStr != null && densityStr.length() > 0) {
9179 return Integer.parseInt(densityStr);
9180 } catch (NumberFormatException ex) {
9187 * Forces the given display to the use the specified density.
9189 * @param displayContent the display to modify
9190 * @param density the density in DPI to use
9192 private void setForcedDisplayDensityLocked(@NonNull DisplayContent displayContent,
9194 displayContent.mBaseDisplayDensity = density;
9195 reconfigureDisplayLocked(displayContent);
9198 // displayContent must not be null
9199 private void reconfigureDisplayLocked(DisplayContent displayContent) {
9200 // TODO: Multidisplay: for now only use with default display.
9201 if (!mDisplayReady) {
9204 configureDisplayPolicyLocked(displayContent);
9205 displayContent.layoutNeeded = true;
9207 boolean configChanged = updateOrientationFromAppTokensLocked(false);
9208 mTempConfiguration.setToDefaults();
9209 mTempConfiguration.updateFrom(mCurConfiguration);
9210 computeScreenConfigurationLocked(mTempConfiguration);
9211 configChanged |= mCurConfiguration.diff(mTempConfiguration) != 0;
9213 if (configChanged) {
9214 mWaitingForConfig = true;
9215 startFreezingDisplayLocked(false, 0, 0);
9216 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9217 if (!mReconfigureOnConfigurationChanged.contains(displayContent)) {
9218 mReconfigureOnConfigurationChanged.add(displayContent);
9222 mWindowPlacerLocked.performSurfacePlacement();
9225 private void configureDisplayPolicyLocked(DisplayContent displayContent) {
9226 mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
9227 displayContent.mBaseDisplayWidth,
9228 displayContent.mBaseDisplayHeight,
9229 displayContent.mBaseDisplayDensity);
9231 DisplayInfo displayInfo = displayContent.getDisplayInfo();
9232 mPolicy.setDisplayOverscan(displayContent.getDisplay(),
9233 displayInfo.overscanLeft, displayInfo.overscanTop,
9234 displayInfo.overscanRight, displayInfo.overscanBottom);
9238 public void setOverscan(int displayId, int left, int top, int right, int bottom) {
9239 if (mContext.checkCallingOrSelfPermission(
9240 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
9241 PackageManager.PERMISSION_GRANTED) {
9242 throw new SecurityException("Must hold permission " +
9243 android.Manifest.permission.WRITE_SECURE_SETTINGS);
9245 final long ident = Binder.clearCallingIdentity();
9247 synchronized(mWindowMap) {
9248 DisplayContent displayContent = getDisplayContentLocked(displayId);
9249 if (displayContent != null) {
9250 setOverscanLocked(displayContent, left, top, right, bottom);
9254 Binder.restoreCallingIdentity(ident);
9258 private void setOverscanLocked(DisplayContent displayContent,
9259 int left, int top, int right, int bottom) {
9260 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
9261 displayInfo.overscanLeft = left;
9262 displayInfo.overscanTop = top;
9263 displayInfo.overscanRight = right;
9264 displayInfo.overscanBottom = bottom;
9266 mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, displayInfo.name, left, top,
9268 mDisplaySettings.writeSettingsLocked();
9270 reconfigureDisplayLocked(displayContent);
9273 // -------------------------------------------------------------
9275 // -------------------------------------------------------------
9277 final WindowState windowForClientLocked(Session session, IWindow client,
9278 boolean throwOnError) {
9279 return windowForClientLocked(session, client.asBinder(), throwOnError);
9282 final WindowState windowForClientLocked(Session session, IBinder client,
9283 boolean throwOnError) {
9284 WindowState win = mWindowMap.get(client);
9285 if (localLOGV) Slog.v(
9286 TAG_WM, "Looking up client " + client + ": " + win);
9288 RuntimeException ex = new IllegalArgumentException(
9289 "Requested window " + client + " does not exist");
9293 Slog.w(TAG_WM, "Failed looking up window", ex);
9296 if (session != null && win.mSession != session) {
9297 RuntimeException ex = new IllegalArgumentException(
9298 "Requested window " + client + " is in session " +
9299 win.mSession + ", not " + session);
9303 Slog.w(TAG_WM, "Failed looking up window", ex);
9310 final void rebuildAppWindowListLocked() {
9311 rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
9314 private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
9315 final WindowList windows = displayContent.getWindowList();
9316 int NW = windows.size();
9321 if (mRebuildTmp.length < NW) {
9322 mRebuildTmp = new WindowState[NW+10];
9325 // First remove all existing app windows.
9328 WindowState w = windows.get(i);
9329 if (w.mAppToken != null) {
9330 WindowState win = windows.remove(i);
9331 win.mRebuilding = true;
9332 mRebuildTmp[numRemoved] = win;
9333 mWindowsChanged = true;
9334 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win);
9338 } else if (lastBelow == i-1) {
9339 if (w.mAttrs.type == TYPE_WALLPAPER) {
9346 // Keep whatever windows were below the app windows still below,
9347 // by skipping them.
9351 // First add all of the exiting app tokens... these are no longer
9352 // in the main app list, but still have windows shown. We put them
9353 // in the back because now that the animation is over we no longer
9354 // will care about them.
9355 final ArrayList<TaskStack> stacks = displayContent.getStacks();
9356 final int numStacks = stacks.size();
9357 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
9358 AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens;
9359 int NT = exitingAppTokens.size();
9360 for (int j = 0; j < NT; j++) {
9361 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
9365 // And add in the still active app tokens in Z order.
9366 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
9367 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
9368 final int numTasks = tasks.size();
9369 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
9370 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9371 final int numTokens = tokens.size();
9372 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
9373 final AppWindowToken wtoken = tokens.get(tokenNdx);
9374 if (wtoken.mIsExiting && !wtoken.waitingForReplacement()) {
9377 i = reAddAppWindowsLocked(displayContent, i, wtoken);
9383 if (i != numRemoved) {
9384 displayContent.layoutNeeded = true;
9385 Slog.w(TAG_WM, "On display=" + displayContent.getDisplayId() + " Rebuild removed "
9386 + numRemoved + " windows but added " + i + " rebuildAppWindowListLocked() "
9387 + " callers=" + Debug.getCallers(10));
9388 for (i = 0; i < numRemoved; i++) {
9389 WindowState ws = mRebuildTmp[i];
9390 if (ws.mRebuilding) {
9391 StringWriter sw = new StringWriter();
9392 PrintWriter pw = new FastPrintWriter(sw, false, 1024);
9393 ws.dump(pw, "", true);
9395 Slog.w(TAG_WM, "This window was lost: " + ws);
9396 Slog.w(TAG_WM, sw.toString());
9397 ws.mWinAnimator.destroySurfaceLocked();
9400 Slog.w(TAG_WM, "Current app token list:");
9401 dumpAppTokensLocked();
9402 Slog.w(TAG_WM, "Final window list:");
9403 dumpWindowsLocked();
9405 Arrays.fill(mRebuildTmp, null);
9408 void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
9409 // If the screen is currently frozen or off, then keep
9410 // it frozen/off until this window draws at its new
9412 if (!okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
9413 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w);
9414 w.mOrientationChanging = true;
9415 w.mLastFreezeDuration = 0;
9416 mWindowPlacerLocked.mOrientationChangeComplete = false;
9417 if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) {
9418 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
9419 // XXX should probably keep timeout from
9420 // when we first froze the display.
9421 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
9422 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
9423 WINDOW_FREEZE_TIMEOUT_DURATION);
9429 * @return bitmap indicating if another pass through layout must be made.
9431 int handleAnimatingStoppedAndTransitionLocked() {
9434 mAppTransition.setIdle();
9436 for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) {
9437 final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i);
9438 mAppTransition.notifyAppTransitionFinishedLocked(token);
9440 mNoAnimationNotifyOnTransitionFinished.clear();
9442 mWallpaperControllerLocked.hideDeferredWallpapersIfNeeded();
9444 // Restore window app tokens to the ActivityManager views
9445 ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks();
9446 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
9447 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
9448 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9449 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9450 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9451 tokens.get(tokenNdx).sendingToBottom = false;
9455 rebuildAppWindowListLocked();
9457 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
9458 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM,
9459 "Wallpaper layer changed: assigning layers + relayout");
9460 moveInputMethodWindowsIfNeededLocked(true);
9461 mWindowPlacerLocked.mWallpaperMayChange = true;
9462 // Since the window list has been rebuilt, focus might
9463 // have to be recomputed since the actual order of windows
9464 // might have changed again.
9465 mFocusMayChange = true;
9470 void updateResizingWindows(final WindowState w) {
9471 final WindowStateAnimator winAnimator = w.mWinAnimator;
9472 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq && !w.isGoneForLayoutLw()) {
9473 final Task task = w.getTask();
9474 // In the case of stack bound animations, the window frames
9475 // will update (unlike other animations which just modifiy
9476 // various transformation properties). We don't want to
9477 // notify the client of frame changes in this case. Not only
9478 // is it a lot of churn, but the frame may not correspond
9479 // to the surface size or the onscreen area at various
9480 // phases in the animation, and the client will become
9481 // sad and confused.
9482 if (task != null && task.mStack.getBoundsAnimating()) {
9485 w.setReportResizeHints();
9486 boolean configChanged = w.isConfigChanged();
9487 if (DEBUG_CONFIGURATION && configChanged) {
9488 Slog.v(TAG_WM, "Win " + w + " config changed: "
9489 + mCurConfiguration);
9491 final boolean dragResizingChanged = w.isDragResizeChanged()
9492 && !w.isDragResizingChangeReported();
9494 if (localLOGV) Slog.v(TAG_WM, "Resizing " + w
9495 + ": configChanged=" + configChanged
9496 + " dragResizingChanged=" + dragResizingChanged
9497 + " last=" + w.mLastFrame + " frame=" + w.mFrame);
9499 // We update mLastFrame always rather than in the conditional with the
9500 // last inset variables, because mFrameSizeChanged only tracks the
9501 // width and height changing.
9502 w.mLastFrame.set(w.mFrame);
9504 if (w.mContentInsetsChanged
9505 || w.mVisibleInsetsChanged
9506 || winAnimator.mSurfaceResized
9507 || w.mOutsetsChanged
9508 || w.mFrameSizeChanged
9510 || dragResizingChanged
9511 || !w.isResizedWhileNotDragResizingReported()) {
9512 if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
9513 Slog.v(TAG_WM, "Resize reasons for w=" + w + ": "
9514 + " contentInsetsChanged=" + w.mContentInsetsChanged
9515 + " " + w.mContentInsets.toShortString()
9516 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
9517 + " " + w.mVisibleInsets.toShortString()
9518 + " stableInsetsChanged=" + w.mStableInsetsChanged
9519 + " " + w.mStableInsets.toShortString()
9520 + " outsetsChanged=" + w.mOutsetsChanged
9521 + " " + w.mOutsets.toShortString()
9522 + " surfaceResized=" + winAnimator.mSurfaceResized
9523 + " configChanged=" + configChanged
9524 + " dragResizingChanged=" + dragResizingChanged
9525 + " resizedWhileNotDragResizingReported="
9526 + w.isResizedWhileNotDragResizingReported());
9529 // If it's a dead window left on screen, and the configuration changed,
9530 // there is nothing we can do about it. Remove the window now.
9531 if (w.mAppToken != null && w.mAppDied) {
9532 w.mAppToken.removeAllDeadWindows();
9536 w.mLastOverscanInsets.set(w.mOverscanInsets);
9537 w.mLastContentInsets.set(w.mContentInsets);
9538 w.mLastVisibleInsets.set(w.mVisibleInsets);
9539 w.mLastStableInsets.set(w.mStableInsets);
9540 w.mLastOutsets.set(w.mOutsets);
9541 makeWindowFreezingScreenIfNeededLocked(w);
9542 // If the orientation is changing, or we're starting or ending
9543 // a drag resizing action, then we need to hold off on unfreezing
9544 // the display until this window has been redrawn; to do that,
9545 // we need to go through the process of getting informed by the
9546 // application when it has finished drawing.
9547 if (w.mOrientationChanging || dragResizingChanged
9548 || w.isResizedWhileNotDragResizing()) {
9549 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) {
9550 Slog.v(TAG_WM, "Orientation or resize start waiting for draw"
9551 + ", mDrawState=DRAW_PENDING in " + w
9552 + ", surfaceController " + winAnimator.mSurfaceController);
9554 winAnimator.mDrawState = DRAW_PENDING;
9555 if (w.mAppToken != null) {
9556 w.mAppToken.clearAllDrawn();
9559 if (!mResizingWindows.contains(w)) {
9560 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG_WM,
9561 "Resizing window " + w);
9562 mResizingWindows.add(w);
9564 } else if (w.mOrientationChanging) {
9565 if (w.isDrawnLw()) {
9566 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
9567 "Orientation not waiting for draw in "
9568 + w + ", surfaceController " + winAnimator.mSurfaceController);
9569 w.mOrientationChanging = false;
9570 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
9571 - mDisplayFreezeTime);
9577 void checkDrawnWindowsLocked() {
9578 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
9581 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
9582 WindowState win = mWaitingForDrawn.get(j);
9583 if (DEBUG_SCREEN_ON) Slog.i(TAG_WM, "Waiting for drawn " + win +
9584 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
9585 " mHasSurface=" + win.mHasSurface +
9586 " drawState=" + win.mWinAnimator.mDrawState);
9587 if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) {
9588 // Window has been removed or hidden; no draw will now happen, so stop waiting.
9589 if (DEBUG_SCREEN_ON) Slog.w(TAG_WM, "Aborted waiting for drawn: " + win);
9590 mWaitingForDrawn.remove(win);
9591 } else if (win.hasDrawnLw()) {
9592 // Window is now drawn (and shown).
9593 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "Window drawn win=" + win);
9594 mWaitingForDrawn.remove(win);
9597 if (mWaitingForDrawn.isEmpty()) {
9598 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "All windows drawn!");
9599 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
9600 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
9604 void setHoldScreenLocked(final Session newHoldScreen) {
9605 final boolean hold = newHoldScreen != null;
9607 if (hold && mHoldingScreenOn != newHoldScreen) {
9608 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
9610 mHoldingScreenOn = newHoldScreen;
9612 final boolean state = mHoldingScreenWakeLock.isHeld();
9613 if (hold != state) {
9615 if (DEBUG_KEEP_SCREEN_ON) {
9616 Slog.d(TAG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to " +
9617 mWindowPlacerLocked.mHoldScreenWindow);
9619 mLastWakeLockHoldingWindow = mWindowPlacerLocked.mHoldScreenWindow;
9620 mLastWakeLockObscuringWindow = null;
9621 mHoldingScreenWakeLock.acquire();
9622 mPolicy.keepScreenOnStartedLw();
9624 if (DEBUG_KEEP_SCREEN_ON) {
9625 Slog.d(TAG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by " +
9626 mWindowPlacerLocked.mObsuringWindow);
9628 mLastWakeLockHoldingWindow = null;
9629 mLastWakeLockObscuringWindow = mWindowPlacerLocked.mObsuringWindow;
9630 mPolicy.keepScreenOnStoppedLw();
9631 mHoldingScreenWakeLock.release();
9636 void requestTraversal() {
9637 synchronized (mWindowMap) {
9638 mWindowPlacerLocked.requestTraversal();
9642 /** Note that Locked in this case is on mLayoutToAnim */
9643 void scheduleAnimationLocked() {
9644 if (!mAnimationScheduled) {
9645 mAnimationScheduled = true;
9646 mChoreographer.postFrameCallback(mAnimator.mAnimationFrameCallback);
9650 boolean needsLayout() {
9651 final int numDisplays = mDisplayContents.size();
9652 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9653 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9654 if (displayContent.layoutNeeded) {
9661 /** If a window that has an animation specifying a colored background and the current wallpaper
9662 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
9663 * suddenly disappear. */
9664 int adjustAnimationBackground(WindowStateAnimator winAnimator) {
9665 WindowList windows = winAnimator.mWin.getWindowList();
9666 for (int i = windows.size() - 1; i >= 0; --i) {
9667 WindowState testWin = windows.get(i);
9668 if (testWin.mIsWallpaper && testWin.isVisibleNow()) {
9669 return testWin.mWinAnimator.mAnimLayer;
9672 return winAnimator.mAnimLayer;
9675 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
9677 final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
9678 boolean leakedSurface = false;
9679 boolean killedApps = false;
9681 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
9682 winAnimator.mSession.mPid, operation);
9684 final long callingIdentity = Binder.clearCallingIdentity();
9686 // There was some problem... first, do a sanity check of the window list to make sure
9687 // we haven't left any dangling surfaces around.
9689 Slog.i(TAG_WM, "Out of memory for surface! Looking for leaks...");
9690 final int numDisplays = mDisplayContents.size();
9691 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9692 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9693 final int numWindows = windows.size();
9694 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9695 final WindowState ws = windows.get(winNdx);
9696 final WindowStateAnimator wsa = ws.mWinAnimator;
9697 if (wsa.mSurfaceController == null) {
9700 if (!mSessions.contains(wsa.mSession)) {
9701 Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
9702 + ws + " surface=" + wsa.mSurfaceController
9703 + " token=" + ws.mToken
9704 + " pid=" + ws.mSession.mPid
9705 + " uid=" + ws.mSession.mUid);
9706 wsa.destroySurface();
9707 mForceRemoves.add(ws);
9708 leakedSurface = true;
9709 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
9710 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
9711 + ws + " surface=" + wsa.mSurfaceController
9712 + " token=" + ws.mAppToken
9713 + " saved=" + ws.hasSavedSurface());
9714 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
9715 wsa.destroySurface();
9716 leakedSurface = true;
9721 if (!leakedSurface) {
9722 Slog.w(TAG_WM, "No leaked surfaces; killing applicatons!");
9723 SparseIntArray pidCandidates = new SparseIntArray();
9724 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9725 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9726 final int numWindows = windows.size();
9727 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9728 final WindowState ws = windows.get(winNdx);
9729 if (mForceRemoves.contains(ws)) {
9732 WindowStateAnimator wsa = ws.mWinAnimator;
9733 if (wsa.mSurfaceController != null) {
9734 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
9737 if (pidCandidates.size() > 0) {
9738 int[] pids = new int[pidCandidates.size()];
9739 for (int i=0; i<pids.length; i++) {
9740 pids[i] = pidCandidates.keyAt(i);
9743 if (mActivityManager.killPids(pids, "Free memory", secure)) {
9746 } catch (RemoteException e) {
9752 if (leakedSurface || killedApps) {
9753 // We managed to reclaim some memory, so get rid of the trouble
9754 // surface and ask the app to request another one.
9755 Slog.w(TAG_WM, "Looks like we have reclaimed some memory, clearing surface for retry.");
9756 if (surfaceController != null) {
9757 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
9758 "RECOVER DESTROY", false);
9759 winAnimator.destroySurface();
9760 scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken);
9764 winAnimator.mWin.mClient.dispatchGetNewSurface();
9765 } catch (RemoteException e) {
9769 Binder.restoreCallingIdentity(callingIdentity);
9772 return leakedSurface || killedApps;
9775 boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
9776 WindowState newFocus = computeFocusedWindowLocked();
9777 if (mCurrentFocus != newFocus) {
9778 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
9779 // This check makes sure that we don't already have the focus
9780 // change message pending.
9781 mH.removeMessages(H.REPORT_FOCUS_CHANGE);
9782 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
9783 // TODO(multidisplay): Focused windows on default display only.
9784 final DisplayContent displayContent = getDefaultDisplayContentLocked();
9785 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked(
9786 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
9787 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
9788 if (imWindowChanged) {
9789 displayContent.layoutNeeded = true;
9790 newFocus = computeFocusedWindowLocked();
9793 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG_WM, "Changing focus from " +
9794 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
9795 final WindowState oldFocus = mCurrentFocus;
9796 mCurrentFocus = newFocus;
9797 mLosingFocus.remove(newFocus);
9799 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
9801 if (imWindowChanged && oldFocus != mInputMethodWindow) {
9802 // Focus of the input method window changed. Perform layout if needed.
9803 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9804 mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/,
9805 updateInputWindows);
9806 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9807 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
9808 // Client will do the layout, but we need to assign layers
9809 // for handleNewWindowLocked() below.
9810 mLayersController.assignLayersLocked(displayContent.getWindowList());
9814 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9815 // The change in focus caused us to need to do a layout. Okay.
9816 displayContent.layoutNeeded = true;
9817 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9818 mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/,
9819 updateInputWindows);
9823 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
9824 // If we defer assigning layers, then the caller is responsible for
9826 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
9829 adjustForImeIfNeeded(displayContent);
9831 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
9837 private WindowState computeFocusedWindowLocked() {
9838 final int displayCount = mDisplayContents.size();
9839 for (int i = 0; i < displayCount; i++) {
9840 final DisplayContent displayContent = mDisplayContents.valueAt(i);
9841 WindowState win = findFocusedWindowLocked(displayContent);
9849 WindowState findFocusedWindowLocked(DisplayContent displayContent) {
9850 final WindowList windows = displayContent.getWindowList();
9851 for (int i = windows.size() - 1; i >= 0; i--) {
9852 final WindowState win = windows.get(i);
9854 if (localLOGV || DEBUG_FOCUS) Slog.v(
9855 TAG_WM, "Looking for focus: " + i
9857 + ", flags=" + win.mAttrs.flags
9858 + ", canReceive=" + win.canReceiveKeys());
9860 if (!win.canReceiveKeys()) {
9864 AppWindowToken wtoken = win.mAppToken;
9866 // If this window's application has been removed, just skip it.
9867 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
9868 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
9869 + (wtoken.removed ? "removed" : "sendingToBottom"));
9873 // Descend through all of the app tokens and find the first that either matches
9874 // win.mAppToken (return win) or mFocusedApp (return null).
9875 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
9876 mFocusedApp != null) {
9877 ArrayList<Task> tasks = displayContent.getTasks();
9878 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9879 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9880 int tokenNdx = tokens.size() - 1;
9881 for ( ; tokenNdx >= 0; --tokenNdx) {
9882 final AppWindowToken token = tokens.get(tokenNdx);
9883 if (wtoken == token) {
9886 if (mFocusedApp == token && token.windowsAreFocusable()) {
9887 // Whoops, we are below the focused app whose windows are focusable...
9888 // No focus for you!!!
9889 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
9890 "findFocusedWindow: Reached focused app=" + mFocusedApp);
9894 if (tokenNdx >= 0) {
9895 // Early exit from loop, must have found the matching token.
9901 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + i +
9906 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
9910 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
9911 if (mDisplayFrozen) {
9915 if (!mDisplayReady || !mPolicy.isScreenOn()) {
9916 // No need to freeze the screen before the system is ready or if
9917 // the screen is off.
9921 if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
9922 "startFreezingDisplayLocked: inTransaction=" + inTransaction
9923 + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim
9924 + " called by " + Debug.getCallers(8));
9925 mScreenFrozenLock.acquire();
9927 mDisplayFrozen = true;
9928 mDisplayFreezeTime = SystemClock.elapsedRealtime();
9929 mLastFinishedFreezeSource = null;
9931 mInputMonitor.freezeInputDispatchingLw();
9933 // Clear the last input window -- that is just used for
9934 // clean transitions between IMEs, and if we are freezing
9935 // the screen then the whole world is changing behind the scenes.
9936 mPolicy.setLastInputMethodWindowLw(null, null);
9938 if (mAppTransition.isTransitionSet()) {
9939 mAppTransition.freeze();
9942 if (PROFILE_ORIENTATION) {
9943 File file = new File("/data/system/frozen");
9944 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
9947 if (CUSTOM_SCREEN_ROTATION) {
9948 mExitAnimId = exitAnim;
9949 mEnterAnimId = enterAnim;
9950 final DisplayContent displayContent = getDefaultDisplayContentLocked();
9951 final int displayId = displayContent.getDisplayId();
9952 ScreenRotationAnimation screenRotationAnimation =
9953 mAnimator.getScreenRotationAnimationLocked(displayId);
9954 if (screenRotationAnimation != null) {
9955 screenRotationAnimation.kill();
9958 // Check whether the current screen contains any secure content.
9959 boolean isSecure = false;
9960 final WindowList windows = getDefaultWindowListLocked();
9961 final int N = windows.size();
9962 for (int i = 0; i < N; i++) {
9963 WindowState ws = windows.get(i);
9964 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) {
9970 // TODO(multidisplay): rotation on main screen only.
9971 displayContent.updateDisplayInfo();
9972 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
9973 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure);
9974 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9978 void stopFreezingDisplayLocked() {
9979 if (!mDisplayFrozen) {
9983 if (mWaitingForConfig || mAppsFreezingScreen > 0
9984 || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE
9985 || mClientFreezingScreen || !mOpeningApps.isEmpty()) {
9986 if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
9987 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
9988 + ", mAppsFreezingScreen=" + mAppsFreezingScreen
9989 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
9990 + ", mClientFreezingScreen=" + mClientFreezingScreen
9991 + ", mOpeningApps.size()=" + mOpeningApps.size());
9995 if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
9996 "stopFreezingDisplayLocked: Unfreezing now");
9998 mDisplayFrozen = false;
9999 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
10000 StringBuilder sb = new StringBuilder(128);
10001 sb.append("Screen frozen for ");
10002 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
10003 if (mLastFinishedFreezeSource != null) {
10004 sb.append(" due to ");
10005 sb.append(mLastFinishedFreezeSource);
10007 Slog.i(TAG_WM, sb.toString());
10008 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
10009 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
10010 if (PROFILE_ORIENTATION) {
10011 Debug.stopMethodTracing();
10014 boolean updateRotation = false;
10016 final DisplayContent displayContent = getDefaultDisplayContentLocked();
10017 final int displayId = displayContent.getDisplayId();
10018 ScreenRotationAnimation screenRotationAnimation =
10019 mAnimator.getScreenRotationAnimationLocked(displayId);
10020 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
10021 && screenRotationAnimation.hasScreenshot()) {
10022 if (DEBUG_ORIENTATION) Slog.i(TAG_WM, "**** Dismissing screen rotation animation");
10023 // TODO(multidisplay): rotation on main screen only.
10024 DisplayInfo displayInfo = displayContent.getDisplayInfo();
10025 // Get rotation animation again, with new top window
10026 boolean isDimming = displayContent.isDimming();
10027 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
10028 mExitAnimId = mEnterAnimId = 0;
10030 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
10031 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth,
10032 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
10033 scheduleAnimationLocked();
10035 screenRotationAnimation.kill();
10036 mAnimator.setScreenRotationAnimationLocked(displayId, null);
10037 updateRotation = true;
10040 if (screenRotationAnimation != null) {
10041 screenRotationAnimation.kill();
10042 mAnimator.setScreenRotationAnimationLocked(displayId, null);
10044 updateRotation = true;
10047 mInputMonitor.thawInputDispatchingLw();
10049 boolean configChanged;
10051 // While the display is frozen we don't re-compute the orientation
10052 // to avoid inconsistent states. However, something interesting
10053 // could have actually changed during that time so re-evaluate it
10054 // now to catch that.
10055 configChanged = updateOrientationFromAppTokensLocked(false);
10057 // A little kludge: a lot could have happened while the
10058 // display was frozen, so now that we are coming back we
10059 // do a gc so that any remote references the system
10060 // processes holds on others can be released if they are
10061 // no longer needed.
10062 mH.removeMessages(H.FORCE_GC);
10063 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
10065 mScreenFrozenLock.release();
10067 if (updateRotation) {
10068 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation");
10069 configChanged |= updateRotationUncheckedLocked(false);
10072 if (configChanged) {
10073 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
10077 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
10078 DisplayMetrics dm) {
10079 if (index < tokens.length) {
10080 String str = tokens[index];
10081 if (str != null && str.length() > 0) {
10083 int val = Integer.parseInt(str);
10085 } catch (Exception e) {
10089 if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
10092 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
10096 void createWatermarkInTransaction() {
10097 if (mWatermark != null) {
10101 File file = new File("/system/etc/setup.conf");
10102 FileInputStream in = null;
10103 DataInputStream ind = null;
10105 in = new FileInputStream(file);
10106 ind = new DataInputStream(in);
10107 String line = ind.readLine();
10108 if (line != null) {
10109 String[] toks = line.split("%");
10110 if (toks != null && toks.length > 0) {
10111 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
10112 mRealDisplayMetrics, mFxSession, toks);
10115 } catch (FileNotFoundException e) {
10116 } catch (IOException e) {
10121 } catch (IOException e) {
10123 } else if (in != null) {
10126 } catch (IOException e) {
10133 public void statusBarVisibilityChanged(int visibility) {
10134 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
10135 != PackageManager.PERMISSION_GRANTED) {
10136 throw new SecurityException("Caller does not hold permission "
10137 + android.Manifest.permission.STATUS_BAR);
10140 synchronized (mWindowMap) {
10141 mLastStatusBarVisibility = visibility;
10142 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
10143 updateStatusBarVisibilityLocked(visibility);
10147 // TOOD(multidisplay): StatusBar on multiple screens?
10148 boolean updateStatusBarVisibilityLocked(int visibility) {
10149 if (mLastDispatchedSystemUiVisibility == visibility) {
10152 final int globalDiff = (visibility ^ mLastDispatchedSystemUiVisibility)
10153 // We are only interested in differences of one of the
10154 // clearable flags...
10155 & View.SYSTEM_UI_CLEARABLE_FLAGS
10156 // ...if it has actually been cleared.
10159 mLastDispatchedSystemUiVisibility = visibility;
10160 mInputManager.setSystemUiVisibility(visibility);
10161 final WindowList windows = getDefaultWindowListLocked();
10162 final int N = windows.size();
10163 for (int i = 0; i < N; i++) {
10164 WindowState ws = windows.get(i);
10166 int curValue = ws.mSystemUiVisibility;
10167 int diff = (curValue ^ visibility) & globalDiff;
10168 int newValue = (curValue&~diff) | (visibility&diff);
10169 if (newValue != curValue) {
10171 ws.mSystemUiVisibility = newValue;
10173 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
10174 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
10175 visibility, newValue, diff);
10177 } catch (RemoteException e) {
10185 public void reevaluateStatusBarVisibility() {
10186 synchronized (mWindowMap) {
10187 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
10188 if (updateStatusBarVisibilityLocked(visibility)) {
10189 mWindowPlacerLocked.requestTraversal();
10194 private static final class HideNavInputConsumer extends InputConsumerImpl
10195 implements WindowManagerPolicy.InputConsumer {
10196 private final InputEventReceiver mInputEventReceiver;
10198 HideNavInputConsumer(WindowManagerService service, Looper looper,
10199 InputEventReceiver.Factory inputEventReceiverFactory) {
10200 super(service, "input consumer", null);
10201 mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver(
10202 mClientChannel, looper);
10206 public void dismiss() {
10207 if (mService.removeInputConsumer()) {
10208 synchronized (mService.mWindowMap) {
10209 mInputEventReceiver.dispose();
10210 disposeChannelsLw();
10217 public WindowManagerPolicy.InputConsumer addInputConsumer(Looper looper,
10218 InputEventReceiver.Factory inputEventReceiverFactory) {
10219 synchronized (mWindowMap) {
10220 HideNavInputConsumer inputConsumerImpl = new HideNavInputConsumer(
10221 this, looper, inputEventReceiverFactory);
10222 mInputConsumer = inputConsumerImpl;
10223 mInputMonitor.updateInputWindowsLw(true);
10224 return inputConsumerImpl;
10228 boolean removeInputConsumer() {
10229 synchronized (mWindowMap) {
10230 if (mInputConsumer != null) {
10231 mInputConsumer = null;
10232 mInputMonitor.updateInputWindowsLw(true);
10240 public void createWallpaperInputConsumer(InputChannel inputChannel) {
10241 synchronized (mWindowMap) {
10242 mWallpaperInputConsumer = new InputConsumerImpl(this, "wallpaper input", inputChannel);
10243 mWallpaperInputConsumer.mWindowHandle.hasWallpaper = true;
10244 mInputMonitor.updateInputWindowsLw(true);
10249 public void removeWallpaperInputConsumer() {
10250 synchronized (mWindowMap) {
10251 if (mWallpaperInputConsumer != null) {
10252 mWallpaperInputConsumer.disposeChannelsLw();
10253 mWallpaperInputConsumer = null;
10254 mInputMonitor.updateInputWindowsLw(true);
10260 public boolean hasNavigationBar() {
10261 return mPolicy.hasNavigationBar();
10265 public void lockNow(Bundle options) {
10266 mPolicy.lockNow(options);
10269 public void showRecentApps(boolean fromHome) {
10270 mPolicy.showRecentApps(fromHome);
10274 public boolean isSafeModeEnabled() {
10279 public boolean clearWindowContentFrameStats(IBinder token) {
10280 if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
10281 "clearWindowContentFrameStats()")) {
10282 throw new SecurityException("Requires FRAME_STATS permission");
10284 synchronized (mWindowMap) {
10285 WindowState windowState = mWindowMap.get(token);
10286 if (windowState == null) {
10289 WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
10290 if (surfaceController == null) {
10293 return surfaceController.clearWindowContentFrameStats();
10298 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
10299 if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
10300 "getWindowContentFrameStats()")) {
10301 throw new SecurityException("Requires FRAME_STATS permission");
10303 synchronized (mWindowMap) {
10304 WindowState windowState = mWindowMap.get(token);
10305 if (windowState == null) {
10308 WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
10309 if (surfaceController == null) {
10312 if (mTempWindowRenderStats == null) {
10313 mTempWindowRenderStats = new WindowContentFrameStats();
10315 WindowContentFrameStats stats = mTempWindowRenderStats;
10316 if (!surfaceController.getWindowContentFrameStats(stats)) {
10323 public void notifyAppRelaunching(IBinder token) {
10324 synchronized (mWindowMap) {
10325 AppWindowToken appWindow = findAppWindowToken(token);
10326 if (appWindow != null) {
10327 appWindow.startRelaunching();
10332 public void notifyAppRelaunchingFinished(IBinder token) {
10333 synchronized (mWindowMap) {
10334 AppWindowToken appWindow = findAppWindowToken(token);
10335 if (appWindow != null) {
10336 appWindow.finishRelaunching();
10341 public void notifyAppRelaunchesCleared(IBinder token) {
10342 synchronized (mWindowMap) {
10343 final AppWindowToken appWindow = findAppWindowToken(token);
10344 if (appWindow != null) {
10345 appWindow.clearRelaunching();
10351 public int getDockedDividerInsetsLw() {
10352 return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets();
10355 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10356 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
10357 mPolicy.dump(" ", pw, args);
10360 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10361 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
10362 mAnimator.dumpLocked(pw, " ", dumpAll);
10365 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
10366 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
10367 if (!mTokenMap.isEmpty()) {
10368 pw.println(" All tokens:");
10369 Iterator<WindowToken> it = mTokenMap.values().iterator();
10370 while (it.hasNext()) {
10371 WindowToken token = it.next();
10372 pw.print(" "); pw.print(token);
10375 token.dump(pw, " ");
10381 mWallpaperControllerLocked.dumpTokens(pw, " ", dumpAll);
10382 if (!mFinishedStarting.isEmpty()) {
10384 pw.println(" Finishing start of application tokens:");
10385 for (int i=mFinishedStarting.size()-1; i>=0; i--) {
10386 WindowToken token = mFinishedStarting.get(i);
10387 pw.print(" Finished Starting #"); pw.print(i);
10388 pw.print(' '); pw.print(token);
10391 token.dump(pw, " ");
10397 if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty()) {
10399 if (mOpeningApps.size() > 0) {
10400 pw.print(" mOpeningApps="); pw.println(mOpeningApps);
10402 if (mClosingApps.size() > 0) {
10403 pw.print(" mClosingApps="); pw.println(mClosingApps);
10408 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
10409 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
10410 for (int i=0; i<mSessions.size(); i++) {
10411 Session s = mSessions.valueAt(i);
10412 pw.print(" Session "); pw.print(s); pw.println(':');
10417 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
10418 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
10419 if (mDisplayReady) {
10420 final int numDisplays = mDisplayContents.size();
10421 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10422 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10423 displayContent.dump(" ", pw);
10426 pw.println(" NO DISPLAY");
10430 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
10431 ArrayList<WindowState> windows) {
10432 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
10433 dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
10436 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
10437 ArrayList<WindowState> windows) {
10438 final int numDisplays = mDisplayContents.size();
10439 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10440 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
10441 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10442 final WindowState w = windowList.get(winNdx);
10443 if (windows == null || windows.contains(w)) {
10444 pw.print(" Window #"); pw.print(winNdx); pw.print(' ');
10445 pw.print(w); pw.println(":");
10446 w.dump(pw, " ", dumpAll || windows != null);
10450 if (mInputMethodDialogs.size() > 0) {
10452 pw.println(" Input method dialogs:");
10453 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
10454 WindowState w = mInputMethodDialogs.get(i);
10455 if (windows == null || windows.contains(w)) {
10456 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
10460 if (mPendingRemove.size() > 0) {
10462 pw.println(" Remove pending for:");
10463 for (int i=mPendingRemove.size()-1; i>=0; i--) {
10464 WindowState w = mPendingRemove.get(i);
10465 if (windows == null || windows.contains(w)) {
10466 pw.print(" Remove #"); pw.print(i); pw.print(' ');
10470 w.dump(pw, " ", true);
10477 if (mForceRemoves != null && mForceRemoves.size() > 0) {
10479 pw.println(" Windows force removing:");
10480 for (int i=mForceRemoves.size()-1; i>=0; i--) {
10481 WindowState w = mForceRemoves.get(i);
10482 pw.print(" Removing #"); pw.print(i); pw.print(' ');
10486 w.dump(pw, " ", true);
10492 if (mDestroySurface.size() > 0) {
10494 pw.println(" Windows waiting to destroy their surface:");
10495 for (int i=mDestroySurface.size()-1; i>=0; i--) {
10496 WindowState w = mDestroySurface.get(i);
10497 if (windows == null || windows.contains(w)) {
10498 pw.print(" Destroy #"); pw.print(i); pw.print(' ');
10502 w.dump(pw, " ", true);
10509 if (mLosingFocus.size() > 0) {
10511 pw.println(" Windows losing focus:");
10512 for (int i=mLosingFocus.size()-1; i>=0; i--) {
10513 WindowState w = mLosingFocus.get(i);
10514 if (windows == null || windows.contains(w)) {
10515 pw.print(" Losing #"); pw.print(i); pw.print(' ');
10519 w.dump(pw, " ", true);
10526 if (mResizingWindows.size() > 0) {
10528 pw.println(" Windows waiting to resize:");
10529 for (int i=mResizingWindows.size()-1; i>=0; i--) {
10530 WindowState w = mResizingWindows.get(i);
10531 if (windows == null || windows.contains(w)) {
10532 pw.print(" Resizing #"); pw.print(i); pw.print(' ');
10536 w.dump(pw, " ", true);
10543 if (mWaitingForDrawn.size() > 0) {
10545 pw.println(" Clients waiting for these windows to be drawn:");
10546 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
10547 WindowState win = mWaitingForDrawn.get(i);
10548 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
10552 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration);
10553 pw.print(" mHasPermanentDpad="); pw.println(mHasPermanentDpad);
10554 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus);
10555 if (mLastFocus != mCurrentFocus) {
10556 pw.print(" mLastFocus="); pw.println(mLastFocus);
10558 pw.print(" mFocusedApp="); pw.println(mFocusedApp);
10559 if (mInputMethodTarget != null) {
10560 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
10562 pw.print(" mInTouchMode="); pw.print(mInTouchMode);
10563 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
10564 pw.print(" mLastDisplayFreezeDuration=");
10565 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
10566 if ( mLastFinishedFreezeSource != null) {
10567 pw.print(" due to ");
10568 pw.print(mLastFinishedFreezeSource);
10571 pw.print(" mLastWakeLockHoldingWindow=");pw.print(mLastWakeLockHoldingWindow);
10572 pw.print(" mLastWakeLockObscuringWindow="); pw.print(mLastWakeLockObscuringWindow);
10575 mInputMonitor.dump(pw, " ");
10578 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer);
10579 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
10580 if (mLastStatusBarVisibility != 0) {
10581 pw.print(" mLastStatusBarVisibility=0x");
10582 pw.println(Integer.toHexString(mLastStatusBarVisibility));
10584 if (mInputMethodWindow != null) {
10585 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
10587 mWindowPlacerLocked.dump(pw, " ");
10588 mWallpaperControllerLocked.dump(pw, " ");
10589 mLayersController.dump(pw, " ");
10590 pw.print(" mSystemBooted="); pw.print(mSystemBooted);
10591 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
10592 if (needsLayout()) {
10593 pw.print(" layoutNeeded on displays=");
10594 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10595 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10596 if (displayContent.layoutNeeded) {
10597 pw.print(displayContent.getDisplayId());
10602 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence);
10603 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen);
10604 pw.print(" windows="); pw.print(mWindowsFreezingScreen);
10605 pw.print(" client="); pw.print(mClientFreezingScreen);
10606 pw.print(" apps="); pw.print(mAppsFreezingScreen);
10607 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
10608 pw.print(" mRotation="); pw.print(mRotation);
10609 pw.print(" mAltOrientation="); pw.println(mAltOrientation);
10610 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
10611 pw.print(" mLastOrientation="); pw.println(mLastOrientation);
10612 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
10613 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled);
10614 pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
10615 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
10616 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting);
10617 pw.print(" mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation);
10618 pw.println(" mLayoutToAnim:");
10619 mAppTransition.dump(pw, " ");
10623 boolean dumpWindows(PrintWriter pw, String name, String[] args,
10624 int opti, boolean dumpAll) {
10625 WindowList windows = new WindowList();
10626 if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
10627 final boolean appsOnly = name.contains("apps");
10628 final boolean visibleOnly = name.contains("visible");
10629 synchronized(mWindowMap) {
10631 dumpDisplayContentsLocked(pw, true);
10634 final int numDisplays = mDisplayContents.size();
10635 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10636 final WindowList windowList =
10637 mDisplayContents.valueAt(displayNdx).getWindowList();
10638 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10639 final WindowState w = windowList.get(winNdx);
10640 if ((!visibleOnly || w.mWinAnimator.getShown())
10641 && (!appsOnly || w.mAppToken != null)) {
10649 // See if this is an object ID.
10651 objectId = Integer.parseInt(name, 16);
10653 } catch (RuntimeException e) {
10655 synchronized(mWindowMap) {
10656 final int numDisplays = mDisplayContents.size();
10657 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10658 final WindowList windowList =
10659 mDisplayContents.valueAt(displayNdx).getWindowList();
10660 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10661 final WindowState w = windowList.get(winNdx);
10662 if (name != null) {
10663 if (w.mAttrs.getTitle().toString().contains(name)) {
10666 } else if (System.identityHashCode(w) == objectId) {
10674 if (windows.size() <= 0) {
10678 synchronized(mWindowMap) {
10679 dumpWindowsLocked(pw, dumpAll, windows);
10684 void dumpLastANRLocked(PrintWriter pw) {
10685 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
10686 if (mLastANRState == null) {
10687 pw.println(" <no ANR has occurred since boot>");
10689 pw.println(mLastANRState);
10694 * Saves information about the state of the window manager at
10695 * the time an ANR occurred before anything else in the system changes
10698 * @param appWindowToken The application that ANR'd, may be null.
10699 * @param windowState The window that ANR'd, may be null.
10700 * @param reason The reason for the ANR, may be null.
10702 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState,
10704 StringWriter sw = new StringWriter();
10705 PrintWriter pw = new FastPrintWriter(sw, false, 1024);
10706 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date()));
10707 if (appWindowToken != null) {
10708 pw.println(" Application at fault: " + appWindowToken.stringName);
10710 if (windowState != null) {
10711 pw.println(" Window at fault: " + windowState.mAttrs.getTitle());
10713 if (reason != null) {
10714 pw.println(" Reason: " + reason);
10717 dumpWindowsNoHeaderLocked(pw, true, null);
10719 pw.println("Last ANR continued");
10720 dumpDisplayContentsLocked(pw, true);
10722 mLastANRState = sw.toString();
10724 mH.removeMessages(H.RESET_ANR_MESSAGE);
10725 mH.sendEmptyMessageDelayed(H.RESET_ANR_MESSAGE, LAST_ANR_LIFETIME_DURATION_MSECS);
10729 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10730 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
10731 != PackageManager.PERMISSION_GRANTED) {
10732 pw.println("Permission Denial: can't dump WindowManager from from pid="
10733 + Binder.getCallingPid()
10734 + ", uid=" + Binder.getCallingUid());
10738 boolean dumpAll = false;
10741 while (opti < args.length) {
10742 String opt = args[opti];
10743 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10747 if ("-a".equals(opt)) {
10749 } else if ("-h".equals(opt)) {
10750 pw.println("Window manager dump options:");
10751 pw.println(" [-a] [-h] [cmd] ...");
10752 pw.println(" cmd may be one of:");
10753 pw.println(" l[astanr]: last ANR information");
10754 pw.println(" p[policy]: policy state");
10755 pw.println(" a[animator]: animator state");
10756 pw.println(" s[essions]: active sessions");
10757 pw.println(" surfaces: active surfaces (debugging enabled only)");
10758 pw.println(" d[isplays]: active display contents");
10759 pw.println(" t[okens]: token list");
10760 pw.println(" w[indows]: window list");
10761 pw.println(" cmd may also be a NAME to dump windows. NAME may");
10762 pw.println(" be a partial substring in a window name, a");
10763 pw.println(" Window hex object identifier, or");
10764 pw.println(" \"all\" for all windows, or");
10765 pw.println(" \"visible\" for the visible windows.");
10766 pw.println(" \"visible-apps\" for the visible app windows.");
10767 pw.println(" -a: include all available server state.");
10770 pw.println("Unknown argument: " + opt + "; use -h for help");
10774 // Is the caller requesting to dump a particular piece of data?
10775 if (opti < args.length) {
10776 String cmd = args[opti];
10778 if ("lastanr".equals(cmd) || "l".equals(cmd)) {
10779 synchronized(mWindowMap) {
10780 dumpLastANRLocked(pw);
10783 } else if ("policy".equals(cmd) || "p".equals(cmd)) {
10784 synchronized(mWindowMap) {
10785 dumpPolicyLocked(pw, args, true);
10788 } else if ("animator".equals(cmd) || "a".equals(cmd)) {
10789 synchronized(mWindowMap) {
10790 dumpAnimatorLocked(pw, args, true);
10793 } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
10794 synchronized(mWindowMap) {
10795 dumpSessionsLocked(pw, true);
10798 } else if ("surfaces".equals(cmd)) {
10799 synchronized(mWindowMap) {
10800 WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, null);
10803 } else if ("displays".equals(cmd) || "d".equals(cmd)) {
10804 synchronized(mWindowMap) {
10805 dumpDisplayContentsLocked(pw, true);
10808 } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
10809 synchronized(mWindowMap) {
10810 dumpTokensLocked(pw, true);
10813 } else if ("windows".equals(cmd) || "w".equals(cmd)) {
10814 synchronized(mWindowMap) {
10815 dumpWindowsLocked(pw, true, null);
10818 } else if ("all".equals(cmd) || "a".equals(cmd)) {
10819 synchronized(mWindowMap) {
10820 dumpWindowsLocked(pw, true, null);
10824 // Dumping a single name?
10825 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
10826 pw.println("Bad window command, or no windows match: " + cmd);
10827 pw.println("Use -h for help.");
10833 synchronized(mWindowMap) {
10836 pw.println("-------------------------------------------------------------------------------");
10838 dumpLastANRLocked(pw);
10841 pw.println("-------------------------------------------------------------------------------");
10843 dumpPolicyLocked(pw, args, dumpAll);
10846 pw.println("-------------------------------------------------------------------------------");
10848 dumpAnimatorLocked(pw, args, dumpAll);
10851 pw.println("-------------------------------------------------------------------------------");
10853 dumpSessionsLocked(pw, dumpAll);
10856 pw.println("-------------------------------------------------------------------------------");
10858 WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ?
10859 "-------------------------------------------------------------------------------"
10863 pw.println("-------------------------------------------------------------------------------");
10865 dumpDisplayContentsLocked(pw, dumpAll);
10868 pw.println("-------------------------------------------------------------------------------");
10870 dumpTokensLocked(pw, dumpAll);
10873 pw.println("-------------------------------------------------------------------------------");
10875 dumpWindowsLocked(pw, dumpAll, null);
10879 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
10881 public void monitor() {
10882 synchronized (mWindowMap) { }
10885 private DisplayContent newDisplayContentLocked(final Display display) {
10886 DisplayContent displayContent = new DisplayContent(display, this);
10887 final int displayId = display.getDisplayId();
10888 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
10889 mDisplayContents.put(displayId, displayContent);
10891 DisplayInfo displayInfo = displayContent.getDisplayInfo();
10892 final Rect rect = new Rect();
10893 mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
10894 displayInfo.overscanLeft = rect.left;
10895 displayInfo.overscanTop = rect.top;
10896 displayInfo.overscanRight = rect.right;
10897 displayInfo.overscanBottom = rect.bottom;
10898 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayId, displayInfo);
10899 configureDisplayPolicyLocked(displayContent);
10901 // TODO: Create an input channel for each display with touch capability.
10902 if (displayId == Display.DEFAULT_DISPLAY) {
10903 displayContent.mTapDetector = new TaskTapPointerEventListener(this, displayContent);
10904 registerPointerEventListener(displayContent.mTapDetector);
10905 registerPointerEventListener(mMousePositionTracker);
10908 return displayContent;
10911 public void createDisplayContentLocked(final Display display) {
10912 if (display == null) {
10913 throw new IllegalArgumentException("getDisplayContent: display must not be null");
10915 getDisplayContentLocked(display.getDisplayId());
10919 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
10920 * there is a Display for the displayId.
10921 * @param displayId The display the caller is interested in.
10922 * @return The DisplayContent associated with displayId or null if there is no Display for it.
10924 public DisplayContent getDisplayContentLocked(final int displayId) {
10925 DisplayContent displayContent = mDisplayContents.get(displayId);
10926 if (displayContent == null) {
10927 final Display display = mDisplayManager.getDisplay(displayId);
10928 if (display != null) {
10929 displayContent = newDisplayContentLocked(display);
10932 return displayContent;
10935 // There is an inherent assumption that this will never return null.
10936 public DisplayContent getDefaultDisplayContentLocked() {
10937 return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
10940 public WindowList getDefaultWindowListLocked() {
10941 return getDefaultDisplayContentLocked().getWindowList();
10944 public DisplayInfo getDefaultDisplayInfoLocked() {
10945 return getDefaultDisplayContentLocked().getDisplayInfo();
10949 * Return the list of WindowStates associated on the passed display.
10950 * @param display The screen to return windows from.
10951 * @return The list of WindowStates on the screen, or null if the there is no screen.
10953 public WindowList getWindowListLocked(final Display display) {
10954 return getWindowListLocked(display.getDisplayId());
10958 * Return the list of WindowStates associated on the passed display.
10959 * @param displayId The screen to return windows from.
10960 * @return The list of WindowStates on the screen, or null if the there is no screen.
10962 public WindowList getWindowListLocked(final int displayId) {
10963 final DisplayContent displayContent = getDisplayContentLocked(displayId);
10964 return displayContent != null ? displayContent.getWindowList() : null;
10967 public void onDisplayAdded(int displayId) {
10968 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
10971 public void handleDisplayAdded(int displayId) {
10972 synchronized (mWindowMap) {
10973 final Display display = mDisplayManager.getDisplay(displayId);
10974 if (display != null) {
10975 createDisplayContentLocked(display);
10976 displayReady(displayId);
10978 mWindowPlacerLocked.requestTraversal();
10982 public void onDisplayRemoved(int displayId) {
10983 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
10986 private void handleDisplayRemovedLocked(int displayId) {
10987 final DisplayContent displayContent = getDisplayContentLocked(displayId);
10988 if (displayContent != null) {
10989 if (displayContent.isAnimating()) {
10990 displayContent.mDeferredRemoval = true;
10993 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + displayContent);
10994 mDisplayContents.delete(displayId);
10995 displayContent.close();
10996 if (displayId == Display.DEFAULT_DISPLAY) {
10997 unregisterPointerEventListener(displayContent.mTapDetector);
10998 unregisterPointerEventListener(mMousePositionTracker);
11001 mAnimator.removeDisplayLocked(displayId);
11002 mWindowPlacerLocked.requestTraversal();
11005 public void onDisplayChanged(int displayId) {
11006 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
11009 private void handleDisplayChangedLocked(int displayId) {
11010 final DisplayContent displayContent = getDisplayContentLocked(displayId);
11011 if (displayContent != null) {
11012 displayContent.updateDisplayInfo();
11014 mWindowPlacerLocked.requestTraversal();
11018 public Object getWindowManagerLock() {
11023 * Hint to a token that its activity will relaunch, which will trigger removal and addition of
11025 * @param token Application token for which the activity will be relaunched.
11027 public void setReplacingWindow(IBinder token, boolean animate) {
11028 AppWindowToken appWindowToken = null;
11029 synchronized (mWindowMap) {
11030 appWindowToken = findAppWindowToken(token);
11031 if (appWindowToken == null || !appWindowToken.isVisible()) {
11032 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
11036 appWindowToken.setReplacingWindows(animate);
11041 * Hint to a token that its windows will be replaced across activity relaunch.
11042 * The windows would otherwise be removed shortly following this as the
11043 * activity is torn down.
11044 * @param token Application token for which the activity will be relaunched.
11045 * @param childrenOnly Whether to mark only child windows for replacement
11046 * (for the case where main windows are being preserved/
11047 * reused rather than replaced).
11050 public void setReplacingWindows(IBinder token, boolean childrenOnly) {
11051 AppWindowToken appWindowToken = null;
11052 synchronized (mWindowMap) {
11053 appWindowToken = findAppWindowToken(token);
11054 if (appWindowToken == null || !appWindowToken.isVisible()) {
11055 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
11060 if (childrenOnly) {
11061 appWindowToken.setReplacingChildren();
11063 appWindowToken.setReplacingWindows(false /* animate */);
11066 scheduleClearReplacingWindowIfNeeded(token, true /* replacing */);
11071 * If we're replacing the window, schedule a timer to clear the replaced window
11072 * after a timeout, in case the replacing window is not coming.
11074 * If we're not replacing the window, clear the replace window settings of the app.
11076 * @param token Application token for the activity whose window might be replaced.
11077 * @param replacing Whether the window is being replaced or not.
11079 public void scheduleClearReplacingWindowIfNeeded(IBinder token, boolean replacing) {
11080 AppWindowToken appWindowToken = null;
11081 synchronized (mWindowMap) {
11082 appWindowToken = findAppWindowToken(token);
11083 if (appWindowToken == null) {
11084 Slog.w(TAG_WM, "Attempted to reset replacing window on non-existing app token "
11089 scheduleReplacingWindowTimeouts(appWindowToken);
11091 appWindowToken.resetReplacingWindows();
11096 void scheduleReplacingWindowTimeouts(AppWindowToken appWindowToken) {
11097 if (!mReplacingWindowTimeouts.contains(appWindowToken)) {
11098 mReplacingWindowTimeouts.add(appWindowToken);
11100 mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
11101 mH.sendEmptyMessageDelayed(
11102 H.WINDOW_REPLACEMENT_TIMEOUT, WINDOW_REPLACEMENT_TIMEOUT_DURATION);
11106 public int getDockedStackSide() {
11107 synchronized (mWindowMap) {
11108 final TaskStack dockedStack = getDefaultDisplayContentLocked()
11109 .getDockedStackVisibleForUserLocked();
11110 return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide();
11115 public void setDockedStackResizing(boolean resizing) {
11116 synchronized (mWindowMap) {
11117 getDefaultDisplayContentLocked().getDockedDividerController().setResizing(resizing);
11118 requestTraversal();
11123 public void setDockedStackDividerTouchRegion(Rect touchRegion) {
11124 synchronized (mWindowMap) {
11125 getDefaultDisplayContentLocked().getDockedDividerController()
11126 .setTouchRegion(touchRegion);
11127 setFocusTaskRegionLocked();
11132 public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
11133 synchronized (mWindowMap) {
11134 getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer(
11135 visible, targetStackId, alpha);
11139 public void animateResizePinnedStack(final Rect bounds, final int animationDuration) {
11140 synchronized (mWindowMap) {
11141 final TaskStack stack = mStackIdToStack.get(PINNED_STACK_ID);
11142 if (stack == null) {
11143 Slog.w(TAG, "animateResizePinnedStack: stackId " + PINNED_STACK_ID + " not found.");
11146 final Rect originalBounds = new Rect();
11147 stack.getBounds(originalBounds);
11148 UiThread.getHandler().post(new Runnable() {
11150 public void run() {
11151 mBoundsAnimationController.animateBounds(
11152 stack, originalBounds, bounds, animationDuration);
11158 public void setTaskResizeable(int taskId, int resizeMode) {
11159 synchronized (mWindowMap) {
11160 final Task task = mTaskIdToTask.get(taskId);
11161 if (task != null) {
11162 task.setResizeable(resizeMode);
11167 public void setForceResizableTasks(boolean forceResizableTasks) {
11168 synchronized (mWindowMap) {
11169 mForceResizableTasks = forceResizableTasks;
11173 static int dipToPixel(int dip, DisplayMetrics displayMetrics) {
11174 return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics);
11178 public void registerDockedStackListener(IDockedStackListener listener) {
11179 if (!checkCallingPermission(android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS,
11180 "registerDockedStackListener()")) {
11183 // TODO(multi-display): The listener is registered on the default display only.
11184 getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener(
11189 public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
11191 WindowState focusedWindow = getFocusedWindow();
11192 if (focusedWindow != null && focusedWindow.mClient != null) {
11193 getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId);
11195 } catch (RemoteException e) {
11200 public void getStableInsets(Rect outInsets) throws RemoteException {
11201 synchronized (mWindowMap) {
11202 getStableInsetsLocked(outInsets);
11206 void getStableInsetsLocked(Rect outInsets) {
11207 final DisplayInfo di = getDefaultDisplayInfoLocked();
11208 mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
11211 private void getNonDecorInsetsLocked(Rect outInsets) {
11212 final DisplayInfo di = getDefaultDisplayInfoLocked();
11213 mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
11217 * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable
11220 * @param inOutBounds The inOutBounds to subtract the stable inset areas from.
11222 public void subtractStableInsets(Rect inOutBounds) {
11223 synchronized (mWindowMap) {
11224 getStableInsetsLocked(mTmpRect2);
11225 final DisplayInfo di = getDefaultDisplayInfoLocked();
11226 mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
11227 subtractInsets(mTmpRect, mTmpRect2, inOutBounds);
11232 * Intersects the specified {@code inOutBounds} with the display frame that excludes
11233 * areas that could never be removed in Honeycomb. See
11234 * {@link WindowManagerPolicy#getNonDecorInsetsLw}.
11236 * @param inOutBounds The inOutBounds to subtract the inset areas from.
11238 public void subtractNonDecorInsets(Rect inOutBounds) {
11239 synchronized (mWindowMap) {
11240 getNonDecorInsetsLocked(mTmpRect2);
11241 final DisplayInfo di = getDefaultDisplayInfoLocked();
11242 mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
11243 subtractInsets(mTmpRect, mTmpRect2, inOutBounds);
11247 void subtractInsets(Rect display, Rect insets, Rect inOutBounds) {
11248 mTmpRect3.set(display);
11249 mTmpRect3.inset(insets);
11250 inOutBounds.intersect(mTmpRect3);
11254 * Calculates the smallest width for a task given the {@param bounds}. It does that by iterating
11255 * across all screen orientations, and returns the minimum of the task width taking into account
11256 * that the bounds might change because the snap algorithm snaps to a different value.
11258 * @return the smallest width to be used in the Configuration, in dips
11260 public int getSmallestWidthForTaskBounds(Rect bounds) {
11261 synchronized (mWindowMap) {
11262 return getDefaultDisplayContentLocked().getDockedDividerController()
11263 .getSmallestWidthDpForBounds(bounds);
11267 private MousePositionTracker mMousePositionTracker = new MousePositionTracker();
11269 private static class MousePositionTracker implements PointerEventListener {
11270 private boolean mLatestEventWasMouse;
11271 private float mLatestMouseX;
11272 private float mLatestMouseY;
11274 void updatePosition(float x, float y) {
11275 synchronized (this) {
11276 mLatestEventWasMouse = true;
11283 public void onPointerEvent(MotionEvent motionEvent) {
11284 if (motionEvent.isFromSource(InputDevice.SOURCE_MOUSE)) {
11285 updatePosition(motionEvent.getRawX(), motionEvent.getRawY());
11287 synchronized (this) {
11288 mLatestEventWasMouse = false;
11294 void updatePointerIcon(IWindow client) {
11295 float mouseX, mouseY;
11297 synchronized(mMousePositionTracker) {
11298 if (!mMousePositionTracker.mLatestEventWasMouse) {
11301 mouseX = mMousePositionTracker.mLatestMouseX;
11302 mouseY = mMousePositionTracker.mLatestMouseY;
11305 synchronized (mWindowMap) {
11306 if (mDragState != null) {
11307 // Drag cursor overrides the app cursor.
11310 WindowState callingWin = windowForClientLocked(null, client, false);
11311 if (callingWin == null) {
11312 Slog.w(TAG_WM, "Bad requesting window " + client);
11315 final DisplayContent displayContent = callingWin.getDisplayContent();
11316 if (displayContent == null) {
11319 WindowState windowUnderPointer =
11320 displayContent.getTouchableWinAtPointLocked(mouseX, mouseY);
11321 if (windowUnderPointer != callingWin) {
11325 windowUnderPointer.mClient.updatePointerIcon(
11326 windowUnderPointer.translateToWindowX(mouseX),
11327 windowUnderPointer.translateToWindowY(mouseY));
11328 } catch (RemoteException e) {
11329 Slog.w(TAG_WM, "unable to update pointer icon");
11334 void restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY) {
11335 // Mouse position tracker has not been getting updates while dragging, update it now.
11336 mMousePositionTracker.updatePosition(latestX, latestY);
11338 WindowState windowUnderPointer =
11339 displayContent.getTouchableWinAtPointLocked(latestX, latestY);
11340 if (windowUnderPointer != null) {
11342 windowUnderPointer.mClient.updatePointerIcon(
11343 windowUnderPointer.translateToWindowX(latestX),
11344 windowUnderPointer.translateToWindowY(latestY));
11345 } catch (RemoteException e) {
11346 Slog.w(TAG_WM, "unable to restore pointer icon");
11349 InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_DEFAULT);
11354 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
11355 throws RemoteException {
11356 if (!checkCallingPermission(Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS,
11357 "registerShortcutKey")) {
11358 throw new SecurityException(
11359 "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission");
11361 mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver);
11364 private final class LocalService extends WindowManagerInternal {
11366 public void requestTraversalFromDisplayManager() {
11367 requestTraversal();
11371 public void setMagnificationSpec(MagnificationSpec spec) {
11372 synchronized (mWindowMap) {
11373 if (mAccessibilityController != null) {
11374 mAccessibilityController.setMagnificationSpecLocked(spec);
11376 throw new IllegalStateException("Magnification callbacks not set!");
11379 if (Binder.getCallingPid() != android.os.Process.myPid()) {
11385 public void getMagnificationRegion(@NonNull Region magnificationRegion) {
11386 synchronized (mWindowMap) {
11387 if (mAccessibilityController != null) {
11388 mAccessibilityController.getMagnificationRegionLocked(magnificationRegion);
11390 throw new IllegalStateException("Magnification callbacks not set!");
11396 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
11397 synchronized (mWindowMap) {
11398 WindowState windowState = mWindowMap.get(windowToken);
11399 if (windowState == null) {
11402 MagnificationSpec spec = null;
11403 if (mAccessibilityController != null) {
11404 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState);
11406 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
11409 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
11410 spec.scale *= windowState.mGlobalScale;
11416 public void setMagnificationCallbacks(@Nullable MagnificationCallbacks callbacks) {
11417 synchronized (mWindowMap) {
11418 if (mAccessibilityController == null) {
11419 mAccessibilityController = new AccessibilityController(
11420 WindowManagerService.this);
11422 mAccessibilityController.setMagnificationCallbacksLocked(callbacks);
11423 if (!mAccessibilityController.hasCallbacksLocked()) {
11424 mAccessibilityController = null;
11430 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) {
11431 synchronized (mWindowMap) {
11432 if (mAccessibilityController == null) {
11433 mAccessibilityController = new AccessibilityController(
11434 WindowManagerService.this);
11436 mAccessibilityController.setWindowsForAccessibilityCallback(callback);
11437 if (!mAccessibilityController.hasCallbacksLocked()) {
11438 mAccessibilityController = null;
11444 public void setInputFilter(IInputFilter filter) {
11445 mInputManager.setInputFilter(filter);
11449 public IBinder getFocusedWindowToken() {
11450 synchronized (mWindowMap) {
11451 WindowState windowState = getFocusedWindowLocked();
11452 if (windowState != null) {
11453 return windowState.mClient.asBinder();
11460 public boolean isKeyguardLocked() {
11461 return WindowManagerService.this.isKeyguardLocked();
11465 public void showGlobalActions() {
11466 WindowManagerService.this.showGlobalActions();
11470 public void getWindowFrame(IBinder token, Rect outBounds) {
11471 synchronized (mWindowMap) {
11472 WindowState windowState = mWindowMap.get(token);
11473 if (windowState != null) {
11474 outBounds.set(windowState.mFrame);
11476 outBounds.setEmpty();
11482 public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
11483 boolean allWindowsDrawn = false;
11484 synchronized (mWindowMap) {
11485 mWaitingForDrawnCallback = callback;
11486 final WindowList windows = getDefaultWindowListLocked();
11487 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
11488 final WindowState win = windows.get(winNdx);
11489 final boolean isForceHiding = mPolicy.isForceHiding(win.mAttrs);
11490 final boolean keyguard = mPolicy.isKeyguardHostWindow(win.mAttrs);
11491 if (win.isVisibleLw()
11492 && (win.mAppToken != null || isForceHiding || keyguard)) {
11493 win.mWinAnimator.mDrawState = DRAW_PENDING;
11494 // Force add to mResizingWindows.
11495 win.mLastContentInsets.set(-1, -1, -1, -1);
11496 mWaitingForDrawn.add(win);
11498 // No need to wait for the windows below Keyguard.
11499 if (isForceHiding) {
11504 mWindowPlacerLocked.requestTraversal();
11505 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
11506 if (mWaitingForDrawn.isEmpty()) {
11507 allWindowsDrawn = true;
11509 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
11510 checkDrawnWindowsLocked();
11513 if (allWindowsDrawn) {
11519 public void addWindowToken(IBinder token, int type) {
11520 WindowManagerService.this.addWindowToken(token, type);
11524 public void removeWindowToken(IBinder token, boolean removeWindows) {
11525 synchronized(mWindowMap) {
11526 if (removeWindows) {
11527 WindowToken wtoken = mTokenMap.remove(token);
11528 if (wtoken != null) {
11529 wtoken.removeAllWindows();
11532 WindowManagerService.this.removeWindowToken(token);
11537 public void registerAppTransitionListener(AppTransitionListener listener) {
11538 synchronized (mWindowMap) {
11539 mAppTransition.registerListenerLocked(listener);
11544 public int getInputMethodWindowVisibleHeight() {
11545 synchronized (mWindowMap) {
11546 return mPolicy.getInputMethodWindowVisibleHeightLw();
11551 public void saveLastInputMethodWindowForTransition() {
11552 synchronized (mWindowMap) {
11553 if (mInputMethodWindow != null) {
11554 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
11560 public void clearLastInputMethodWindowForTransition() {
11561 synchronized (mWindowMap) {
11562 mPolicy.setLastInputMethodWindowLw(null, null);
11567 public boolean isHardKeyboardAvailable() {
11568 synchronized (mWindowMap) {
11569 return mHardKeyboardAvailable;
11574 public void setOnHardKeyboardStatusChangeListener(
11575 OnHardKeyboardStatusChangeListener listener) {
11576 synchronized (mWindowMap) {
11577 mHardKeyboardStatusChangeListener = listener;
11582 public boolean isStackVisible(int stackId) {
11583 synchronized (mWindowMap) {
11584 return WindowManagerService.this.isStackVisibleLocked(stackId);
11589 public boolean isDockedDividerResizing() {
11590 synchronized (mWindowMap) {
11591 return getDefaultDisplayContentLocked().getDockedDividerController().isResizing();