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