Home | History | Annotate | Download | only in wm
      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 static android.Manifest.permission.MANAGE_APP_TOKENS;
     20 import static android.Manifest.permission.READ_FRAME_BUFFER;
     21 import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
     22 import static android.Manifest.permission.RESTRICTED_VR_ACCESS;
     23 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
     24 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
     25 import static android.app.StatusBarManager.DISABLE_MASK;
     26 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
     27 import static android.content.Intent.ACTION_USER_REMOVED;
     28 import static android.content.Intent.EXTRA_USER_HANDLE;
     29 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
     30 import static android.os.Process.ROOT_UID;
     31 import static android.os.Process.SHELL_UID;
     32 import static android.os.Process.SYSTEM_UID;
     33 import static android.os.Process.myPid;
     34 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
     35 import static android.os.UserHandle.USER_NULL;
     36 import static android.view.Display.DEFAULT_DISPLAY;
     37 import static android.view.Display.INVALID_DISPLAY;
     38 import static android.view.WindowManager.DOCKED_INVALID;
     39 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
     40 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
     41 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
     42 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
     43 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
     44 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
     45 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
     46 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
     47 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
     48 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
     49 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
     50 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
     51 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
     52 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
     53 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
     54 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
     55 import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
     56 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
     57 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
     58 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
     59 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
     60 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
     61 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
     62 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
     63 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
     64 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
     65 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
     66 import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
     67 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
     68 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
     69 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
     70 import static com.android.server.LockGuard.INDEX_WINDOW;
     71 import static com.android.server.LockGuard.installLock;
     72 import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
     73 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END;
     74 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
     75 import static com.android.server.wm.KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED;
     76 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
     77 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
     78 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
     79 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
     80 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
     81 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
     82 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
     83 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
     84 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
     85 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
     86 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
     87 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
     88 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
     89 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
     90 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
     91 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
     92 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
     93 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
     94 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
     95 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
     96 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
     97 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
     98 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
     99 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
    100 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
    101 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSACTIONS;
    102 import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
    103 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
    104 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
    105 
    106 import android.Manifest;
    107 import android.Manifest.permission;
    108 import android.animation.AnimationHandler;
    109 import android.animation.ValueAnimator;
    110 import android.annotation.IntDef;
    111 import android.annotation.NonNull;
    112 import android.annotation.Nullable;
    113 import android.app.ActivityManager;
    114 import android.app.ActivityManager.TaskSnapshot;
    115 import android.app.ActivityManagerInternal;
    116 import android.app.ActivityThread;
    117 import android.app.AppOpsManager;
    118 import android.app.IActivityManager;
    119 import android.content.BroadcastReceiver;
    120 import android.content.ContentResolver;
    121 import android.content.Context;
    122 import android.content.Intent;
    123 import android.content.IntentFilter;
    124 import android.content.pm.ApplicationInfo;
    125 import android.content.pm.PackageManager;
    126 import android.content.res.Configuration;
    127 import android.database.ContentObserver;
    128 import android.graphics.Bitmap;
    129 import android.graphics.GraphicBuffer;
    130 import android.graphics.Matrix;
    131 import android.graphics.PixelFormat;
    132 import android.graphics.Point;
    133 import android.graphics.Rect;
    134 import android.graphics.RectF;
    135 import android.graphics.Region;
    136 import android.hardware.configstore.V1_0.ISurfaceFlingerConfigs;
    137 import android.hardware.configstore.V1_0.OptionalBool;
    138 import android.hardware.display.DisplayManager;
    139 import android.hardware.display.DisplayManagerInternal;
    140 import android.hardware.input.InputManager;
    141 import android.net.Uri;
    142 import android.os.Binder;
    143 import android.os.Build;
    144 import android.os.Bundle;
    145 import android.os.Debug;
    146 import android.os.Handler;
    147 import android.os.IBinder;
    148 import android.os.IRemoteCallback;
    149 import android.os.Looper;
    150 import android.os.Message;
    151 import android.os.Parcel;
    152 import android.os.ParcelFileDescriptor;
    153 import android.os.PowerManager;
    154 import android.os.PowerManagerInternal;
    155 import android.os.PowerSaveState;
    156 import android.os.RemoteException;
    157 import android.os.ServiceManager;
    158 import android.os.StrictMode;
    159 import android.os.SystemClock;
    160 import android.os.SystemProperties;
    161 import android.os.SystemService;
    162 import android.os.Trace;
    163 import android.os.UserHandle;
    164 import android.os.WorkSource;
    165 import android.provider.Settings;
    166 import android.text.format.DateUtils;
    167 import android.util.ArraySet;
    168 import android.util.DisplayMetrics;
    169 import android.util.EventLog;
    170 import android.util.Log;
    171 import android.util.MergedConfiguration;
    172 import android.util.Pair;
    173 import android.util.Slog;
    174 import android.util.SparseArray;
    175 import android.util.SparseIntArray;
    176 import android.util.TimeUtils;
    177 import android.util.TypedValue;
    178 import android.view.AppTransitionAnimationSpec;
    179 import android.view.Display;
    180 import android.view.DisplayInfo;
    181 import android.view.Gravity;
    182 import android.view.IAppTransitionAnimationSpecsFuture;
    183 import android.view.IDockedStackListener;
    184 import android.view.IInputFilter;
    185 import android.view.IOnKeyguardExitResult;
    186 import android.view.IPinnedStackListener;
    187 import android.view.IRotationWatcher;
    188 import android.view.IWallpaperVisibilityListener;
    189 import android.view.IWindow;
    190 import android.view.IWindowId;
    191 import android.view.IWindowManager;
    192 import android.view.IWindowSession;
    193 import android.view.IWindowSessionCallback;
    194 import android.view.InputChannel;
    195 import android.view.InputDevice;
    196 import android.view.InputEvent;
    197 import android.view.InputEventReceiver;
    198 import android.view.KeyEvent;
    199 import android.view.MagnificationSpec;
    200 import android.view.MotionEvent;
    201 import android.view.PointerIcon;
    202 import android.view.Surface;
    203 import android.view.Surface.OutOfResourcesException;
    204 import android.view.SurfaceControl;
    205 import android.view.SurfaceSession;
    206 import android.view.View;
    207 import android.view.WindowContentFrameStats;
    208 import android.view.WindowManager;
    209 import android.view.WindowManager.LayoutParams;
    210 import android.view.WindowManagerGlobal;
    211 import android.view.WindowManagerInternal;
    212 import android.view.WindowManagerPolicy;
    213 import android.view.WindowManagerPolicy.PointerEventListener;
    214 import android.view.WindowManagerPolicy.ScreenOffListener;
    215 import android.view.animation.Animation;
    216 import android.view.inputmethod.InputMethodManagerInternal;
    217 
    218 import com.android.internal.R;
    219 import com.android.internal.app.IAssistScreenshotReceiver;
    220 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
    221 import com.android.internal.os.IResultReceiver;
    222 import com.android.internal.policy.IKeyguardDismissCallback;
    223 import com.android.internal.policy.IShortcutService;
    224 import com.android.internal.util.DumpUtils;
    225 import com.android.internal.util.FastPrintWriter;
    226 import com.android.internal.view.IInputContext;
    227 import com.android.internal.view.IInputMethodClient;
    228 import com.android.internal.view.IInputMethodManager;
    229 import com.android.internal.view.WindowManagerPolicyThread;
    230 import com.android.server.AnimationThread;
    231 import com.android.server.DisplayThread;
    232 import com.android.server.EventLogTags;
    233 import com.android.server.FgThread;
    234 import com.android.server.LocalServices;
    235 import com.android.server.UiThread;
    236 import com.android.server.Watchdog;
    237 import com.android.server.input.InputManagerService;
    238 import com.android.server.power.BatterySaverPolicy.ServiceType;
    239 import com.android.server.power.ShutdownThread;
    240 
    241 import java.io.BufferedWriter;
    242 import java.io.DataInputStream;
    243 import java.io.File;
    244 import java.io.FileDescriptor;
    245 import java.io.FileInputStream;
    246 import java.io.FileNotFoundException;
    247 import java.io.IOException;
    248 import java.io.OutputStream;
    249 import java.io.OutputStreamWriter;
    250 import java.io.PrintWriter;
    251 import java.io.StringWriter;
    252 import java.lang.annotation.Retention;
    253 import java.lang.annotation.RetentionPolicy;
    254 import java.net.Socket;
    255 import java.text.DateFormat;
    256 import java.util.ArrayList;
    257 import java.util.Date;
    258 import java.util.List;
    259 /** {@hide} */
    260 public class WindowManagerService extends IWindowManager.Stub
    261         implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    262     private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowManagerService" : TAG_WM;
    263 
    264     static final int LAYOUT_REPEAT_THRESHOLD = 4;
    265 
    266     static final boolean PROFILE_ORIENTATION = false;
    267     static final boolean localLOGV = DEBUG;
    268 
    269     /** How much to multiply the policy's type layer, to reserve room
    270      * for multiple windows of the same type and Z-ordering adjustment
    271      * with TYPE_LAYER_OFFSET. */
    272     static final int TYPE_LAYER_MULTIPLIER = 10000;
    273 
    274     /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
    275      * or below others in the same layer. */
    276     static final int TYPE_LAYER_OFFSET = 1000;
    277 
    278     /** How much to increment the layer for each window, to reserve room
    279      * for effect surfaces between them.
    280      */
    281     static final int WINDOW_LAYER_MULTIPLIER = 5;
    282 
    283     /**
    284      * Dim surface layer is immediately below target window.
    285      */
    286     static final int LAYER_OFFSET_DIM = 1;
    287 
    288     /**
    289      * Animation thumbnail is as far as possible below the window above
    290      * the thumbnail (or in other words as far as possible above the window
    291      * below it).
    292      */
    293     static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER - 1;
    294 
    295     /** The maximum length we will accept for a loaded animation duration:
    296      * this is 10 seconds.
    297      */
    298     static final int MAX_ANIMATION_DURATION = 10 * 1000;
    299 
    300     /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
    301     static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
    302 
    303     /** Amount of time (in milliseconds) to delay before declaring a seamless rotation timeout. */
    304     static final int SEAMLESS_ROTATION_TIMEOUT_DURATION = 2000;
    305 
    306     /** Amount of time (in milliseconds) to delay before declaring a window replacement timeout. */
    307     static final int WINDOW_REPLACEMENT_TIMEOUT_DURATION = 2000;
    308 
    309     /** Amount of time to allow a last ANR message to exist before freeing the memory. */
    310     static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours
    311     /**
    312      * If true, the window manager will do its own custom freezing and general
    313      * management of the screen during rotation.
    314      */
    315     static final boolean CUSTOM_SCREEN_ROTATION = true;
    316 
    317     // Maximum number of milliseconds to wait for input devices to be enumerated before
    318     // proceding with safe mode detection.
    319     private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
    320 
    321     // Default input dispatching timeout in nanoseconds.
    322     static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
    323 
    324     // Poll interval in milliseconds for watching boot animation finished.
    325     private static final int BOOT_ANIMATION_POLL_INTERVAL = 200;
    326 
    327     // The name of the boot animation service in init.rc.
    328     private static final String BOOT_ANIMATION_SERVICE = "bootanim";
    329 
    330     static final int UPDATE_FOCUS_NORMAL = 0;
    331     static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
    332     static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
    333     static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
    334 
    335     private static final String SYSTEM_SECURE = "ro.secure";
    336     private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
    337 
    338     private static final String DENSITY_OVERRIDE = "ro.config.density_override";
    339     private static final String SIZE_OVERRIDE = "ro.config.size_override";
    340 
    341     private static final int MAX_SCREENSHOT_RETRIES = 3;
    342 
    343     private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
    344 
    345     // Used to indicate that if there is already a transition set, it should be preserved when
    346     // trying to apply a new one.
    347     private static final boolean ALWAYS_KEEP_CURRENT = true;
    348 
    349     private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f;
    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     boolean mKeyguardGoingAway;
    361     // VR Vr2d Display Id.
    362     int mVr2dDisplayId = INVALID_DISPLAY;
    363 
    364     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
    365         @Override
    366         public void onReceive(Context context, Intent intent) {
    367             switch (intent.getAction()) {
    368                 case ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED:
    369                     mKeyguardDisableHandler.sendEmptyMessage(KEYGUARD_POLICY_CHANGED);
    370                     break;
    371                 case ACTION_USER_REMOVED:
    372                     final int userId = intent.getIntExtra(EXTRA_USER_HANDLE, USER_NULL);
    373                     if (userId != USER_NULL) {
    374                         synchronized (mWindowMap) {
    375                             mScreenCaptureDisabled.remove(userId);
    376                         }
    377                     }
    378                     break;
    379             }
    380         }
    381     };
    382     final WindowSurfacePlacer mWindowPlacerLocked;
    383 
    384     /**
    385      * Current user when multi-user is enabled. Don't show windows of
    386      * non-current user. Also see mCurrentProfileIds.
    387      */
    388     int mCurrentUserId;
    389     /**
    390      * Users that are profiles of the current user. These are also allowed to show windows
    391      * on the current user.
    392      */
    393     int[] mCurrentProfileIds = new int[] {};
    394 
    395     final Context mContext;
    396 
    397     final boolean mHaveInputMethods;
    398 
    399     final boolean mHasPermanentDpad;
    400     final long mDrawLockTimeoutMillis;
    401     final boolean mAllowAnimationsInLowPowerMode;
    402 
    403     final boolean mAllowBootMessages;
    404 
    405     final boolean mLimitedAlphaCompositing;
    406     final int mMaxUiWidth;
    407 
    408     final WindowManagerPolicy mPolicy;
    409 
    410     final IActivityManager mActivityManager;
    411     final ActivityManagerInternal mAmInternal;
    412 
    413     final AppOpsManager mAppOps;
    414 
    415     final DisplaySettings mDisplaySettings;
    416 
    417     /** If the system should display notifications for apps displaying an alert window. */
    418     boolean mShowAlertWindowNotifications = true;
    419 
    420     /**
    421      * All currently active sessions with clients.
    422      */
    423     final ArraySet<Session> mSessions = new ArraySet<>();
    424 
    425     /**
    426      * Mapping from an IWindow IBinder to the server's Window object.
    427      * This is also used as the lock for all of our state.
    428      * NOTE: Never call into methods that lock ActivityManagerService while holding this object.
    429      */
    430     final WindowHashMap mWindowMap = new WindowHashMap();
    431 
    432     /**
    433      * List of window tokens that have finished starting their application,
    434      * and now need to have the policy remove their windows.
    435      */
    436     final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<>();
    437 
    438     /**
    439      * List of window tokens that have finished drawing their own windows and
    440      * no longer need to show any saved surfaces. Windows that's still showing
    441      * saved surfaces will be cleaned up after next animation pass.
    442      */
    443     final ArrayList<AppWindowToken> mFinishedEarlyAnim = new ArrayList<>();
    444 
    445     /**
    446      * List of app window tokens that are waiting for replacing windows. If the
    447      * replacement doesn't come in time the stale windows needs to be disposed of.
    448      */
    449     final ArrayList<AppWindowToken> mWindowReplacementTimeouts = new ArrayList<>();
    450 
    451     /**
    452      * Windows that are being resized.  Used so we can tell the client about
    453      * the resize after closing the transaction in which we resized the
    454      * underlying surface.
    455      */
    456     final ArrayList<WindowState> mResizingWindows = new ArrayList<>();
    457 
    458     /**
    459      * Windows whose animations have ended and now must be removed.
    460      */
    461     final ArrayList<WindowState> mPendingRemove = new ArrayList<>();
    462 
    463     /**
    464      * Used when processing mPendingRemove to avoid working on the original array.
    465      */
    466     WindowState[] mPendingRemoveTmp = new WindowState[20];
    467 
    468     /**
    469      * Windows whose surface should be destroyed.
    470      */
    471     final ArrayList<WindowState> mDestroySurface = new ArrayList<>();
    472 
    473     /**
    474      * Windows with a preserved surface waiting to be destroyed. These windows
    475      * are going through a surface change. We keep the old surface around until
    476      * the first frame on the new surface finishes drawing.
    477      */
    478     final ArrayList<WindowState> mDestroyPreservedSurface = new ArrayList<>();
    479 
    480     /**
    481      * Windows that have lost input focus and are waiting for the new
    482      * focus window to be displayed before they are told about this.
    483      */
    484     ArrayList<WindowState> mLosingFocus = new ArrayList<>();
    485 
    486     /**
    487      * This is set when we have run out of memory, and will either be an empty
    488      * list or contain windows that need to be force removed.
    489      */
    490     final ArrayList<WindowState> mForceRemoves = new ArrayList<>();
    491 
    492     /**
    493      * Windows that clients are waiting to have drawn.
    494      */
    495     ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>();
    496     /**
    497      * And the callback to make when they've all been drawn.
    498      */
    499     Runnable mWaitingForDrawnCallback;
    500 
    501     /** List of window currently causing non-system overlay windows to be hidden. */
    502     private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>();
    503 
    504     /**
    505      * Stores for each user whether screencapture is disabled
    506      * This array is essentially a cache for all userId for
    507      * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled}
    508      */
    509     private SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>();
    510 
    511     IInputMethodManager mInputMethodManager;
    512 
    513     AccessibilityController mAccessibilityController;
    514 
    515     final SurfaceSession mFxSession;
    516     Watermark mWatermark;
    517     StrictModeFlash mStrictModeFlash;
    518     CircularDisplayMask mCircularDisplayMask;
    519     EmulatorDisplayOverlay mEmulatorDisplayOverlay;
    520 
    521     final float[] mTmpFloats = new float[9];
    522     final Rect mTmpRect = new Rect();
    523     final Rect mTmpRect2 = new Rect();
    524     final Rect mTmpRect3 = new Rect();
    525     final RectF mTmpRectF = new RectF();
    526 
    527     final Matrix mTmpTransform = new Matrix();
    528 
    529     boolean mDisplayReady;
    530     boolean mSafeMode;
    531     boolean mDisplayEnabled = false;
    532     boolean mSystemBooted = false;
    533     boolean mForceDisplayEnabled = false;
    534     boolean mShowingBootMessages = false;
    535     boolean mBootAnimationStopped = false;
    536 
    537     // Following variables are for debugging screen wakelock only.
    538     WindowState mLastWakeLockHoldingWindow = null;
    539     WindowState mLastWakeLockObscuringWindow = null;
    540 
    541     /** Dump of the windows and app tokens at the time of the last ANR. Cleared after
    542      * LAST_ANR_LIFETIME_DURATION_MSECS */
    543     String mLastANRState;
    544 
    545     // The root of the device window hierarchy.
    546     RootWindowContainer mRoot;
    547 
    548     int mDockedStackCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
    549     Rect mDockedStackCreateBounds;
    550 
    551     private final SparseIntArray mTmpTaskIds = new SparseIntArray();
    552 
    553     boolean mForceResizableTasks = false;
    554     boolean mSupportsPictureInPicture = false;
    555 
    556     int getDragLayerLocked() {
    557         return mPolicy.getWindowLayerFromTypeLw(TYPE_DRAG) * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
    558     }
    559 
    560     class RotationWatcher {
    561         final IRotationWatcher mWatcher;
    562         final IBinder.DeathRecipient mDeathRecipient;
    563         final int mDisplayId;
    564         RotationWatcher(IRotationWatcher watcher, IBinder.DeathRecipient deathRecipient,
    565                 int displayId) {
    566             mWatcher = watcher;
    567             mDeathRecipient = deathRecipient;
    568             mDisplayId = displayId;
    569         }
    570     }
    571 
    572     ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<>();
    573     int mDeferredRotationPauseCount;
    574     final WallpaperVisibilityListeners mWallpaperVisibilityListeners =
    575             new WallpaperVisibilityListeners();
    576 
    577     int mSystemDecorLayer = 0;
    578     final Rect mScreenRect = new Rect();
    579 
    580     boolean mDisplayFrozen = false;
    581     long mDisplayFreezeTime = 0;
    582     int mLastDisplayFreezeDuration = 0;
    583     Object mLastFinishedFreezeSource = null;
    584     boolean mWaitingForConfig = false;
    585     boolean mSwitchingUser = false;
    586 
    587     final static int WINDOWS_FREEZING_SCREENS_NONE = 0;
    588     final static int WINDOWS_FREEZING_SCREENS_ACTIVE = 1;
    589     final static int WINDOWS_FREEZING_SCREENS_TIMEOUT = 2;
    590     int mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
    591 
    592     boolean mClientFreezingScreen = false;
    593     int mAppsFreezingScreen = 0;
    594 
    595     int mLayoutSeq = 0;
    596 
    597     // Last systemUiVisibility we received from status bar.
    598     int mLastStatusBarVisibility = 0;
    599     // Last systemUiVisibility we dispatched to windows.
    600     int mLastDispatchedSystemUiVisibility = 0;
    601 
    602     // State while inside of layoutAndPlaceSurfacesLocked().
    603     boolean mFocusMayChange;
    604 
    605     // This is held as long as we have the screen frozen, to give us time to
    606     // perform a rotation animation when turning off shows the lock screen which
    607     // changes the orientation.
    608     private final PowerManager.WakeLock mScreenFrozenLock;
    609 
    610     final AppTransition mAppTransition;
    611     boolean mSkipAppTransitionAnimation = false;
    612 
    613     final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<>();
    614     final ArraySet<AppWindowToken> mClosingApps = new ArraySet<>();
    615 
    616     final UnknownAppVisibilityController mUnknownAppVisibilityController =
    617             new UnknownAppVisibilityController(this);
    618     final TaskSnapshotController mTaskSnapshotController;
    619 
    620     boolean mIsTouchDevice;
    621 
    622     final H mH = new H();
    623 
    624     /**
    625      * Handler for things to run that have direct impact on an animation, i.e. animation tick,
    626      * layout, starting window creation, whereas {@link H} runs things that are still important, but
    627      * not as critical.
    628      */
    629     final Handler mAnimationHandler = new Handler(AnimationThread.getHandler().getLooper());
    630 
    631     WindowState mCurrentFocus = null;
    632     WindowState mLastFocus = null;
    633 
    634     /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
    635     private final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>();
    636     /** Windows removed since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
    637     private final ArrayList<WindowState> mWinRemovedSinceNullFocus = new ArrayList<>();
    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 
    648     boolean mHardKeyboardAvailable;
    649     WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
    650     SettingsObserver mSettingsObserver;
    651 
    652     // A count of the windows which are 'seamlessly rotated', e.g. a surface
    653     // at an old orientation is being transformed. We freeze orientation updates
    654     // while any windows are seamlessly rotated, so we need to track when this
    655     // hits zero so we can apply deferred orientation updates.
    656     int mSeamlessRotationCount = 0;
    657 
    658     private final class SettingsObserver extends ContentObserver {
    659         private final Uri mDisplayInversionEnabledUri =
    660                 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
    661         private final Uri mWindowAnimationScaleUri =
    662                 Settings.Global.getUriFor(Settings.Global.WINDOW_ANIMATION_SCALE);
    663         private final Uri mTransitionAnimationScaleUri =
    664                 Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE);
    665         private final Uri mAnimationDurationScaleUri =
    666                 Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE);
    667 
    668         public SettingsObserver() {
    669             super(new Handler());
    670             ContentResolver resolver = mContext.getContentResolver();
    671             resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this,
    672                     UserHandle.USER_ALL);
    673             resolver.registerContentObserver(mWindowAnimationScaleUri, false, this,
    674                     UserHandle.USER_ALL);
    675             resolver.registerContentObserver(mTransitionAnimationScaleUri, false, this,
    676                     UserHandle.USER_ALL);
    677             resolver.registerContentObserver(mAnimationDurationScaleUri, false, this,
    678                     UserHandle.USER_ALL);
    679         }
    680 
    681         @Override
    682         public void onChange(boolean selfChange, Uri uri) {
    683             if (uri == null) {
    684                 return;
    685             }
    686 
    687             if (mDisplayInversionEnabledUri.equals(uri)) {
    688                 updateCircularDisplayMaskIfNeeded();
    689             } else {
    690                 @UpdateAnimationScaleMode
    691                 final int mode;
    692                 if (mWindowAnimationScaleUri.equals(uri)) {
    693                     mode = WINDOW_ANIMATION_SCALE;
    694                 } else if (mTransitionAnimationScaleUri.equals(uri)) {
    695                     mode = TRANSITION_ANIMATION_SCALE;
    696                 } else if (mAnimationDurationScaleUri.equals(uri)) {
    697                     mode = ANIMATION_DURATION_SCALE;
    698                 } else {
    699                     // Ignoring unrecognized content changes
    700                     return;
    701                 }
    702                 Message m = mH.obtainMessage(H.UPDATE_ANIMATION_SCALE, mode, 0);
    703                 mH.sendMessage(m);
    704             }
    705         }
    706     }
    707 
    708     boolean mAnimateWallpaperWithTarget;
    709 
    710     // TODO: Move to RootWindowContainer
    711     AppWindowToken mFocusedApp = null;
    712 
    713     PowerManager mPowerManager;
    714     PowerManagerInternal mPowerManagerInternal;
    715 
    716     private float mWindowAnimationScaleSetting = 1.0f;
    717     private float mTransitionAnimationScaleSetting = 1.0f;
    718     private float mAnimatorDurationScaleSetting = 1.0f;
    719     private boolean mAnimationsDisabled = false;
    720 
    721     final InputManagerService mInputManager;
    722     final DisplayManagerInternal mDisplayManagerInternal;
    723     final DisplayManager mDisplayManager;
    724     private final Display[] mDisplays;
    725 
    726     // Indicates whether this device supports wide color gamut rendering
    727     private boolean mHasWideColorGamutSupport;
    728 
    729     // Who is holding the screen on.
    730     private Session mHoldingScreenOn;
    731     private PowerManager.WakeLock mHoldingScreenWakeLock;
    732 
    733     boolean mTurnOnScreen;
    734 
    735     // Whether or not a layout can cause a wake up when theater mode is enabled.
    736     boolean mAllowTheaterModeWakeFromLayout;
    737 
    738     TaskPositioner mTaskPositioner;
    739     DragState mDragState = null;
    740 
    741     // For frozen screen animations.
    742     private int mExitAnimId, mEnterAnimId;
    743 
    744     // The display that the rotation animation is applying to.
    745     private int mFrozenDisplayId;
    746 
    747     /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
    748      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
    749     int mTransactionSequence;
    750 
    751     final WindowAnimator mAnimator;
    752 
    753     final BoundsAnimationController mBoundsAnimationController;
    754 
    755     private final PointerEventDispatcher mPointerEventDispatcher;
    756 
    757     private WindowContentFrameStats mTempWindowRenderStats;
    758 
    759     final class DragInputEventReceiver extends InputEventReceiver {
    760         // Set, if stylus button was down at the start of the drag.
    761         private boolean mStylusButtonDownAtStart;
    762         // Indicates the first event to check for button state.
    763         private boolean mIsStartEvent = true;
    764         // Set to true to ignore input events after the drag gesture is complete but the drag events
    765         // are still being dispatched.
    766         private boolean mMuteInput = false;
    767 
    768         public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
    769             super(inputChannel, looper);
    770         }
    771 
    772         @Override
    773         public void onInputEvent(InputEvent event, int displayId) {
    774             boolean handled = false;
    775             try {
    776                 if (mDragState == null) {
    777                     // The drag has ended but the clean-up message has not been processed by
    778                     // window manager. Drop events that occur after this until window manager
    779                     // has a chance to clean-up the input handle.
    780                     handled = true;
    781                     return;
    782                 }
    783                 if (event instanceof MotionEvent
    784                         && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0
    785                         && !mMuteInput) {
    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                             mMuteInput = true;
    814                             synchronized (mWindowMap) {
    815                                 endDrag = mDragState.notifyDropLw(newX, newY);
    816                             }
    817                         } else {
    818                             synchronized (mWindowMap) {
    819                                 // move the surface and tell the involved window(s) where we are
    820                                 mDragState.notifyMoveLw(newX, newY);
    821                             }
    822                         }
    823                     } break;
    824 
    825                     case MotionEvent.ACTION_UP: {
    826                         if (DEBUG_DRAG) Slog.d(TAG_WM, "Got UP on move channel; dropping at "
    827                                 + newX + "," + newY);
    828                         mMuteInput = true;
    829                         synchronized (mWindowMap) {
    830                             endDrag = mDragState.notifyDropLw(newX, newY);
    831                         }
    832                     } break;
    833 
    834                     case MotionEvent.ACTION_CANCEL: {
    835                         if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag cancelled!");
    836                         mMuteInput = true;
    837                         endDrag = true;
    838                     } break;
    839                     }
    840 
    841                     if (endDrag) {
    842                         if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ended; tearing down state");
    843                         // tell all the windows that the drag has ended
    844                         synchronized (mWindowMap) {
    845                             // endDragLw will post back to looper to dispose the receiver
    846                             // since we still need the receiver for the last finishInputEvent.
    847                             mDragState.endDragLw();
    848                         }
    849                         mStylusButtonDownAtStart = false;
    850                         mIsStartEvent = true;
    851                     }
    852 
    853                     handled = true;
    854                 }
    855             } catch (Exception e) {
    856                 Slog.e(TAG_WM, "Exception caught by drag handleMotion", e);
    857             } finally {
    858                 finishInputEvent(event, handled);
    859             }
    860         }
    861     }
    862 
    863     /**
    864      * Whether the UI is currently running in touch mode (not showing
    865      * navigational focus because the user is directly pressing the screen).
    866      */
    867     boolean mInTouchMode;
    868 
    869     private ViewServer mViewServer;
    870     final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
    871     boolean mWindowsChanged = false;
    872 
    873     public interface WindowChangeListener {
    874         public void windowsChanged();
    875         public void focusChanged();
    876     }
    877 
    878     final Configuration mTempConfiguration = new Configuration();
    879 
    880     // If true, only the core apps and services are being launched because the device
    881     // is in a special boot mode, such as being encrypted or waiting for a decryption password.
    882     // For example, when this flag is true, there will be no wallpaper service.
    883     final boolean mOnlyCore;
    884 
    885     // List of clients without a transtiton animation that we notify once we are done transitioning
    886     // since they won't be notified through the app window animator.
    887     final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
    888 
    889     static WindowManagerThreadPriorityBooster sThreadPriorityBooster =
    890             new WindowManagerThreadPriorityBooster();
    891 
    892     static void boostPriorityForLockedSection() {
    893         sThreadPriorityBooster.boost();
    894     }
    895 
    896     static void resetPriorityAfterLockedSection() {
    897         sThreadPriorityBooster.reset();
    898     }
    899 
    900     void openSurfaceTransaction() {
    901         try {
    902             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "openSurfaceTransaction");
    903             synchronized (mWindowMap) {
    904                 if (mRoot.mSurfaceTraceEnabled) {
    905                     mRoot.mRemoteEventTrace.openSurfaceTransaction();
    906                 }
    907                 SurfaceControl.openTransaction();
    908             }
    909         } finally {
    910             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
    911         }
    912     }
    913 
    914     /**
    915      * Closes a surface transaction.
    916      */
    917     void closeSurfaceTransaction() {
    918         try {
    919             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction");
    920             synchronized (mWindowMap) {
    921                 if (mRoot.mSurfaceTraceEnabled) {
    922                     mRoot.mRemoteEventTrace.closeSurfaceTransaction();
    923                 }
    924                 SurfaceControl.closeTransaction();
    925             }
    926         } finally {
    927             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
    928         }
    929     }
    930 
    931     /**
    932      * Executes an empty animation transaction without holding the WM lock to simulate
    933      * back-pressure. See {@link WindowAnimator#animate} why this is needed.
    934      */
    935     void executeEmptyAnimationTransaction() {
    936         try {
    937             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "openSurfaceTransaction");
    938             synchronized (mWindowMap) {
    939                 if (mRoot.mSurfaceTraceEnabled) {
    940                     mRoot.mRemoteEventTrace.openSurfaceTransaction();
    941                 }
    942                 SurfaceControl.openTransaction();
    943                 SurfaceControl.setAnimationTransaction();
    944                 if (mRoot.mSurfaceTraceEnabled) {
    945                     mRoot.mRemoteEventTrace.closeSurfaceTransaction();
    946                 }
    947             }
    948         } finally {
    949             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
    950         }
    951         try {
    952             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction");
    953             SurfaceControl.closeTransaction();
    954         } finally {
    955             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
    956         }
    957     }
    958 
    959     /** Listener to notify activity manager about app transitions. */
    960     final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier
    961             = new WindowManagerInternal.AppTransitionListener() {
    962 
    963         @Override
    964         public void onAppTransitionCancelledLocked(int transit) {
    965             mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_CANCELLED);
    966         }
    967 
    968         @Override
    969         public void onAppTransitionFinishedLocked(IBinder token) {
    970             mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_FINISHED);
    971             final AppWindowToken atoken = mRoot.getAppWindowToken(token);
    972             if (atoken == null) {
    973                 return;
    974             }
    975             if (atoken.mLaunchTaskBehind) {
    976                 try {
    977                     mActivityManager.notifyLaunchTaskBehindComplete(atoken.token);
    978                 } catch (RemoteException e) {
    979                 }
    980                 atoken.mLaunchTaskBehind = false;
    981             } else {
    982                 atoken.updateReportedVisibilityLocked();
    983                 if (atoken.mEnteringAnimation) {
    984                     atoken.mEnteringAnimation = false;
    985                     try {
    986                         mActivityManager.notifyEnterAnimationComplete(atoken.token);
    987                     } catch (RemoteException e) {
    988                     }
    989                 }
    990             }
    991         }
    992     };
    993 
    994     final ArrayList<AppFreezeListener> mAppFreezeListeners = new ArrayList<>();
    995 
    996     interface AppFreezeListener {
    997         void onAppFreezeTimeout();
    998     }
    999 
   1000     private static WindowManagerService sInstance;
   1001     static WindowManagerService getInstance() {
   1002         return sInstance;
   1003     }
   1004 
   1005     public static WindowManagerService main(final Context context, final InputManagerService im,
   1006             final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
   1007             WindowManagerPolicy policy) {
   1008         DisplayThread.getHandler().runWithScissors(() ->
   1009                 sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
   1010                         onlyCore, policy), 0);
   1011         return sInstance;
   1012     }
   1013 
   1014     private void initPolicy() {
   1015         UiThread.getHandler().runWithScissors(new Runnable() {
   1016             @Override
   1017             public void run() {
   1018                 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
   1019 
   1020                 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
   1021             }
   1022         }, 0);
   1023     }
   1024 
   1025     private WindowManagerService(Context context, InputManagerService inputManager,
   1026             boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
   1027             WindowManagerPolicy policy) {
   1028         installLock(this, INDEX_WINDOW);
   1029         mRoot = new RootWindowContainer(this);
   1030         mContext = context;
   1031         mHaveInputMethods = haveInputMethods;
   1032         mAllowBootMessages = showBootMsgs;
   1033         mOnlyCore = onlyCore;
   1034         mLimitedAlphaCompositing = context.getResources().getBoolean(
   1035                 com.android.internal.R.bool.config_sf_limitedAlpha);
   1036         mHasPermanentDpad = context.getResources().getBoolean(
   1037                 com.android.internal.R.bool.config_hasPermanentDpad);
   1038         mInTouchMode = context.getResources().getBoolean(
   1039                 com.android.internal.R.bool.config_defaultInTouchMode);
   1040         mDrawLockTimeoutMillis = context.getResources().getInteger(
   1041                 com.android.internal.R.integer.config_drawLockTimeoutMillis);
   1042         mAllowAnimationsInLowPowerMode = context.getResources().getBoolean(
   1043                 com.android.internal.R.bool.config_allowAnimationsInLowPowerMode);
   1044         mMaxUiWidth = context.getResources().getInteger(
   1045                 com.android.internal.R.integer.config_maxUiWidth);
   1046         mInputManager = inputManager; // Must be before createDisplayContentLocked.
   1047         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
   1048         mDisplaySettings = new DisplaySettings();
   1049         mDisplaySettings.readSettingsLocked();
   1050 
   1051         mWindowPlacerLocked = new WindowSurfacePlacer(this);
   1052         mPolicy = policy;
   1053         mTaskSnapshotController = new TaskSnapshotController(this);
   1054 
   1055         LocalServices.addService(WindowManagerPolicy.class, mPolicy);
   1056 
   1057         if(mInputManager != null) {
   1058             final InputChannel inputChannel = mInputManager.monitorInput(TAG_WM);
   1059             mPointerEventDispatcher = inputChannel != null
   1060                     ? new PointerEventDispatcher(inputChannel) : null;
   1061         } else {
   1062             mPointerEventDispatcher = null;
   1063         }
   1064 
   1065         mFxSession = new SurfaceSession();
   1066         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
   1067         mDisplays = mDisplayManager.getDisplays();
   1068         for (Display display : mDisplays) {
   1069             createDisplayContentLocked(display);
   1070         }
   1071 
   1072         mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
   1073 
   1074         mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
   1075         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
   1076 
   1077         if (mPowerManagerInternal != null) {
   1078             mPowerManagerInternal.registerLowPowerModeObserver(
   1079                     new PowerManagerInternal.LowPowerModeListener() {
   1080                 @Override
   1081                 public int getServiceType() {
   1082                     return ServiceType.ANIMATION;
   1083                 }
   1084 
   1085                 @Override
   1086                 public void onLowPowerModeChanged(PowerSaveState result) {
   1087                     synchronized (mWindowMap) {
   1088                         final boolean enabled = result.batterySaverEnabled;
   1089                         if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
   1090                             mAnimationsDisabled = enabled;
   1091                             dispatchNewAnimatorScaleLocked(null);
   1092                         }
   1093                     }
   1094                 }
   1095             });
   1096             mAnimationsDisabled = mPowerManagerInternal
   1097                     .getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled;
   1098         }
   1099         mScreenFrozenLock = mPowerManager.newWakeLock(
   1100                 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
   1101         mScreenFrozenLock.setReferenceCounted(false);
   1102 
   1103         mAppTransition = new AppTransition(context, this);
   1104         mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier);
   1105 
   1106         final AnimationHandler animationHandler = new AnimationHandler();
   1107         animationHandler.setProvider(new SfVsyncFrameCallbackProvider());
   1108         mBoundsAnimationController = new BoundsAnimationController(context, mAppTransition,
   1109                 AnimationThread.getHandler(), animationHandler);
   1110 
   1111         mActivityManager = ActivityManager.getService();
   1112         mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
   1113         mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
   1114         AppOpsManager.OnOpChangedInternalListener opListener =
   1115                 new AppOpsManager.OnOpChangedInternalListener() {
   1116                     @Override public void onOpChanged(int op, String packageName) {
   1117                         updateAppOpsState();
   1118                     }
   1119                 };
   1120         mAppOps.startWatchingMode(OP_SYSTEM_ALERT_WINDOW, null, opListener);
   1121         mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener);
   1122 
   1123         // Get persisted window scale setting
   1124         mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
   1125                 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
   1126         mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
   1127                 Settings.Global.TRANSITION_ANIMATION_SCALE,
   1128                 context.getResources().getFloat(
   1129                         R.dimen.config_appTransitionAnimationDurationScaleDefault));
   1130 
   1131         setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
   1132                 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
   1133 
   1134         IntentFilter filter = new IntentFilter();
   1135         // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
   1136         filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
   1137         // Listen to user removal broadcasts so that we can remove the user-specific data.
   1138         filter.addAction(Intent.ACTION_USER_REMOVED);
   1139         mContext.registerReceiver(mBroadcastReceiver, filter);
   1140 
   1141         mSettingsObserver = new SettingsObserver();
   1142 
   1143         mHoldingScreenWakeLock = mPowerManager.newWakeLock(
   1144                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
   1145         mHoldingScreenWakeLock.setReferenceCounted(false);
   1146 
   1147         mAnimator = new WindowAnimator(this);
   1148 
   1149         mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
   1150                 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
   1151 
   1152 
   1153         LocalServices.addService(WindowManagerInternal.class, new LocalService());
   1154         initPolicy();
   1155 
   1156         // Add ourself to the Watchdog monitors.
   1157         Watchdog.getInstance().addMonitor(this);
   1158 
   1159         openSurfaceTransaction();
   1160         try {
   1161             createWatermarkInTransaction();
   1162         } finally {
   1163             closeSurfaceTransaction();
   1164         }
   1165 
   1166         showEmulatorDisplayOverlayIfNeeded();
   1167     }
   1168 
   1169     public InputMonitor getInputMonitor() {
   1170         return mInputMonitor;
   1171     }
   1172 
   1173     @Override
   1174     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
   1175             throws RemoteException {
   1176         try {
   1177             return super.onTransact(code, data, reply, flags);
   1178         } catch (RuntimeException e) {
   1179             // The window manager only throws security exceptions, so let's
   1180             // log all others.
   1181             if (!(e instanceof SecurityException)) {
   1182                 Slog.wtf(TAG_WM, "Window Manager Crash", e);
   1183             }
   1184             throw e;
   1185         }
   1186     }
   1187 
   1188     static boolean excludeWindowTypeFromTapOutTask(int windowType) {
   1189         switch (windowType) {
   1190             case TYPE_STATUS_BAR:
   1191             case TYPE_NAVIGATION_BAR:
   1192             case TYPE_INPUT_METHOD_DIALOG:
   1193                 return true;
   1194         }
   1195         return false;
   1196     }
   1197 
   1198     public int addWindow(Session session, IWindow client, int seq,
   1199             WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
   1200             Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
   1201             InputChannel outInputChannel) {
   1202         int[] appOp = new int[1];
   1203         int res = mPolicy.checkAddPermission(attrs, appOp);
   1204         if (res != WindowManagerGlobal.ADD_OKAY) {
   1205             return res;
   1206         }
   1207 
   1208         boolean reportNewConfig = false;
   1209         WindowState parentWindow = null;
   1210         long origId;
   1211         final int callingUid = Binder.getCallingUid();
   1212         final int type = attrs.type;
   1213 
   1214         synchronized(mWindowMap) {
   1215             if (!mDisplayReady) {
   1216                 throw new IllegalStateException("Display has not been initialialized");
   1217             }
   1218 
   1219             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
   1220             if (displayContent == null) {
   1221                 Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "
   1222                         + displayId + ".  Aborting.");
   1223                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
   1224             }
   1225             if (!displayContent.hasAccess(session.mUid)
   1226                     && !mDisplayManagerInternal.isUidPresentOnDisplay(session.mUid, displayId)) {
   1227                 Slog.w(TAG_WM, "Attempted to add window to a display for which the application "
   1228                         + "does not have access: " + displayId + ".  Aborting.");
   1229                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
   1230             }
   1231 
   1232             if (mWindowMap.containsKey(client.asBinder())) {
   1233                 Slog.w(TAG_WM, "Window " + client + " is already added");
   1234                 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
   1235             }
   1236 
   1237             if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
   1238                 parentWindow = windowForClientLocked(null, attrs.token, false);
   1239                 if (parentWindow == null) {
   1240                     Slog.w(TAG_WM, "Attempted to add window with token that is not a window: "
   1241                           + attrs.token + ".  Aborting.");
   1242                     return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
   1243                 }
   1244                 if (parentWindow.mAttrs.type >= FIRST_SUB_WINDOW
   1245                         && parentWindow.mAttrs.type <= LAST_SUB_WINDOW) {
   1246                     Slog.w(TAG_WM, "Attempted to add window with token that is a sub-window: "
   1247                             + attrs.token + ".  Aborting.");
   1248                     return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
   1249                 }
   1250             }
   1251 
   1252             if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
   1253                 Slog.w(TAG_WM, "Attempted to add private presentation window to a non-private display.  Aborting.");
   1254                 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
   1255             }
   1256 
   1257             AppWindowToken atoken = null;
   1258             final boolean hasParent = parentWindow != null;
   1259             // Use existing parent window token for child windows since they go in the same token
   1260             // as there parent window so we can apply the same policy on them.
   1261             WindowToken token = displayContent.getWindowToken(
   1262                     hasParent ? parentWindow.mAttrs.token : attrs.token);
   1263             // If this is a child window, we want to apply the same type checking rules as the
   1264             // parent window type.
   1265             final int rootType = hasParent ? parentWindow.mAttrs.type : type;
   1266 
   1267             boolean addToastWindowRequiresToken = false;
   1268 
   1269             if (token == null) {
   1270                 if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
   1271                     Slog.w(TAG_WM, "Attempted to add application window with unknown token "
   1272                           + attrs.token + ".  Aborting.");
   1273                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   1274                 }
   1275                 if (rootType == TYPE_INPUT_METHOD) {
   1276                     Slog.w(TAG_WM, "Attempted to add input method window with unknown token "
   1277                           + attrs.token + ".  Aborting.");
   1278                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   1279                 }
   1280                 if (rootType == TYPE_VOICE_INTERACTION) {
   1281                     Slog.w(TAG_WM, "Attempted to add voice interaction window with unknown token "
   1282                           + attrs.token + ".  Aborting.");
   1283                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   1284                 }
   1285                 if (rootType == TYPE_WALLPAPER) {
   1286                     Slog.w(TAG_WM, "Attempted to add wallpaper window with unknown token "
   1287                           + attrs.token + ".  Aborting.");
   1288                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   1289                 }
   1290                 if (rootType == TYPE_DREAM) {
   1291                     Slog.w(TAG_WM, "Attempted to add Dream window with unknown token "
   1292                           + attrs.token + ".  Aborting.");
   1293                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   1294                 }
   1295                 if (rootType == TYPE_QS_DIALOG) {
   1296                     Slog.w(TAG_WM, "Attempted to add QS dialog window with unknown token "
   1297                           + attrs.token + ".  Aborting.");
   1298                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   1299                 }
   1300                 if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
   1301                     Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with unknown token "
   1302                             + attrs.token + ".  Aborting.");
   1303                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   1304                 }
   1305                 if (type == TYPE_TOAST) {
   1306                     // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
   1307                     if (doesAddToastWindowRequireToken(attrs.packageName, callingUid,
   1308                             parentWindow)) {
   1309                         Slog.w(TAG_WM, "Attempted to add a toast window with unknown token "
   1310                                 + attrs.token + ".  Aborting.");
   1311                         return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   1312                     }
   1313                 }
   1314                 final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();
   1315                 token = new WindowToken(this, binder, type, false, displayContent,
   1316                         session.mCanAddInternalSystemWindow);
   1317             } else if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
   1318                 atoken = token.asAppWindowToken();
   1319                 if (atoken == null) {
   1320                     Slog.w(TAG_WM, "Attempted to add window with non-application token "
   1321                           + token + ".  Aborting.");
   1322                     return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
   1323                 } else if (atoken.removed) {
   1324                     Slog.w(TAG_WM, "Attempted to add window with exiting application token "
   1325                           + token + ".  Aborting.");
   1326                     return WindowManagerGlobal.ADD_APP_EXITING;
   1327                 }
   1328             } else if (rootType == TYPE_INPUT_METHOD) {
   1329                 if (token.windowType != TYPE_INPUT_METHOD) {
   1330                     Slog.w(TAG_WM, "Attempted to add input method window with bad token "
   1331                             + attrs.token + ".  Aborting.");
   1332                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   1333                 }
   1334             } else if (rootType == TYPE_VOICE_INTERACTION) {
   1335                 if (token.windowType != TYPE_VOICE_INTERACTION) {
   1336                     Slog.w(TAG_WM, "Attempted to add voice interaction window with bad token "
   1337                             + attrs.token + ".  Aborting.");
   1338                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   1339                 }
   1340             } else if (rootType == TYPE_WALLPAPER) {
   1341                 if (token.windowType != TYPE_WALLPAPER) {
   1342                     Slog.w(TAG_WM, "Attempted to add wallpaper window with bad token "
   1343                             + attrs.token + ".  Aborting.");
   1344                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   1345                 }
   1346             } else if (rootType == TYPE_DREAM) {
   1347                 if (token.windowType != TYPE_DREAM) {
   1348                     Slog.w(TAG_WM, "Attempted to add Dream window with bad token "
   1349                             + attrs.token + ".  Aborting.");
   1350                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   1351                 }
   1352             } else if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
   1353                 if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
   1354                     Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with bad token "
   1355                             + attrs.token + ".  Aborting.");
   1356                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   1357                 }
   1358             } else if (type == TYPE_TOAST) {
   1359                 // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
   1360                 addToastWindowRequiresToken = doesAddToastWindowRequireToken(attrs.packageName,
   1361                         callingUid, parentWindow);
   1362                 if (addToastWindowRequiresToken && token.windowType != TYPE_TOAST) {
   1363                     Slog.w(TAG_WM, "Attempted to add a toast window with bad token "
   1364                             + attrs.token + ".  Aborting.");
   1365                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   1366                 }
   1367             } else if (type == TYPE_QS_DIALOG) {
   1368                 if (token.windowType != TYPE_QS_DIALOG) {
   1369                     Slog.w(TAG_WM, "Attempted to add QS dialog window with bad token "
   1370                             + attrs.token + ".  Aborting.");
   1371                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
   1372                 }
   1373             } else if (token.asAppWindowToken() != null) {
   1374                 Slog.w(TAG_WM, "Non-null appWindowToken for system window of rootType=" + rootType);
   1375                 // It is not valid to use an app token with other system types; we will
   1376                 // instead make a new token for it (as if null had been passed in for the token).
   1377                 attrs.token = null;
   1378                 token = new WindowToken(this, client.asBinder(), type, false, displayContent,
   1379                         session.mCanAddInternalSystemWindow);
   1380             }
   1381 
   1382             final WindowState win = new WindowState(this, session, client, token, parentWindow,
   1383                     appOp[0], seq, attrs, viewVisibility, session.mUid,
   1384                     session.mCanAddInternalSystemWindow);
   1385             if (win.mDeathRecipient == null) {
   1386                 // Client has apparently died, so there is no reason to
   1387                 // continue.
   1388                 Slog.w(TAG_WM, "Adding window client " + client.asBinder()
   1389                         + " that is dead, aborting.");
   1390                 return WindowManagerGlobal.ADD_APP_EXITING;
   1391             }
   1392 
   1393             if (win.getDisplayContent() == null) {
   1394                 Slog.w(TAG_WM, "Adding window to Display that has been removed.");
   1395                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
   1396             }
   1397 
   1398             mPolicy.adjustWindowParamsLw(win.mAttrs);
   1399             win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
   1400 
   1401             res = mPolicy.prepareAddWindowLw(win, attrs);
   1402             if (res != WindowManagerGlobal.ADD_OKAY) {
   1403                 return res;
   1404             }
   1405 
   1406             final boolean openInputChannels = (outInputChannel != null
   1407                     && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
   1408             if  (openInputChannels) {
   1409                 win.openInputChannel(outInputChannel);
   1410             }
   1411 
   1412             // If adding a toast requires a token for this app we always schedule hiding
   1413             // toast windows to make sure they don't stick around longer then necessary.
   1414             // We hide instead of remove such windows as apps aren't prepared to handle
   1415             // windows being removed under them.
   1416             //
   1417             // If the app is older it can add toasts without a token and hence overlay
   1418             // other apps. To be maximally compatible with these apps we will hide the
   1419             // window after the toast timeout only if the focused window is from another
   1420             // UID, otherwise we allow unlimited duration. When a UID looses focus we
   1421             // schedule hiding all of its toast windows.
   1422             if (type == TYPE_TOAST) {
   1423                 if (!getDefaultDisplayContentLocked().canAddToastWindowForUid(callingUid)) {
   1424                     Slog.w(TAG_WM, "Adding more than one toast window for UID at a time.");
   1425                     return WindowManagerGlobal.ADD_DUPLICATE_ADD;
   1426                 }
   1427                 // Make sure this happens before we moved focus as one can make the
   1428                 // toast focusable to force it not being hidden after the timeout.
   1429                 // Focusable toasts are always timed out to prevent a focused app to
   1430                 // show a focusable toasts while it has focus which will be kept on
   1431                 // the screen after the activity goes away.
   1432                 if (addToastWindowRequiresToken
   1433                         || (attrs.flags & LayoutParams.FLAG_NOT_FOCUSABLE) == 0
   1434                         || mCurrentFocus == null
   1435                         || mCurrentFocus.mOwnerUid != callingUid) {
   1436                     mH.sendMessageDelayed(
   1437                             mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, win),
   1438                             win.mAttrs.hideTimeoutMilliseconds);
   1439                 }
   1440             }
   1441 
   1442             // From now on, no exceptions or errors allowed!
   1443 
   1444             res = WindowManagerGlobal.ADD_OKAY;
   1445             if (mCurrentFocus == null) {
   1446                 mWinAddedSinceNullFocus.add(win);
   1447             }
   1448 
   1449             if (excludeWindowTypeFromTapOutTask(type)) {
   1450                 displayContent.mTapExcludedWindows.add(win);
   1451             }
   1452 
   1453             origId = Binder.clearCallingIdentity();
   1454 
   1455             win.attach();
   1456             mWindowMap.put(client.asBinder(), win);
   1457             if (win.mAppOp != AppOpsManager.OP_NONE) {
   1458                 int startOpResult = mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(),
   1459                         win.getOwningPackage());
   1460                 if ((startOpResult != AppOpsManager.MODE_ALLOWED) &&
   1461                         (startOpResult != AppOpsManager.MODE_DEFAULT)) {
   1462                     win.setAppOpVisibilityLw(false);
   1463                 }
   1464             }
   1465 
   1466             final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
   1467             win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
   1468 
   1469             final AppWindowToken aToken = token.asAppWindowToken();
   1470             if (type == TYPE_APPLICATION_STARTING && aToken != null) {
   1471                 aToken.startingWindow = win;
   1472                 if (DEBUG_STARTING_WINDOW) Slog.v (TAG_WM, "addWindow: " + aToken
   1473                         + " startingWindow=" + win);
   1474             }
   1475 
   1476             boolean imMayMove = true;
   1477 
   1478             win.mToken.addWindow(win);
   1479             if (type == TYPE_INPUT_METHOD) {
   1480                 win.mGivenInsetsPending = true;
   1481                 setInputMethodWindowLocked(win);
   1482                 imMayMove = false;
   1483             } else if (type == TYPE_INPUT_METHOD_DIALOG) {
   1484                 displayContent.computeImeTarget(true /* updateImeTarget */);
   1485                 imMayMove = false;
   1486             } else {
   1487                 if (type == TYPE_WALLPAPER) {
   1488                     displayContent.mWallpaperController.clearLastWallpaperTimeoutTime();
   1489                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
   1490                 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
   1491                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
   1492                 } else if (displayContent.mWallpaperController.isBelowWallpaperTarget(win)) {
   1493                     // If there is currently a wallpaper being shown, and
   1494                     // the base layer of the new window is below the current
   1495                     // layer of the target window, then adjust the wallpaper.
   1496                     // This is to avoid a new window being placed between the
   1497                     // wallpaper and its target.
   1498                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
   1499                 }
   1500             }
   1501 
   1502             // If the window is being added to a stack that's currently adjusted for IME,
   1503             // make sure to apply the same adjust to this new window.
   1504             win.applyAdjustForImeIfNeeded();
   1505 
   1506             if (type == TYPE_DOCK_DIVIDER) {
   1507                 mRoot.getDisplayContent(displayId).getDockedDividerController().setWindow(win);
   1508             }
   1509 
   1510             final WindowStateAnimator winAnimator = win.mWinAnimator;
   1511             winAnimator.mEnterAnimationPending = true;
   1512             winAnimator.mEnteringAnimation = true;
   1513             // Check if we need to prepare a transition for replacing window first.
   1514             if (atoken != null && atoken.isVisible()
   1515                     && !prepareWindowReplacementTransition(atoken)) {
   1516                 // If not, check if need to set up a dummy transition during display freeze
   1517                 // so that the unfreeze wait for the apps to draw. This might be needed if
   1518                 // the app is relaunching.
   1519                 prepareNoneTransitionForRelaunching(atoken);
   1520             }
   1521 
   1522             if (displayContent.isDefaultDisplay) {
   1523                 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
   1524                 final Rect taskBounds;
   1525                 if (atoken != null && atoken.getTask() != null) {
   1526                     taskBounds = mTmpRect;
   1527                     atoken.getTask().getBounds(mTmpRect);
   1528                 } else {
   1529                     taskBounds = null;
   1530                 }
   1531                 if (mPolicy.getInsetHintLw(win.mAttrs, taskBounds, displayInfo.rotation,
   1532                         displayInfo.logicalWidth, displayInfo.logicalHeight, outContentInsets,
   1533                         outStableInsets, outOutsets)) {
   1534                     res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR;
   1535                 }
   1536             } else {
   1537                 outContentInsets.setEmpty();
   1538                 outStableInsets.setEmpty();
   1539             }
   1540 
   1541             if (mInTouchMode) {
   1542                 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
   1543             }
   1544             if (win.mAppToken == null || !win.mAppToken.isClientHidden()) {
   1545                 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
   1546             }
   1547 
   1548             mInputMonitor.setUpdateInputWindowsNeededLw();
   1549 
   1550             boolean focusChanged = false;
   1551             if (win.canReceiveKeys()) {
   1552                 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
   1553                         false /*updateInputWindows*/);
   1554                 if (focusChanged) {
   1555                     imMayMove = false;
   1556                 }
   1557             }
   1558 
   1559             if (imMayMove) {
   1560                 displayContent.computeImeTarget(true /* updateImeTarget */);
   1561             }
   1562 
   1563             // Don't do layout here, the window must call
   1564             // relayout to be displayed, so we'll do it there.
   1565             displayContent.assignWindowLayers(false /* setLayoutNeeded */);
   1566 
   1567             if (focusChanged) {
   1568                 mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
   1569             }
   1570             mInputMonitor.updateInputWindowsLw(false /*force*/);
   1571 
   1572             if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client "
   1573                     + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5));
   1574 
   1575             if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false, displayId)) {
   1576                 reportNewConfig = true;
   1577             }
   1578         }
   1579 
   1580         if (reportNewConfig) {
   1581             sendNewConfiguration(displayId);
   1582         }
   1583 
   1584         Binder.restoreCallingIdentity(origId);
   1585 
   1586         return res;
   1587     }
   1588 
   1589     private boolean doesAddToastWindowRequireToken(String packageName, int callingUid,
   1590             WindowState attachedWindow) {
   1591         // Try using the target SDK of the root window
   1592         if (attachedWindow != null) {
   1593             return attachedWindow.mAppToken != null
   1594                     && attachedWindow.mAppToken.mTargetSdk >= Build.VERSION_CODES.O;
   1595         } else {
   1596             // Otherwise, look at the package
   1597             try {
   1598                 ApplicationInfo appInfo = mContext.getPackageManager()
   1599                         .getApplicationInfoAsUser(packageName, 0,
   1600                                 UserHandle.getUserId(callingUid));
   1601                 if (appInfo.uid != callingUid) {
   1602                     throw new SecurityException("Package " + packageName + " not in UID "
   1603                             + callingUid);
   1604                 }
   1605                 if (appInfo.targetSdkVersion >= Build.VERSION_CODES.O) {
   1606                     return true;
   1607                 }
   1608             } catch (PackageManager.NameNotFoundException e) {
   1609                 /* ignore */
   1610             }
   1611         }
   1612         return false;
   1613     }
   1614 
   1615     /**
   1616      * Returns true if we're done setting up any transitions.
   1617      */
   1618     private boolean prepareWindowReplacementTransition(AppWindowToken atoken) {
   1619         atoken.clearAllDrawn();
   1620         final WindowState replacedWindow = atoken.getReplacingWindow();
   1621         if (replacedWindow == null) {
   1622             // We expect to already receive a request to remove the old window. If it did not
   1623             // happen, let's just simply add a window.
   1624             return false;
   1625         }
   1626         // We use the visible frame, because we want the animation to morph the window from what
   1627         // was visible to the user to the final destination of the new window.
   1628         Rect frame = replacedWindow.mVisibleFrame;
   1629         // We treat this as if this activity was opening, so we can trigger the app transition
   1630         // animation and piggy-back on existing transition animation infrastructure.
   1631         mOpeningApps.add(atoken);
   1632         prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_RELAUNCH, ALWAYS_KEEP_CURRENT);
   1633         mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top,
   1634                 frame.width(), frame.height());
   1635         executeAppTransition();
   1636         return true;
   1637     }
   1638 
   1639     private void prepareNoneTransitionForRelaunching(AppWindowToken atoken) {
   1640         // Set up a none-transition and add the app to opening apps, so that the display
   1641         // unfreeze wait for the apps to be drawn.
   1642         // Note that if the display unfroze already because app unfreeze timed out,
   1643         // we don't set up the transition anymore and just let it go.
   1644         if (mDisplayFrozen && !mOpeningApps.contains(atoken) && atoken.isRelaunching()) {
   1645             mOpeningApps.add(atoken);
   1646             prepareAppTransition(AppTransition.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT);
   1647             executeAppTransition();
   1648         }
   1649     }
   1650 
   1651     /**
   1652      * Returns whether screen capture is disabled for all windows of a specific user.
   1653      */
   1654     boolean isScreenCaptureDisabledLocked(int userId) {
   1655         Boolean disabled = mScreenCaptureDisabled.get(userId);
   1656         if (disabled == null) {
   1657             return false;
   1658         }
   1659         return disabled;
   1660     }
   1661 
   1662     boolean isSecureLocked(WindowState w) {
   1663         if ((w.mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
   1664             return true;
   1665         }
   1666         if (isScreenCaptureDisabledLocked(UserHandle.getUserId(w.mOwnerUid))) {
   1667             return true;
   1668         }
   1669         return false;
   1670     }
   1671 
   1672     @Override
   1673     public void enableSurfaceTrace(ParcelFileDescriptor pfd) {
   1674         final int callingUid = Binder.getCallingUid();
   1675         if (callingUid != SHELL_UID && callingUid != ROOT_UID) {
   1676             throw new SecurityException("Only shell can call enableSurfaceTrace");
   1677         }
   1678 
   1679         synchronized (mWindowMap) {
   1680             mRoot.enableSurfaceTrace(pfd);
   1681         }
   1682     }
   1683 
   1684     @Override
   1685     public void disableSurfaceTrace() {
   1686         final int callingUid = Binder.getCallingUid();
   1687         if (callingUid != SHELL_UID && callingUid != ROOT_UID &&
   1688             callingUid != SYSTEM_UID) {
   1689             throw new SecurityException("Only shell can call disableSurfaceTrace");
   1690         }
   1691         synchronized (mWindowMap) {
   1692             mRoot.disableSurfaceTrace();
   1693         }
   1694     }
   1695 
   1696     /**
   1697      * Set mScreenCaptureDisabled for specific user
   1698      */
   1699     @Override
   1700     public void setScreenCaptureDisabled(int userId, boolean disabled) {
   1701         int callingUid = Binder.getCallingUid();
   1702         if (callingUid != SYSTEM_UID) {
   1703             throw new SecurityException("Only system can call setScreenCaptureDisabled.");
   1704         }
   1705 
   1706         synchronized(mWindowMap) {
   1707             mScreenCaptureDisabled.put(userId, disabled);
   1708             // Update secure surface for all windows belonging to this user.
   1709             mRoot.setSecureSurfaceState(userId, disabled);
   1710         }
   1711     }
   1712 
   1713     void removeWindow(Session session, IWindow client) {
   1714         synchronized(mWindowMap) {
   1715             WindowState win = windowForClientLocked(session, client, false);
   1716             if (win == null) {
   1717                 return;
   1718             }
   1719             win.removeIfPossible();
   1720         }
   1721     }
   1722 
   1723     /**
   1724      * Performs some centralized bookkeeping clean-up on the window that is being removed.
   1725      * NOTE: Should only be called from {@link WindowState#removeImmediately()}
   1726      * TODO: Maybe better handled with a method {@link WindowContainer#removeChild} if we can
   1727      * figure-out a good way to have all parents of a WindowState doing the same thing without
   1728      * forgetting to add the wiring when a new parent of WindowState is added.
   1729      */
   1730     void postWindowRemoveCleanupLocked(WindowState win) {
   1731         if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "postWindowRemoveCleanupLocked: " + win);
   1732         mWindowMap.remove(win.mClient.asBinder());
   1733         if (win.mAppOp != AppOpsManager.OP_NONE) {
   1734             mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
   1735         }
   1736 
   1737         if (mCurrentFocus == null) {
   1738             mWinRemovedSinceNullFocus.add(win);
   1739         }
   1740         mPendingRemove.remove(win);
   1741         mResizingWindows.remove(win);
   1742         updateNonSystemOverlayWindowsVisibilityIfNeeded(win, false /* surfaceShown */);
   1743         mWindowsChanged = true;
   1744         if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Final remove of window: " + win);
   1745 
   1746         if (mInputMethodWindow == win) {
   1747             setInputMethodWindowLocked(null);
   1748         }
   1749 
   1750         final WindowToken token = win.mToken;
   1751         final AppWindowToken atoken = win.mAppToken;
   1752         if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Removing " + win + " from " + token);
   1753         // Window will already be removed from token before this post clean-up method is called.
   1754         if (token.isEmpty()) {
   1755             if (!token.mPersistOnEmpty) {
   1756                 token.removeImmediately();
   1757             } else if (atoken != null) {
   1758                 // TODO: Should this be moved into AppWindowToken.removeWindow? Might go away after
   1759                 // re-factor.
   1760                 atoken.firstWindowDrawn = false;
   1761                 atoken.clearAllDrawn();
   1762                 final TaskStack stack = atoken.getStack();
   1763                 if (stack != null) {
   1764                     stack.mExitingAppTokens.remove(atoken);
   1765                 }
   1766             }
   1767         }
   1768 
   1769         if (atoken != null) {
   1770             atoken.postWindowRemoveStartingWindowCleanup(win);
   1771         }
   1772 
   1773         final DisplayContent dc = win.getDisplayContent();
   1774         if (win.mAttrs.type == TYPE_WALLPAPER) {
   1775             dc.mWallpaperController.clearLastWallpaperTimeoutTime();
   1776             dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
   1777         } else if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
   1778             dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
   1779         }
   1780 
   1781         if (dc != null && !mWindowPlacerLocked.isInLayout()) {
   1782             dc.assignWindowLayers(true /* setLayoutNeeded */);
   1783             mWindowPlacerLocked.performSurfacePlacement();
   1784             if (win.mAppToken != null) {
   1785                 win.mAppToken.updateReportedVisibilityLocked();
   1786             }
   1787         }
   1788 
   1789         mInputMonitor.updateInputWindowsLw(true /*force*/);
   1790     }
   1791 
   1792     void setInputMethodWindowLocked(WindowState win) {
   1793         mInputMethodWindow = win;
   1794         final DisplayContent dc = win != null
   1795                 ? win.getDisplayContent() : getDefaultDisplayContentLocked();
   1796         dc.computeImeTarget(true /* updateImeTarget */);
   1797     }
   1798 
   1799     private void updateAppOpsState() {
   1800         synchronized(mWindowMap) {
   1801             mRoot.updateAppOpsState();
   1802         }
   1803     }
   1804 
   1805     static void logSurface(WindowState w, String msg, boolean withStackTrace) {
   1806         String str = "  SURFACE " + msg + ": " + w;
   1807         if (withStackTrace) {
   1808             logWithStack(TAG, str);
   1809         } else {
   1810             Slog.i(TAG_WM, str);
   1811         }
   1812     }
   1813 
   1814     static void logSurface(SurfaceControl s, String title, String msg) {
   1815         String str = "  SURFACE " + s + ": " + msg + " / " + title;
   1816         Slog.i(TAG_WM, str);
   1817     }
   1818 
   1819     static void logWithStack(String tag, String s) {
   1820         RuntimeException e = null;
   1821         if (SHOW_STACK_CRAWLS) {
   1822             e = new RuntimeException();
   1823             e.fillInStackTrace();
   1824         }
   1825         Slog.i(tag, s, e);
   1826     }
   1827 
   1828     void setTransparentRegionWindow(Session session, IWindow client, Region region) {
   1829         long origId = Binder.clearCallingIdentity();
   1830         try {
   1831             synchronized (mWindowMap) {
   1832                 WindowState w = windowForClientLocked(session, client, false);
   1833                 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
   1834                         "transparentRegionHint=" + region, false);
   1835 
   1836                 if ((w != null) && w.mHasSurface) {
   1837                     w.mWinAnimator.setTransparentRegionHintLocked(region);
   1838                 }
   1839             }
   1840         } finally {
   1841             Binder.restoreCallingIdentity(origId);
   1842         }
   1843     }
   1844 
   1845     void setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets,
   1846             Rect visibleInsets, Region touchableRegion) {
   1847         long origId = Binder.clearCallingIdentity();
   1848         try {
   1849             synchronized (mWindowMap) {
   1850                 WindowState w = windowForClientLocked(session, client, false);
   1851                 if (DEBUG_LAYOUT) Slog.d(TAG, "setInsetsWindow " + w
   1852                         + ", contentInsets=" + w.mGivenContentInsets + " -> " + contentInsets
   1853                         + ", visibleInsets=" + w.mGivenVisibleInsets + " -> " + visibleInsets
   1854                         + ", touchableRegion=" + w.mGivenTouchableRegion + " -> " + touchableRegion
   1855                         + ", touchableInsets " + w.mTouchableInsets + " -> " + touchableInsets);
   1856                 if (w != null) {
   1857                     w.mGivenInsetsPending = false;
   1858                     w.mGivenContentInsets.set(contentInsets);
   1859                     w.mGivenVisibleInsets.set(visibleInsets);
   1860                     w.mGivenTouchableRegion.set(touchableRegion);
   1861                     w.mTouchableInsets = touchableInsets;
   1862                     if (w.mGlobalScale != 1) {
   1863                         w.mGivenContentInsets.scale(w.mGlobalScale);
   1864                         w.mGivenVisibleInsets.scale(w.mGlobalScale);
   1865                         w.mGivenTouchableRegion.scale(w.mGlobalScale);
   1866                     }
   1867                     w.setDisplayLayoutNeeded();
   1868                     mWindowPlacerLocked.performSurfacePlacement();
   1869                 }
   1870             }
   1871         } finally {
   1872             Binder.restoreCallingIdentity(origId);
   1873         }
   1874     }
   1875 
   1876     public void getWindowDisplayFrame(Session session, IWindow client,
   1877             Rect outDisplayFrame) {
   1878         synchronized(mWindowMap) {
   1879             WindowState win = windowForClientLocked(session, client, false);
   1880             if (win == null) {
   1881                 outDisplayFrame.setEmpty();
   1882                 return;
   1883             }
   1884             outDisplayFrame.set(win.mDisplayFrame);
   1885         }
   1886     }
   1887 
   1888     public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
   1889         synchronized (mWindowMap) {
   1890             if (mAccessibilityController != null) {
   1891                 WindowState window = mWindowMap.get(token);
   1892                 //TODO (multidisplay): Magnification is supported only for the default display.
   1893                 if (window != null && window.getDisplayId() == DEFAULT_DISPLAY) {
   1894                     mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle);
   1895                 }
   1896             }
   1897         }
   1898     }
   1899 
   1900     public IWindowId getWindowId(IBinder token) {
   1901         synchronized (mWindowMap) {
   1902             WindowState window = mWindowMap.get(token);
   1903             return window != null ? window.mWindowId : null;
   1904         }
   1905     }
   1906 
   1907     public void pokeDrawLock(Session session, IBinder token) {
   1908         synchronized (mWindowMap) {
   1909             WindowState window = windowForClientLocked(session, token, false);
   1910             if (window != null) {
   1911                 window.pokeDrawLockLw(mDrawLockTimeoutMillis);
   1912             }
   1913         }
   1914     }
   1915 
   1916     public int relayoutWindow(Session session, IWindow client, int seq,
   1917             WindowManager.LayoutParams attrs, int requestedWidth,
   1918             int requestedHeight, int viewVisibility, int flags,
   1919             Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
   1920             Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
   1921             MergedConfiguration mergedConfiguration, Surface outSurface) {
   1922         int result = 0;
   1923         boolean configChanged;
   1924         boolean hasStatusBarPermission =
   1925                 mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
   1926                         == PackageManager.PERMISSION_GRANTED;
   1927 
   1928         long origId = Binder.clearCallingIdentity();
   1929         final int displayId;
   1930         synchronized(mWindowMap) {
   1931             WindowState win = windowForClientLocked(session, client, false);
   1932             if (win == null) {
   1933                 return 0;
   1934             }
   1935             displayId = win.getDisplayId();
   1936 
   1937             WindowStateAnimator winAnimator = win.mWinAnimator;
   1938             if (viewVisibility != View.GONE) {
   1939                 win.setRequestedSize(requestedWidth, requestedHeight);
   1940             }
   1941 
   1942             int attrChanges = 0;
   1943             int flagChanges = 0;
   1944             if (attrs != null) {
   1945                 mPolicy.adjustWindowParamsLw(attrs);
   1946                 // if they don't have the permission, mask out the status bar bits
   1947                 if (seq == win.mSeq) {
   1948                     int systemUiVisibility = attrs.systemUiVisibility
   1949                             | attrs.subtreeSystemUiVisibility;
   1950                     if ((systemUiVisibility & DISABLE_MASK) != 0) {
   1951                         if (!hasStatusBarPermission) {
   1952                             systemUiVisibility &= ~DISABLE_MASK;
   1953                         }
   1954                     }
   1955                     win.mSystemUiVisibility = systemUiVisibility;
   1956                 }
   1957                 if (win.mAttrs.type != attrs.type) {
   1958                     throw new IllegalArgumentException(
   1959                             "Window type can not be changed after the window is added.");
   1960                 }
   1961 
   1962                 // Odd choice but less odd than embedding in copyFrom()
   1963                 if ((attrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY)
   1964                         != 0) {
   1965                     attrs.x = win.mAttrs.x;
   1966                     attrs.y = win.mAttrs.y;
   1967                     attrs.width = win.mAttrs.width;
   1968                     attrs.height = win.mAttrs.height;
   1969                 }
   1970 
   1971                 flagChanges = win.mAttrs.flags ^= attrs.flags;
   1972                 attrChanges = win.mAttrs.copyFrom(attrs);
   1973                 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
   1974                         | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
   1975                     win.mLayoutNeeded = true;
   1976                 }
   1977                 if (win.mAppToken != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0
   1978                         || (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) {
   1979                     win.mAppToken.checkKeyguardFlagsChanged();
   1980                 }
   1981                 if (((attrChanges & LayoutParams.ACCESSIBILITY_TITLE_CHANGED) != 0)
   1982                         && (mAccessibilityController != null)
   1983                         && (win.getDisplayId() == DEFAULT_DISPLAY)) {
   1984                     // No move or resize, but the controller checks for title changes as well
   1985                     mAccessibilityController.onSomeWindowResizedOrMovedLocked();
   1986                 }
   1987             }
   1988 
   1989             if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility
   1990                     + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
   1991             winAnimator.mSurfaceDestroyDeferred = (flags & RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
   1992             win.mEnforceSizeCompat =
   1993                     (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
   1994             if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
   1995                 winAnimator.mAlpha = attrs.alpha;
   1996             }
   1997             win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
   1998 
   1999             if (win.mAttrs.surfaceInsets.left != 0
   2000                     || win.mAttrs.surfaceInsets.top != 0
   2001                     || win.mAttrs.surfaceInsets.right != 0
   2002                     || win.mAttrs.surfaceInsets.bottom != 0) {
   2003                 winAnimator.setOpaqueLocked(false);
   2004             }
   2005 
   2006             boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
   2007             final boolean isDefaultDisplay = win.isDefaultDisplay();
   2008             boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
   2009                     || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
   2010                     || (!win.mRelayoutCalled));
   2011 
   2012             boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
   2013                     && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
   2014             wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
   2015             if ((flagChanges & FLAG_SECURE) != 0 && winAnimator.mSurfaceController != null) {
   2016                 winAnimator.mSurfaceController.setSecure(isSecureLocked(win));
   2017             }
   2018 
   2019             win.mRelayoutCalled = true;
   2020             win.mInRelayout = true;
   2021 
   2022             final int oldVisibility = win.mViewVisibility;
   2023             win.mViewVisibility = viewVisibility;
   2024             if (DEBUG_SCREEN_ON) {
   2025                 RuntimeException stack = new RuntimeException();
   2026                 stack.fillInStackTrace();
   2027                 Slog.i(TAG_WM, "Relayout " + win + ": oldVis=" + oldVisibility
   2028                         + " newVis=" + viewVisibility, stack);
   2029             }
   2030 
   2031             // We should only relayout if the view is visible, it is a starting window, or the
   2032             // associated appToken is not hidden.
   2033             final boolean shouldRelayout = viewVisibility == View.VISIBLE &&
   2034                 (win.mAppToken == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
   2035                     || !win.mAppToken.isClientHidden());
   2036 
   2037             if (shouldRelayout) {
   2038                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_1");
   2039 
   2040                 // We are about to create a surface, but we didn't run a layout yet. So better run
   2041                 // a layout now that we already know the right size, as a resize call will make the
   2042                 // surface transaction blocking until next vsync and slow us down.
   2043                 // TODO: Ideally we'd create the surface after running layout a bit further down,
   2044                 // but moving this seems to be too risky at this point in the release.
   2045                 if (win.mLayoutSeq == -1) {
   2046                     win.setDisplayLayoutNeeded();
   2047                     mWindowPlacerLocked.performSurfacePlacement(true);
   2048                 }
   2049                 result = win.relayoutVisibleWindow(result, attrChanges, oldVisibility);
   2050 
   2051                 try {
   2052                     result = createSurfaceControl(outSurface, result, win, winAnimator);
   2053                 } catch (Exception e) {
   2054                     mInputMonitor.updateInputWindowsLw(true /*force*/);
   2055 
   2056                     Slog.w(TAG_WM, "Exception thrown when creating surface for client "
   2057                              + client + " (" + win.mAttrs.getTitle() + ")",
   2058                              e);
   2059                     Binder.restoreCallingIdentity(origId);
   2060                     return 0;
   2061                 }
   2062                 if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
   2063                     focusMayChange = isDefaultDisplay;
   2064                 }
   2065                 if (win.mAttrs.type == TYPE_INPUT_METHOD && mInputMethodWindow == null) {
   2066                     setInputMethodWindowLocked(win);
   2067                     imMayMove = true;
   2068                 }
   2069                 win.adjustStartingWindowFlags();
   2070                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
   2071             } else {
   2072                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_2");
   2073 
   2074                 winAnimator.mEnterAnimationPending = false;
   2075                 winAnimator.mEnteringAnimation = false;
   2076                 final boolean usingSavedSurfaceBeforeVisible =
   2077                         oldVisibility != View.VISIBLE && win.isAnimatingWithSavedSurface();
   2078                 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
   2079                     if (winAnimator.hasSurface() && !win.mAnimatingExit
   2080                             && usingSavedSurfaceBeforeVisible) {
   2081                         Slog.d(TAG, "Ignoring layout to invisible when using saved surface " + win);
   2082                     }
   2083                 }
   2084 
   2085                 if (winAnimator.hasSurface() && !win.mAnimatingExit
   2086                         && !usingSavedSurfaceBeforeVisible) {
   2087                     if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Relayout invis " + win
   2088                             + ": mAnimatingExit=" + win.mAnimatingExit);
   2089                     // If we are not currently running the exit animation, we
   2090                     // need to see about starting one.
   2091                     // We don't want to animate visibility of windows which are pending
   2092                     // replacement. In the case of activity relaunch child windows
   2093                     // could request visibility changes as they are detached from the main
   2094                     // application window during the tear down process. If we satisfied
   2095                     // these visibility changes though, we would cause a visual glitch
   2096                     // hiding the window before it's replacement was available.
   2097                     // So we just do nothing on our side.
   2098                     if (!win.mWillReplaceWindow) {
   2099                         focusMayChange = tryStartExitingAnimation(
   2100                                 win, winAnimator, isDefaultDisplay, focusMayChange);
   2101                     }
   2102                     result |= RELAYOUT_RES_SURFACE_CHANGED;
   2103                 }
   2104                 if (viewVisibility == View.VISIBLE && winAnimator.hasSurface()) {
   2105                     // We already told the client to go invisible, but the message may not be
   2106                     // handled yet, or it might want to draw a last frame. If we already have a
   2107                     // surface, let the client use that, but don't create new surface at this point.
   2108                     Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: getSurface");
   2109                     winAnimator.mSurfaceController.getSurface(outSurface);
   2110                     Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
   2111                 } else {
   2112                     if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win);
   2113 
   2114                     try {
   2115                         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wmReleaseOutSurface_"
   2116                                 + win.mAttrs.getTitle());
   2117                         outSurface.release();
   2118                     } finally {
   2119                         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
   2120                     }
   2121                 }
   2122 
   2123                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
   2124             }
   2125 
   2126             if (focusMayChange) {
   2127                 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
   2128                 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
   2129                         false /*updateInputWindows*/)) {
   2130                     imMayMove = false;
   2131                 }
   2132                 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
   2133             }
   2134 
   2135             // updateFocusedWindowLocked() already assigned layers so we only need to
   2136             // reassign them at this point if the IM window state gets shuffled
   2137             boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
   2138             final DisplayContent dc = win.getDisplayContent();
   2139             if (imMayMove) {
   2140                 dc.computeImeTarget(true /* updateImeTarget */);
   2141                 if (toBeDisplayed) {
   2142                     // Little hack here -- we -should- be able to rely on the function to return
   2143                     // true if the IME has moved and needs its layer recomputed. However, if the IME
   2144                     // was hidden and isn't actually moved in the list, its layer may be out of data
   2145                     // so we make sure to recompute it.
   2146                     dc.assignWindowLayers(false /* setLayoutNeeded */);
   2147                 }
   2148             }
   2149 
   2150             if (wallpaperMayMove) {
   2151                 win.getDisplayContent().pendingLayoutChanges |=
   2152                         WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
   2153             }
   2154 
   2155             if (win.mAppToken != null) {
   2156                 mUnknownAppVisibilityController.notifyRelayouted(win.mAppToken);
   2157             }
   2158 
   2159             win.setDisplayLayoutNeeded();
   2160             win.mGivenInsetsPending = (flags & WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
   2161             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
   2162                     "relayoutWindow: updateOrientationFromAppTokens");
   2163             configChanged = updateOrientationFromAppTokensLocked(false, displayId);
   2164             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
   2165 
   2166             // We may be deferring layout passes at the moment, but since the client is interested
   2167             // in the new out values right now we need to force a layout.
   2168             mWindowPlacerLocked.performSurfacePlacement(true /* force */);
   2169             if (toBeDisplayed && win.mIsWallpaper) {
   2170                 DisplayInfo displayInfo = win.getDisplayContent().getDisplayInfo();
   2171                 dc.mWallpaperController.updateWallpaperOffset(
   2172                         win, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
   2173             }
   2174             if (win.mAppToken != null) {
   2175                 win.mAppToken.updateReportedVisibilityLocked();
   2176             }
   2177             if (winAnimator.mReportSurfaceResized) {
   2178                 winAnimator.mReportSurfaceResized = false;
   2179                 result |= WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED;
   2180             }
   2181             if (mPolicy.isNavBarForcedShownLw(win)) {
   2182                 result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR;
   2183             }
   2184             if (!win.isGoneForLayoutLw()) {
   2185                 win.mResizedWhileGone = false;
   2186             }
   2187 
   2188             // We must always send the latest {@link MergedConfiguration}, regardless of whether we
   2189             // have already reported it. The client might not have processed the previous value yet
   2190             // and needs process it before handling the corresponding window frame. the variable
   2191             // {@code mergedConfiguration} is an out parameter that will be passed back to the
   2192             // client over IPC and checked there.
   2193             // Note: in the cases where the window is tied to an activity, we should not send a
   2194             // configuration update when the window has requested to be hidden. Doing so can lead
   2195             // to the client erroneously accepting a configuration that would have otherwise caused
   2196             // an activity restart. We instead hand back the last reported
   2197             // {@link MergedConfiguration}.
   2198             if (shouldRelayout) {
   2199                 win.getMergedConfiguration(mergedConfiguration);
   2200             } else {
   2201                 win.getLastReportedMergedConfiguration(mergedConfiguration);
   2202             }
   2203 
   2204             win.setLastReportedMergedConfiguration(mergedConfiguration);
   2205 
   2206             outFrame.set(win.mCompatFrame);
   2207             outOverscanInsets.set(win.mOverscanInsets);
   2208             outContentInsets.set(win.mContentInsets);
   2209             win.mLastRelayoutContentInsets.set(win.mContentInsets);
   2210             outVisibleInsets.set(win.mVisibleInsets);
   2211             outStableInsets.set(win.mStableInsets);
   2212             outOutsets.set(win.mOutsets);
   2213             outBackdropFrame.set(win.getBackdropFrame(win.mFrame));
   2214             if (localLOGV) Slog.v(
   2215                 TAG_WM, "Relayout given client " + client.asBinder()
   2216                 + ", requestedWidth=" + requestedWidth
   2217                 + ", requestedHeight=" + requestedHeight
   2218                 + ", viewVisibility=" + viewVisibility
   2219                 + "\nRelayout returning frame=" + outFrame
   2220                 + ", surface=" + outSurface);
   2221 
   2222             if (localLOGV || DEBUG_FOCUS) Slog.v(
   2223                 TAG_WM, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
   2224 
   2225             result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0;
   2226 
   2227             mInputMonitor.updateInputWindowsLw(true /*force*/);
   2228 
   2229             if (DEBUG_LAYOUT) {
   2230                 Slog.v(TAG_WM, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
   2231             }
   2232             win.mInRelayout = false;
   2233         }
   2234 
   2235         if (configChanged) {
   2236             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: sendNewConfiguration");
   2237             sendNewConfiguration(displayId);
   2238             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
   2239         }
   2240         Binder.restoreCallingIdentity(origId);
   2241         return result;
   2242     }
   2243 
   2244     private boolean tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator,
   2245             boolean isDefaultDisplay, boolean focusMayChange) {
   2246         // Try starting an animation; if there isn't one, we
   2247         // can destroy the surface right away.
   2248         int transit = WindowManagerPolicy.TRANSIT_EXIT;
   2249         if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
   2250             transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
   2251         }
   2252         if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) {
   2253             focusMayChange = isDefaultDisplay;
   2254             win.mAnimatingExit = true;
   2255             win.mWinAnimator.mAnimating = true;
   2256         } else if (win.mWinAnimator.isAnimationSet()) {
   2257             // Currently in a hide animation... turn this into
   2258             // an exit.
   2259             win.mAnimatingExit = true;
   2260             win.mWinAnimator.mAnimating = true;
   2261         } else if (win.getDisplayContent().mWallpaperController.isWallpaperTarget(win)) {
   2262             // If the wallpaper is currently behind this
   2263             // window, we need to change both of them inside
   2264             // of a transaction to avoid artifacts.
   2265             win.mAnimatingExit = true;
   2266             win.mWinAnimator.mAnimating = true;
   2267         } else {
   2268             if (mInputMethodWindow == win) {
   2269                 setInputMethodWindowLocked(null);
   2270             }
   2271             boolean stopped = win.mAppToken != null ? win.mAppToken.mAppStopped : false;
   2272             // We set mDestroying=true so AppWindowToken#notifyAppStopped in-to destroy surfaces
   2273             // will later actually destroy the surface if we do not do so here. Normally we leave
   2274             // this to the exit animation.
   2275             win.mDestroying = true;
   2276             win.destroySurface(false, stopped);
   2277         }
   2278         // TODO(multidisplay): Magnification is supported only for the default display.
   2279         if (mAccessibilityController != null && win.getDisplayId() == DEFAULT_DISPLAY) {
   2280             mAccessibilityController.onWindowTransitionLocked(win, transit);
   2281         }
   2282 
   2283         // When we start the exit animation we take the Surface from the client
   2284         // so it will stop perturbing it. We need to likewise takeaway the SurfaceFlinger
   2285         // side child surfaces, so they will remain preserved in their current state
   2286         // (rather than be cleaned up immediately by the app code).
   2287         SurfaceControl.openTransaction();
   2288         winAnimator.detachChildren();
   2289         SurfaceControl.closeTransaction();
   2290 
   2291         return focusMayChange;
   2292     }
   2293 
   2294     private int createSurfaceControl(Surface outSurface, int result, WindowState win,
   2295             WindowStateAnimator winAnimator) {
   2296         if (!win.mHasSurface) {
   2297             result |= RELAYOUT_RES_SURFACE_CHANGED;
   2298         }
   2299 
   2300         WindowSurfaceController surfaceController;
   2301         try {
   2302             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");
   2303             surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
   2304         } finally {
   2305             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
   2306         }
   2307         if (surfaceController != null) {
   2308             surfaceController.getSurface(outSurface);
   2309             if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  OUT SURFACE " + outSurface + ": copied");
   2310         } else {
   2311             // For some reason there isn't a surface.  Clear the
   2312             // caller's object so they see the same state.
   2313             Slog.w(TAG_WM, "Failed to create surface control for " + win);
   2314             outSurface.release();
   2315         }
   2316 
   2317         return result;
   2318     }
   2319 
   2320     public boolean outOfMemoryWindow(Session session, IWindow client) {
   2321         final long origId = Binder.clearCallingIdentity();
   2322 
   2323         try {
   2324             synchronized (mWindowMap) {
   2325                 WindowState win = windowForClientLocked(session, client, false);
   2326                 if (win == null) {
   2327                     return false;
   2328                 }
   2329                 return mRoot.reclaimSomeSurfaceMemory(win.mWinAnimator, "from-client", false);
   2330             }
   2331         } finally {
   2332             Binder.restoreCallingIdentity(origId);
   2333         }
   2334     }
   2335 
   2336     void finishDrawingWindow(Session session, IWindow client) {
   2337         final long origId = Binder.clearCallingIdentity();
   2338         try {
   2339             synchronized (mWindowMap) {
   2340                 WindowState win = windowForClientLocked(session, client, false);
   2341                 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "finishDrawingWindow: " + win + " mDrawState="
   2342                         + (win != null ? win.mWinAnimator.drawStateToString() : "null"));
   2343                 if (win != null && win.mWinAnimator.finishDrawingLocked()) {
   2344                     if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
   2345                         win.getDisplayContent().pendingLayoutChanges |=
   2346                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
   2347                     }
   2348                     win.setDisplayLayoutNeeded();
   2349                     mWindowPlacerLocked.requestTraversal();
   2350                 }
   2351             }
   2352         } finally {
   2353             Binder.restoreCallingIdentity(origId);
   2354         }
   2355     }
   2356 
   2357     boolean applyAnimationLocked(AppWindowToken atoken, WindowManager.LayoutParams lp,
   2358             int transit, boolean enter, boolean isVoiceInteraction) {
   2359         // Only apply an animation if the display isn't frozen.  If it is
   2360         // frozen, there is no reason to animate and it can cause strange
   2361         // artifacts when we unfreeze the display if some different animation
   2362         // is running.
   2363         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked");
   2364         if (atoken.okToAnimate()) {
   2365             final DisplayContent displayContent = atoken.getTask().getDisplayContent();
   2366             final DisplayInfo displayInfo = displayContent.getDisplayInfo();
   2367             final int width = displayInfo.appWidth;
   2368             final int height = displayInfo.appHeight;
   2369             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
   2370                     "applyAnimation: atoken=" + atoken);
   2371 
   2372             // Determine the visible rect to calculate the thumbnail clip
   2373             final WindowState win = atoken.findMainWindow();
   2374             final Rect frame = new Rect(0, 0, width, height);
   2375             final Rect displayFrame = new Rect(0, 0,
   2376                     displayInfo.logicalWidth, displayInfo.logicalHeight);
   2377             final Rect insets = new Rect();
   2378             final Rect stableInsets = new Rect();
   2379             Rect surfaceInsets = null;
   2380             final boolean freeform = win != null && win.inFreeformWorkspace();
   2381             if (win != null) {
   2382                 // Containing frame will usually cover the whole screen, including dialog windows.
   2383                 // For freeform workspace windows it will not cover the whole screen and it also
   2384                 // won't exactly match the final freeform window frame (e.g. when overlapping with
   2385                 // the status bar). In that case we need to use the final frame.
   2386                 if (freeform) {
   2387                     frame.set(win.mFrame);
   2388                 } else {
   2389                     frame.set(win.mContainingFrame);
   2390                 }
   2391                 surfaceInsets = win.getAttrs().surfaceInsets;
   2392                 insets.set(win.mContentInsets);
   2393                 stableInsets.set(win.mStableInsets);
   2394             }
   2395 
   2396             if (atoken.mLaunchTaskBehind) {
   2397                 // Differentiate the two animations. This one which is briefly on the screen
   2398                 // gets the !enter animation, and the other activity which remains on the
   2399                 // screen gets the enter animation. Both appear in the mOpeningApps set.
   2400                 enter = false;
   2401             }
   2402             if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
   2403                     + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
   2404                     + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
   2405             final Configuration displayConfig = displayContent.getConfiguration();
   2406             Animation a = mAppTransition.loadAnimation(lp, transit, enter, displayConfig.uiMode,
   2407                     displayConfig.orientation, frame, displayFrame, insets, surfaceInsets,
   2408                     stableInsets, isVoiceInteraction, freeform, atoken.getTask().mTaskId);
   2409             if (a != null) {
   2410                 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken);
   2411                 final int containingWidth = frame.width();
   2412                 final int containingHeight = frame.height();
   2413                 atoken.mAppAnimator.setAnimation(a, containingWidth, containingHeight, width,
   2414                         height, mAppTransition.canSkipFirstFrame(),
   2415                         mAppTransition.getAppStackClipMode(),
   2416                         transit, mAppTransition.getTransitFlags());
   2417             }
   2418         } else {
   2419             atoken.mAppAnimator.clearAnimation();
   2420         }
   2421         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
   2422 
   2423         return atoken.mAppAnimator.animation != null;
   2424     }
   2425 
   2426     boolean checkCallingPermission(String permission, String func) {
   2427         // Quick check: if the calling permission is me, it's all okay.
   2428         if (Binder.getCallingPid() == myPid()) {
   2429             return true;
   2430         }
   2431 
   2432         if (mContext.checkCallingPermission(permission)
   2433                 == PackageManager.PERMISSION_GRANTED) {
   2434             return true;
   2435         }
   2436         final String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid()
   2437                 + ", uid=" + Binder.getCallingUid() + " requires " + permission;
   2438         Slog.w(TAG_WM, msg);
   2439         return false;
   2440     }
   2441 
   2442     @Override
   2443     public void addWindowToken(IBinder binder, int type, int displayId) {
   2444         if (!checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()")) {
   2445             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   2446         }
   2447 
   2448         synchronized(mWindowMap) {
   2449             final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId);
   2450             WindowToken token = dc.getWindowToken(binder);
   2451             if (token != null) {
   2452                 Slog.w(TAG_WM, "addWindowToken: Attempted to add binder token: " + binder
   2453                         + " for already created window token: " + token
   2454                         + " displayId=" + displayId);
   2455                 return;
   2456             }
   2457             if (type == TYPE_WALLPAPER) {
   2458                 new WallpaperWindowToken(this, binder, true, dc,
   2459                         true /* ownerCanManageAppTokens */);
   2460             } else {
   2461                 new WindowToken(this, binder, type, true, dc, true /* ownerCanManageAppTokens */);
   2462             }
   2463         }
   2464     }
   2465 
   2466     @Override
   2467     public void removeWindowToken(IBinder binder, int displayId) {
   2468         if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeWindowToken()")) {
   2469             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   2470         }
   2471 
   2472         final long origId = Binder.clearCallingIdentity();
   2473         try {
   2474             synchronized (mWindowMap) {
   2475                 final DisplayContent dc = mRoot.getDisplayContent(displayId);
   2476                 if (dc == null) {
   2477                     Slog.w(TAG_WM, "removeWindowToken: Attempted to remove token: " + binder
   2478                             + " for non-exiting displayId=" + displayId);
   2479                     return;
   2480                 }
   2481 
   2482                 final WindowToken token = dc.removeWindowToken(binder);
   2483                 if (token == null) {
   2484                     Slog.w(TAG_WM,
   2485                             "removeWindowToken: Attempted to remove non-existing token: " + binder);
   2486                     return;
   2487                 }
   2488 
   2489                 mInputMonitor.updateInputWindowsLw(true /*force*/);
   2490             }
   2491         } finally {
   2492             Binder.restoreCallingIdentity(origId);
   2493         }
   2494     }
   2495 
   2496     @Override
   2497     public Configuration updateOrientationFromAppTokens(Configuration currentConfig,
   2498             IBinder freezeThisOneIfNeeded, int displayId) {
   2499         if (!checkCallingPermission(MANAGE_APP_TOKENS, "updateOrientationFromAppTokens()")) {
   2500             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   2501         }
   2502 
   2503         final Configuration config;
   2504         final long ident = Binder.clearCallingIdentity();
   2505         try {
   2506             synchronized(mWindowMap) {
   2507                 config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded,
   2508                         displayId);
   2509             }
   2510         } finally {
   2511             Binder.restoreCallingIdentity(ident);
   2512         }
   2513 
   2514         return config;
   2515     }
   2516 
   2517     private Configuration updateOrientationFromAppTokensLocked(Configuration currentConfig,
   2518             IBinder freezeThisOneIfNeeded, int displayId) {
   2519         if (!mDisplayReady) {
   2520             return null;
   2521         }
   2522         Configuration config = null;
   2523 
   2524         if (updateOrientationFromAppTokensLocked(false, displayId)) {
   2525             // If we changed the orientation but mOrientationChangeComplete is already true,
   2526             // we used seamless rotation, and we don't need to freeze the screen.
   2527             if (freezeThisOneIfNeeded != null && !mRoot.mOrientationChangeComplete) {
   2528                 final AppWindowToken atoken = mRoot.getAppWindowToken(freezeThisOneIfNeeded);
   2529                 if (atoken != null) {
   2530                     atoken.startFreezingScreen();
   2531                 }
   2532             }
   2533             config = computeNewConfigurationLocked(displayId);
   2534 
   2535         } else if (currentConfig != null) {
   2536             // No obvious action we need to take, but if our current state mismatches the activity
   2537             // manager's, update it, disregarding font scale, which should remain set to the value
   2538             // of the previous configuration.
   2539             // Here we're calling Configuration#unset() instead of setToDefaults() because we need
   2540             // to keep override configs clear of non-empty values (e.g. fontSize).
   2541             mTempConfiguration.unset();
   2542             mTempConfiguration.updateFrom(currentConfig);
   2543             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
   2544             displayContent.computeScreenConfiguration(mTempConfiguration);
   2545             if (currentConfig.diff(mTempConfiguration) != 0) {
   2546                 mWaitingForConfig = true;
   2547                 displayContent.setLayoutNeeded();
   2548                 int anim[] = new int[2];
   2549                 if (displayContent.isDimming()) {
   2550                     anim[0] = anim[1] = 0;
   2551                 } else {
   2552                     mPolicy.selectRotationAnimationLw(anim);
   2553                 }
   2554                 startFreezingDisplayLocked(false, anim[0], anim[1], displayContent);
   2555                 config = new Configuration(mTempConfiguration);
   2556             }
   2557         }
   2558 
   2559         return config;
   2560     }
   2561 
   2562     /**
   2563      * Determine the new desired orientation of the display, returning a non-null new Configuration
   2564      * if it has changed from the current orientation.  IF TRUE IS RETURNED SOMEONE MUST CALL
   2565      * {@link #setNewDisplayOverrideConfiguration(Configuration, int)} TO TELL THE WINDOW MANAGER IT
   2566      * CAN UNFREEZE THE SCREEN.  This will typically be done for you if you call
   2567      * {@link #sendNewConfiguration(int)}.
   2568      *
   2569      * The orientation is computed from non-application windows first. If none of the
   2570      * non-application windows specify orientation, the orientation is computed from application
   2571      * tokens.
   2572      * @see android.view.IWindowManager#updateOrientationFromAppTokens(Configuration, IBinder, int)
   2573      */
   2574     boolean updateOrientationFromAppTokensLocked(boolean inTransaction, int displayId) {
   2575         long ident = Binder.clearCallingIdentity();
   2576         try {
   2577             final DisplayContent dc = mRoot.getDisplayContent(displayId);
   2578             final int req = dc.getOrientation();
   2579             if (req != dc.getLastOrientation()) {
   2580                 dc.setLastOrientation(req);
   2581                 //send a message to Policy indicating orientation change to take
   2582                 //action like disabling/enabling sensors etc.,
   2583                 // TODO(multi-display): Implement policy for secondary displays.
   2584                 if (dc.isDefaultDisplay) {
   2585                     mPolicy.setCurrentOrientationLw(req);
   2586                 }
   2587                 if (dc.updateRotationUnchecked(inTransaction)) {
   2588                     // changed
   2589                     return true;
   2590                 }
   2591             }
   2592 
   2593             return false;
   2594         } finally {
   2595             Binder.restoreCallingIdentity(ident);
   2596         }
   2597     }
   2598 
   2599     // If this is true we have updated our desired orientation, but not yet
   2600     // changed the real orientation our applied our screen rotation animation.
   2601     // For example, because a previous screen rotation was in progress.
   2602     boolean rotationNeedsUpdateLocked() {
   2603         // TODO(multi-display): Check for updates on all displays. Need to have per-display policy
   2604         // to implement WindowManagerPolicy#rotationForOrientationLw() correctly.
   2605         final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
   2606         final int lastOrientation = defaultDisplayContent.getLastOrientation();
   2607         final int oldRotation = defaultDisplayContent.getRotation();
   2608         final boolean oldAltOrientation = defaultDisplayContent.getAltOrientation();
   2609 
   2610         final int rotation = mPolicy.rotationForOrientationLw(lastOrientation,
   2611                 oldRotation);
   2612         boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
   2613                 lastOrientation, rotation);
   2614         if (oldRotation == rotation && oldAltOrientation == altOrientation) {
   2615             return false;
   2616         }
   2617         return true;
   2618     }
   2619 
   2620     @Override
   2621     public int[] setNewDisplayOverrideConfiguration(Configuration overrideConfig, int displayId) {
   2622         if (!checkCallingPermission(MANAGE_APP_TOKENS, "setNewDisplayOverrideConfiguration()")) {
   2623             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   2624         }
   2625 
   2626         synchronized(mWindowMap) {
   2627             if (mWaitingForConfig) {
   2628                 mWaitingForConfig = false;
   2629                 mLastFinishedFreezeSource = "new-config";
   2630             }
   2631             return mRoot.setDisplayOverrideConfigurationIfNeeded(overrideConfig, displayId);
   2632         }
   2633     }
   2634 
   2635     void setFocusTaskRegionLocked(AppWindowToken previousFocus) {
   2636         final Task focusedTask = mFocusedApp != null ? mFocusedApp.getTask() : null;
   2637         final Task previousTask = previousFocus != null ? previousFocus.getTask() : null;
   2638         final DisplayContent focusedDisplayContent =
   2639                 focusedTask != null ? focusedTask.getDisplayContent() : null;
   2640         final DisplayContent previousDisplayContent =
   2641                 previousTask != null ? previousTask.getDisplayContent() : null;
   2642         if (previousDisplayContent != null && previousDisplayContent != focusedDisplayContent) {
   2643             previousDisplayContent.setTouchExcludeRegion(null);
   2644         }
   2645         if (focusedDisplayContent != null) {
   2646             focusedDisplayContent.setTouchExcludeRegion(focusedTask);
   2647         }
   2648     }
   2649 
   2650     @Override
   2651     public void setFocusedApp(IBinder token, boolean moveFocusNow) {
   2652         if (!checkCallingPermission(MANAGE_APP_TOKENS, "setFocusedApp()")) {
   2653             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   2654         }
   2655 
   2656         synchronized(mWindowMap) {
   2657             final AppWindowToken newFocus;
   2658             if (token == null) {
   2659                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Clearing focused app, was " + mFocusedApp);
   2660                 newFocus = null;
   2661             } else {
   2662                 newFocus = mRoot.getAppWindowToken(token);
   2663                 if (newFocus == null) {
   2664                     Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token);
   2665                 }
   2666                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Set focused app to: " + newFocus
   2667                         + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow);
   2668             }
   2669 
   2670             final boolean changed = mFocusedApp != newFocus;
   2671             if (changed) {
   2672                 AppWindowToken prev = mFocusedApp;
   2673                 mFocusedApp = newFocus;
   2674                 mInputMonitor.setFocusedAppLw(newFocus);
   2675                 setFocusTaskRegionLocked(prev);
   2676             }
   2677 
   2678             if (moveFocusNow && changed) {
   2679                 final long origId = Binder.clearCallingIdentity();
   2680                 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
   2681                 Binder.restoreCallingIdentity(origId);
   2682             }
   2683         }
   2684     }
   2685 
   2686     @Override
   2687     public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
   2688         prepareAppTransition(transit, alwaysKeepCurrent, 0 /* flags */, false /* forceOverride */);
   2689     }
   2690 
   2691     /**
   2692      * @param transit What kind of transition is happening. Use one of the constants
   2693      *                AppTransition.TRANSIT_*.
   2694      * @param alwaysKeepCurrent If true and a transition is already set, new transition will NOT
   2695      *                          be set.
   2696      * @param flags Additional flags for the app transition, Use a combination of the constants
   2697      *              AppTransition.TRANSIT_FLAG_*.
   2698      * @param forceOverride Always override the transit, not matter what was set previously.
   2699      */
   2700     public void prepareAppTransition(int transit, boolean alwaysKeepCurrent, int flags,
   2701             boolean forceOverride) {
   2702         if (!checkCallingPermission(MANAGE_APP_TOKENS, "prepareAppTransition()")) {
   2703             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   2704         }
   2705         synchronized(mWindowMap) {
   2706             boolean prepared = mAppTransition.prepareAppTransitionLocked(transit, alwaysKeepCurrent,
   2707                     flags, forceOverride);
   2708             // TODO (multidisplay): associate app transitions with displays
   2709             final DisplayContent dc = mRoot.getDisplayContent(DEFAULT_DISPLAY);
   2710             if (prepared && dc != null && dc.okToAnimate()) {
   2711                 mSkipAppTransitionAnimation = false;
   2712             }
   2713         }
   2714     }
   2715 
   2716     @Override
   2717     public int getPendingAppTransition() {
   2718         return mAppTransition.getAppTransition();
   2719     }
   2720 
   2721     @Override
   2722     public void overridePendingAppTransition(String packageName,
   2723             int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
   2724         synchronized(mWindowMap) {
   2725             mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim,
   2726                     startedCallback);
   2727         }
   2728     }
   2729 
   2730     @Override
   2731     public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
   2732             int startHeight) {
   2733         synchronized(mWindowMap) {
   2734             mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth,
   2735                     startHeight);
   2736         }
   2737     }
   2738 
   2739     @Override
   2740     public void overridePendingAppTransitionClipReveal(int startX, int startY,
   2741             int startWidth, int startHeight) {
   2742         synchronized(mWindowMap) {
   2743             mAppTransition.overridePendingAppTransitionClipReveal(startX, startY, startWidth,
   2744                     startHeight);
   2745         }
   2746     }
   2747 
   2748     @Override
   2749     public void overridePendingAppTransitionThumb(GraphicBuffer srcThumb, int startX,
   2750             int startY, IRemoteCallback startedCallback, boolean scaleUp) {
   2751         synchronized(mWindowMap) {
   2752             mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY,
   2753                     startedCallback, scaleUp);
   2754         }
   2755     }
   2756 
   2757     @Override
   2758     public void overridePendingAppTransitionAspectScaledThumb(GraphicBuffer srcThumb, int startX,
   2759             int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
   2760             boolean scaleUp) {
   2761         synchronized(mWindowMap) {
   2762             mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX, startY,
   2763                     targetWidth, targetHeight, startedCallback, scaleUp);
   2764         }
   2765     }
   2766 
   2767     @Override
   2768     public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
   2769             IRemoteCallback onAnimationStartedCallback, IRemoteCallback onAnimationFinishedCallback,
   2770             boolean scaleUp) {
   2771         synchronized (mWindowMap) {
   2772             mAppTransition.overridePendingAppTransitionMultiThumb(specs, onAnimationStartedCallback,
   2773                     onAnimationFinishedCallback, scaleUp);
   2774             prolongAnimationsFromSpecs(specs, scaleUp);
   2775 
   2776         }
   2777     }
   2778 
   2779     void prolongAnimationsFromSpecs(@NonNull AppTransitionAnimationSpec[] specs, boolean scaleUp) {
   2780         // This is used by freeform <-> recents windows transition. We need to synchronize
   2781         // the animation with the appearance of the content of recents, so we will make
   2782         // animation stay on the first or last frame a little longer.
   2783         mTmpTaskIds.clear();
   2784         for (int i = specs.length - 1; i >= 0; i--) {
   2785             mTmpTaskIds.put(specs[i].taskId, 0);
   2786         }
   2787         for (final WindowState win : mWindowMap.values()) {
   2788             final Task task = win.getTask();
   2789             if (task != null && mTmpTaskIds.get(task.mTaskId, -1) != -1
   2790                     && task.inFreeformWorkspace()) {
   2791                 final AppWindowToken appToken = win.mAppToken;
   2792                 if (appToken != null && appToken.mAppAnimator != null) {
   2793                     appToken.mAppAnimator.startProlongAnimation(scaleUp ?
   2794                             PROLONG_ANIMATION_AT_START : PROLONG_ANIMATION_AT_END);
   2795                 }
   2796             }
   2797         }
   2798     }
   2799 
   2800     @Override
   2801     public void overridePendingAppTransitionInPlace(String packageName, int anim) {
   2802         synchronized(mWindowMap) {
   2803             mAppTransition.overrideInPlaceAppTransition(packageName, anim);
   2804         }
   2805     }
   2806 
   2807     @Override
   2808     public void overridePendingAppTransitionMultiThumbFuture(
   2809             IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback,
   2810             boolean scaleUp) {
   2811         synchronized(mWindowMap) {
   2812             mAppTransition.overridePendingAppTransitionMultiThumbFuture(specsFuture, callback,
   2813                     scaleUp);
   2814         }
   2815     }
   2816 
   2817     @Override
   2818     public void endProlongedAnimations() {
   2819         synchronized (mWindowMap) {
   2820             for (final WindowState win : mWindowMap.values()) {
   2821                 final AppWindowToken appToken = win.mAppToken;
   2822                 if (appToken != null && appToken.mAppAnimator != null) {
   2823                     appToken.mAppAnimator.endProlongedAnimation();
   2824                 }
   2825             }
   2826             mAppTransition.notifyProlongedAnimationsEnded();
   2827         }
   2828     }
   2829 
   2830     @Override
   2831     public void executeAppTransition() {
   2832         if (!checkCallingPermission(MANAGE_APP_TOKENS, "executeAppTransition()")) {
   2833             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   2834         }
   2835 
   2836         synchronized(mWindowMap) {
   2837             if (DEBUG_APP_TRANSITIONS) Slog.w(TAG_WM, "Execute app transition: " + mAppTransition
   2838                     + " Callers=" + Debug.getCallers(5));
   2839             if (mAppTransition.isTransitionSet()) {
   2840                 mAppTransition.setReady();
   2841                 final long origId = Binder.clearCallingIdentity();
   2842                 try {
   2843                     mWindowPlacerLocked.performSurfacePlacement();
   2844                 } finally {
   2845                     Binder.restoreCallingIdentity(origId);
   2846                 }
   2847             }
   2848         }
   2849     }
   2850 
   2851     public void setAppFullscreen(IBinder token, boolean toOpaque) {
   2852         synchronized (mWindowMap) {
   2853             final AppWindowToken atoken = mRoot.getAppWindowToken(token);
   2854             if (atoken != null) {
   2855                 atoken.setFillsParent(toOpaque);
   2856                 setWindowOpaqueLocked(token, toOpaque);
   2857                 mWindowPlacerLocked.requestTraversal();
   2858             }
   2859         }
   2860     }
   2861 
   2862     public void setWindowOpaque(IBinder token, boolean isOpaque) {
   2863         synchronized (mWindowMap) {
   2864             setWindowOpaqueLocked(token, isOpaque);
   2865         }
   2866     }
   2867 
   2868     private void setWindowOpaqueLocked(IBinder token, boolean isOpaque) {
   2869         final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
   2870         if (wtoken != null) {
   2871             final WindowState win = wtoken.findMainWindow();
   2872             if (win != null) {
   2873                 win.mWinAnimator.setOpaqueLocked(isOpaque);
   2874             }
   2875         }
   2876     }
   2877 
   2878     void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) {
   2879         if (transit != TRANSIT_UNSET) {
   2880             if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
   2881                 wtoken.mAppAnimator.setNullAnimation();
   2882             }
   2883             applyAnimationLocked(wtoken, null, transit, false, false);
   2884         }
   2885     }
   2886 
   2887     public void setDockedStackCreateState(int mode, Rect bounds) {
   2888         synchronized (mWindowMap) {
   2889             setDockedStackCreateStateLocked(mode, bounds);
   2890         }
   2891     }
   2892 
   2893     void setDockedStackCreateStateLocked(int mode, Rect bounds) {
   2894         mDockedStackCreateMode = mode;
   2895         mDockedStackCreateBounds = bounds;
   2896     }
   2897 
   2898     public boolean isValidPictureInPictureAspectRatio(int displayId, float aspectRatio) {
   2899         final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
   2900         return displayContent.getPinnedStackController().isValidPictureInPictureAspectRatio(
   2901                 aspectRatio);
   2902     }
   2903 
   2904     @Override
   2905     public void getStackBounds(int stackId, Rect bounds) {
   2906         synchronized (mWindowMap) {
   2907             final TaskStack stack = mRoot.getStackById(stackId);
   2908             if (stack != null) {
   2909                 stack.getBounds(bounds);
   2910                 return;
   2911             }
   2912             bounds.setEmpty();
   2913         }
   2914     }
   2915 
   2916     @Override
   2917     public void notifyShowingDreamChanged() {
   2918         notifyKeyguardFlagsChanged(null /* callback */);
   2919     }
   2920 
   2921     @Override
   2922     public WindowManagerPolicy.WindowState getInputMethodWindowLw() {
   2923         return mInputMethodWindow;
   2924     }
   2925 
   2926     @Override
   2927     public void notifyKeyguardTrustedChanged() {
   2928         mH.sendEmptyMessage(H.NOTIFY_KEYGUARD_TRUSTED_CHANGED);
   2929     }
   2930 
   2931     @Override
   2932     public void screenTurningOff(ScreenOffListener listener) {
   2933         mTaskSnapshotController.screenTurningOff(listener);
   2934     }
   2935 
   2936     /**
   2937      * Starts deferring layout passes. Useful when doing multiple changes but to optimize
   2938      * performance, only one layout pass should be done. This can be called multiple times, and
   2939      * layouting will be resumed once the last caller has called {@link #continueSurfaceLayout}
   2940      */
   2941     public void deferSurfaceLayout() {
   2942         synchronized (mWindowMap) {
   2943             mWindowPlacerLocked.deferLayout();
   2944         }
   2945     }
   2946 
   2947     /**
   2948      * Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()}
   2949      */
   2950     public void continueSurfaceLayout() {
   2951         synchronized (mWindowMap) {
   2952             mWindowPlacerLocked.continueLayout();
   2953         }
   2954     }
   2955 
   2956     /**
   2957      * @return true if the activity contains windows that have
   2958      *         {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set
   2959      */
   2960     public boolean containsShowWhenLockedWindow(IBinder token) {
   2961         synchronized (mWindowMap) {
   2962             final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
   2963             return wtoken != null && wtoken.containsShowWhenLockedWindow();
   2964         }
   2965     }
   2966 
   2967     /**
   2968      * @return true if the activity contains windows that have
   2969      *         {@link LayoutParams#FLAG_DISMISS_KEYGUARD} set
   2970      */
   2971     public boolean containsDismissKeyguardWindow(IBinder token) {
   2972         synchronized (mWindowMap) {
   2973             final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
   2974             return wtoken != null && wtoken.containsDismissKeyguardWindow();
   2975         }
   2976     }
   2977 
   2978     /**
   2979      * Notifies activity manager that some Keyguard flags have changed and that it needs to
   2980      * reevaluate the visibilities of the activities.
   2981      * @param callback Runnable to be called when activity manager is done reevaluating visibilities
   2982      */
   2983     void notifyKeyguardFlagsChanged(@Nullable Runnable callback) {
   2984         final Runnable wrappedCallback = callback != null
   2985                 ? () -> { synchronized (mWindowMap) { callback.run(); } }
   2986                 : null;
   2987         mH.obtainMessage(H.NOTIFY_KEYGUARD_FLAGS_CHANGED, wrappedCallback).sendToTarget();
   2988     }
   2989 
   2990     public boolean isKeyguardTrusted() {
   2991         synchronized (mWindowMap) {
   2992             return mPolicy.isKeyguardTrustedLw();
   2993         }
   2994     }
   2995 
   2996     public void setKeyguardGoingAway(boolean keyguardGoingAway) {
   2997         synchronized (mWindowMap) {
   2998             mKeyguardGoingAway = keyguardGoingAway;
   2999         }
   3000     }
   3001 
   3002     // -------------------------------------------------------------
   3003     // Misc IWindowSession methods
   3004     // -------------------------------------------------------------
   3005 
   3006     @Override
   3007     public void startFreezingScreen(int exitAnim, int enterAnim) {
   3008         if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
   3009                 "startFreezingScreen()")) {
   3010             throw new SecurityException("Requires FREEZE_SCREEN permission");
   3011         }
   3012 
   3013         synchronized(mWindowMap) {
   3014             if (!mClientFreezingScreen) {
   3015                 mClientFreezingScreen = true;
   3016                 final long origId = Binder.clearCallingIdentity();
   3017                 try {
   3018                     startFreezingDisplayLocked(false, exitAnim, enterAnim);
   3019                     mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
   3020                     mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
   3021                 } finally {
   3022                     Binder.restoreCallingIdentity(origId);
   3023                 }
   3024             }
   3025         }
   3026     }
   3027 
   3028     @Override
   3029     public void stopFreezingScreen() {
   3030         if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
   3031                 "stopFreezingScreen()")) {
   3032             throw new SecurityException("Requires FREEZE_SCREEN permission");
   3033         }
   3034 
   3035         synchronized(mWindowMap) {
   3036             if (mClientFreezingScreen) {
   3037                 mClientFreezingScreen = false;
   3038                 mLastFinishedFreezeSource = "client";
   3039                 final long origId = Binder.clearCallingIdentity();
   3040                 try {
   3041                     stopFreezingDisplayLocked();
   3042                 } finally {
   3043                     Binder.restoreCallingIdentity(origId);
   3044                 }
   3045             }
   3046         }
   3047     }
   3048 
   3049     @Override
   3050     public void disableKeyguard(IBinder token, String tag) {
   3051         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
   3052             != PackageManager.PERMISSION_GRANTED) {
   3053             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
   3054         }
   3055         // If this isn't coming from the system then don't allow disabling the lockscreen
   3056         // to bypass security.
   3057         if (Binder.getCallingUid() != SYSTEM_UID && isKeyguardSecure()) {
   3058             Log.d(TAG_WM, "current mode is SecurityMode, ignore disableKeyguard");
   3059             return;
   3060         }
   3061 
   3062         // If this isn't coming from the current profiles, ignore it.
   3063         if (!isCurrentProfileLocked(UserHandle.getCallingUserId())) {
   3064             Log.d(TAG_WM, "non-current profiles, ignore disableKeyguard");
   3065             return;
   3066         }
   3067 
   3068         if (token == null) {
   3069             throw new IllegalArgumentException("token == null");
   3070         }
   3071 
   3072         mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
   3073                 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
   3074     }
   3075 
   3076     @Override
   3077     public void reenableKeyguard(IBinder token) {
   3078         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
   3079             != PackageManager.PERMISSION_GRANTED) {
   3080             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
   3081         }
   3082 
   3083         if (token == null) {
   3084             throw new IllegalArgumentException("token == null");
   3085         }
   3086 
   3087         mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
   3088                 KeyguardDisableHandler.KEYGUARD_REENABLE, token));
   3089     }
   3090 
   3091     /**
   3092      * @see android.app.KeyguardManager#exitKeyguardSecurely
   3093      */
   3094     @Override
   3095     public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
   3096         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
   3097             != PackageManager.PERMISSION_GRANTED) {
   3098             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
   3099         }
   3100 
   3101         if (callback == null) {
   3102             throw new IllegalArgumentException("callback == null");
   3103         }
   3104 
   3105         mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
   3106             @Override
   3107             public void onKeyguardExitResult(boolean success) {
   3108                 try {
   3109                     callback.onKeyguardExitResult(success);
   3110                 } catch (RemoteException e) {
   3111                     // Client has died, we don't care.
   3112                 }
   3113             }
   3114         });
   3115     }
   3116 
   3117     @Override
   3118     public boolean inKeyguardRestrictedInputMode() {
   3119         return mPolicy.inKeyguardRestrictedKeyInputMode();
   3120     }
   3121 
   3122     @Override
   3123     public boolean isKeyguardLocked() {
   3124         return mPolicy.isKeyguardLocked();
   3125     }
   3126 
   3127     public boolean isKeyguardShowingAndNotOccluded() {
   3128         return mPolicy.isKeyguardShowingAndNotOccluded();
   3129     }
   3130 
   3131     @Override
   3132     public boolean isKeyguardSecure() {
   3133         int userId = UserHandle.getCallingUserId();
   3134         long origId = Binder.clearCallingIdentity();
   3135         try {
   3136             return mPolicy.isKeyguardSecure(userId);
   3137         } finally {
   3138             Binder.restoreCallingIdentity(origId);
   3139         }
   3140     }
   3141 
   3142     public boolean isShowingDream() {
   3143         synchronized (mWindowMap) {
   3144             return mPolicy.isShowingDreamLw();
   3145         }
   3146     }
   3147 
   3148     @Override
   3149     public void dismissKeyguard(IKeyguardDismissCallback callback) {
   3150         checkCallingPermission(permission.CONTROL_KEYGUARD, "dismissKeyguard");
   3151         synchronized(mWindowMap) {
   3152             mPolicy.dismissKeyguardLw(callback);
   3153         }
   3154     }
   3155 
   3156     public void onKeyguardOccludedChanged(boolean occluded) {
   3157         synchronized (mWindowMap) {
   3158             mPolicy.onKeyguardOccludedChangedLw(occluded);
   3159         }
   3160     }
   3161 
   3162     @Override
   3163     public void setSwitchingUser(boolean switching) {
   3164         if (!checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
   3165                 "setSwitchingUser()")) {
   3166             throw new SecurityException("Requires INTERACT_ACROSS_USERS_FULL permission");
   3167         }
   3168         mPolicy.setSwitchingUser(switching);
   3169         synchronized (mWindowMap) {
   3170             mSwitchingUser = switching;
   3171         }
   3172     }
   3173 
   3174     void showGlobalActions() {
   3175         mPolicy.showGlobalActions();
   3176     }
   3177 
   3178     @Override
   3179     public void closeSystemDialogs(String reason) {
   3180         synchronized(mWindowMap) {
   3181             mRoot.closeSystemDialogs(reason);
   3182         }
   3183     }
   3184 
   3185     static float fixScale(float scale) {
   3186         if (scale < 0) scale = 0;
   3187         else if (scale > 20) scale = 20;
   3188         return Math.abs(scale);
   3189     }
   3190 
   3191     @Override
   3192     public void setAnimationScale(int which, float scale) {
   3193         if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
   3194                 "setAnimationScale()")) {
   3195             throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
   3196         }
   3197 
   3198         scale = fixScale(scale);
   3199         switch (which) {
   3200             case 0: mWindowAnimationScaleSetting = scale; break;
   3201             case 1: mTransitionAnimationScaleSetting = scale; break;
   3202             case 2: mAnimatorDurationScaleSetting = scale; break;
   3203         }
   3204 
   3205         // Persist setting
   3206         mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
   3207     }
   3208 
   3209     @Override
   3210     public void setAnimationScales(float[] scales) {
   3211         if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
   3212                 "setAnimationScale()")) {
   3213             throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
   3214         }
   3215 
   3216         if (scales != null) {
   3217             if (scales.length >= 1) {
   3218                 mWindowAnimationScaleSetting = fixScale(scales[0]);
   3219             }
   3220             if (scales.length >= 2) {
   3221                 mTransitionAnimationScaleSetting = fixScale(scales[1]);
   3222             }
   3223             if (scales.length >= 3) {
   3224                 mAnimatorDurationScaleSetting = fixScale(scales[2]);
   3225                 dispatchNewAnimatorScaleLocked(null);
   3226             }
   3227         }
   3228 
   3229         // Persist setting
   3230         mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
   3231     }
   3232 
   3233     private void setAnimatorDurationScale(float scale) {
   3234         mAnimatorDurationScaleSetting = scale;
   3235         ValueAnimator.setDurationScale(scale);
   3236     }
   3237 
   3238     public float getWindowAnimationScaleLocked() {
   3239         return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting;
   3240     }
   3241 
   3242     public float getTransitionAnimationScaleLocked() {
   3243         return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting;
   3244     }
   3245 
   3246     @Override
   3247     public float getAnimationScale(int which) {
   3248         switch (which) {
   3249             case 0: return mWindowAnimationScaleSetting;
   3250             case 1: return mTransitionAnimationScaleSetting;
   3251             case 2: return mAnimatorDurationScaleSetting;
   3252         }
   3253         return 0;
   3254     }
   3255 
   3256     @Override
   3257     public float[] getAnimationScales() {
   3258         return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting,
   3259                 mAnimatorDurationScaleSetting };
   3260     }
   3261 
   3262     @Override
   3263     public float getCurrentAnimatorScale() {
   3264         synchronized(mWindowMap) {
   3265             return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting;
   3266         }
   3267     }
   3268 
   3269     void dispatchNewAnimatorScaleLocked(Session session) {
   3270         mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget();
   3271     }
   3272 
   3273     @Override
   3274     public void registerPointerEventListener(PointerEventListener listener) {
   3275         mPointerEventDispatcher.registerInputEventListener(listener);
   3276     }
   3277 
   3278     @Override
   3279     public void unregisterPointerEventListener(PointerEventListener listener) {
   3280         mPointerEventDispatcher.unregisterInputEventListener(listener);
   3281     }
   3282 
   3283     /** Check if the service is set to dispatch pointer events. */
   3284     boolean canDispatchPointerEvents() {
   3285         return mPointerEventDispatcher != null;
   3286     }
   3287 
   3288     // Called by window manager policy. Not exposed externally.
   3289     @Override
   3290     public int getLidState() {
   3291         int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
   3292                 InputManagerService.SW_LID);
   3293         if (sw > 0) {
   3294             // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
   3295             return LID_CLOSED;
   3296         } else if (sw == 0) {
   3297             // Switch state: AKEY_STATE_UP.
   3298             return LID_OPEN;
   3299         } else {
   3300             // Switch state: AKEY_STATE_UNKNOWN.
   3301             return LID_ABSENT;
   3302         }
   3303     }
   3304 
   3305     // Called by window manager policy. Not exposed externally.
   3306     @Override
   3307     public void lockDeviceNow() {
   3308         lockNow(null);
   3309     }
   3310 
   3311     // Called by window manager policy. Not exposed externally.
   3312     @Override
   3313     public int getCameraLensCoverState() {
   3314         int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
   3315                 InputManagerService.SW_CAMERA_LENS_COVER);
   3316         if (sw > 0) {
   3317             // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
   3318             return CAMERA_LENS_COVERED;
   3319         } else if (sw == 0) {
   3320             // Switch state: AKEY_STATE_UP.
   3321             return CAMERA_LENS_UNCOVERED;
   3322         } else {
   3323             // Switch state: AKEY_STATE_UNKNOWN.
   3324             return CAMERA_LENS_COVER_ABSENT;
   3325         }
   3326     }
   3327 
   3328     // Called by window manager policy.  Not exposed externally.
   3329     @Override
   3330     public void switchInputMethod(boolean forwardDirection) {
   3331         final InputMethodManagerInternal inputMethodManagerInternal =
   3332                 LocalServices.getService(InputMethodManagerInternal.class);
   3333         if (inputMethodManagerInternal != null) {
   3334             inputMethodManagerInternal.switchInputMethod(forwardDirection);
   3335         }
   3336     }
   3337 
   3338     // Called by window manager policy.  Not exposed externally.
   3339     @Override
   3340     public void shutdown(boolean confirm) {
   3341         // Pass in the UI context, since ShutdownThread requires it (to show UI).
   3342         ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(),
   3343                 PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
   3344     }
   3345 
   3346     // Called by window manager policy.  Not exposed externally.
   3347     @Override
   3348     public void reboot(boolean confirm) {
   3349         // Pass in the UI context, since ShutdownThread requires it (to show UI).
   3350         ShutdownThread.reboot(ActivityThread.currentActivityThread().getSystemUiContext(),
   3351                 PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
   3352     }
   3353 
   3354     // Called by window manager policy.  Not exposed externally.
   3355     @Override
   3356     public void rebootSafeMode(boolean confirm) {
   3357         // Pass in the UI context, since ShutdownThread requires it (to show UI).
   3358         ShutdownThread.rebootSafeMode(ActivityThread.currentActivityThread().getSystemUiContext(),
   3359                 confirm);
   3360     }
   3361 
   3362     public void setCurrentProfileIds(final int[] currentProfileIds) {
   3363         synchronized (mWindowMap) {
   3364             mCurrentProfileIds = currentProfileIds;
   3365         }
   3366     }
   3367 
   3368     public void setCurrentUser(final int newUserId, final int[] currentProfileIds) {
   3369         synchronized (mWindowMap) {
   3370             mCurrentUserId = newUserId;
   3371             mCurrentProfileIds = currentProfileIds;
   3372             mAppTransition.setCurrentUser(newUserId);
   3373             mPolicy.setCurrentUserLw(newUserId);
   3374 
   3375             // If keyguard was disabled, re-enable it
   3376             // TODO: Keep track of keyguardEnabled state per user and use here...
   3377             // e.g. enabled = mKeyguardDisableHandler.getEnabledStateForUser(newUserId);
   3378             mPolicy.enableKeyguard(true);
   3379 
   3380             // Hide windows that should not be seen by the new user.
   3381             mRoot.switchUser();
   3382             mWindowPlacerLocked.performSurfacePlacement();
   3383 
   3384             // Notify whether the docked stack exists for the current user
   3385             final DisplayContent displayContent = getDefaultDisplayContentLocked();
   3386             final TaskStack stack = displayContent.getDockedStackIgnoringVisibility();
   3387             displayContent.mDividerControllerLocked.notifyDockedStackExistsChanged(
   3388                     stack != null && stack.hasTaskForUser(newUserId));
   3389 
   3390             // If the display is already prepared, update the density.
   3391             // Otherwise, we'll update it when it's prepared.
   3392             if (mDisplayReady) {
   3393                 final int forcedDensity = getForcedDisplayDensityForUserLocked(newUserId);
   3394                 final int targetDensity = forcedDensity != 0 ? forcedDensity
   3395                         : displayContent.mInitialDisplayDensity;
   3396                 setForcedDisplayDensityLocked(displayContent, targetDensity);
   3397             }
   3398         }
   3399     }
   3400 
   3401     /* Called by WindowState */
   3402     boolean isCurrentProfileLocked(int userId) {
   3403         if (userId == mCurrentUserId) return true;
   3404         for (int i = 0; i < mCurrentProfileIds.length; i++) {
   3405             if (mCurrentProfileIds[i] == userId) return true;
   3406         }
   3407         return false;
   3408     }
   3409 
   3410     public void enableScreenAfterBoot() {
   3411         synchronized(mWindowMap) {
   3412             if (DEBUG_BOOT) {
   3413                 RuntimeException here = new RuntimeException("here");
   3414                 here.fillInStackTrace();
   3415                 Slog.i(TAG_WM, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
   3416                         + " mForceDisplayEnabled=" + mForceDisplayEnabled
   3417                         + " mShowingBootMessages=" + mShowingBootMessages
   3418                         + " mSystemBooted=" + mSystemBooted, here);
   3419             }
   3420             if (mSystemBooted) {
   3421                 return;
   3422             }
   3423             mSystemBooted = true;
   3424             hideBootMessagesLocked();
   3425             // If the screen still doesn't come up after 30 seconds, give
   3426             // up and turn it on.
   3427             mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30 * 1000);
   3428         }
   3429 
   3430         mPolicy.systemBooted();
   3431 
   3432         performEnableScreen();
   3433     }
   3434 
   3435     @Override
   3436     public void enableScreenIfNeeded() {
   3437         synchronized (mWindowMap) {
   3438             enableScreenIfNeededLocked();
   3439         }
   3440     }
   3441 
   3442     void enableScreenIfNeededLocked() {
   3443         if (DEBUG_BOOT) {
   3444             RuntimeException here = new RuntimeException("here");
   3445             here.fillInStackTrace();
   3446             Slog.i(TAG_WM, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
   3447                     + " mForceDisplayEnabled=" + mForceDisplayEnabled
   3448                     + " mShowingBootMessages=" + mShowingBootMessages
   3449                     + " mSystemBooted=" + mSystemBooted, here);
   3450         }
   3451         if (mDisplayEnabled) {
   3452             return;
   3453         }
   3454         if (!mSystemBooted && !mShowingBootMessages) {
   3455             return;
   3456         }
   3457         mH.sendEmptyMessage(H.ENABLE_SCREEN);
   3458     }
   3459 
   3460     public void performBootTimeout() {
   3461         synchronized(mWindowMap) {
   3462             if (mDisplayEnabled) {
   3463                 return;
   3464             }
   3465             Slog.w(TAG_WM, "***** BOOT TIMEOUT: forcing display enabled");
   3466             mForceDisplayEnabled = true;
   3467         }
   3468         performEnableScreen();
   3469     }
   3470 
   3471     /**
   3472      * Called when System UI has been started.
   3473      */
   3474     public void onSystemUiStarted() {
   3475         mPolicy.onSystemUiStarted();
   3476     }
   3477 
   3478     private void performEnableScreen() {
   3479         synchronized(mWindowMap) {
   3480             if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
   3481                     + " mForceDisplayEnabled=" + mForceDisplayEnabled
   3482                     + " mShowingBootMessages=" + mShowingBootMessages
   3483                     + " mSystemBooted=" + mSystemBooted
   3484                     + " mOnlyCore=" + mOnlyCore,
   3485                     new RuntimeException("here").fillInStackTrace());
   3486             if (mDisplayEnabled) {
   3487                 return;
   3488             }
   3489             if (!mSystemBooted && !mShowingBootMessages) {
   3490                 return;
   3491             }
   3492 
   3493             if (!mShowingBootMessages && !mPolicy.canDismissBootAnimation()) {
   3494                 return;
   3495             }
   3496 
   3497             // Don't enable the screen until all existing windows have been drawn.
   3498             if (!mForceDisplayEnabled
   3499                     // TODO(multidisplay): Expand to all displays?
   3500                     && getDefaultDisplayContentLocked().checkWaitingForWindows()) {
   3501                 return;
   3502             }
   3503 
   3504             if (!mBootAnimationStopped) {
   3505                 Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
   3506                 // stop boot animation
   3507                 // formerly we would just kill the process, but we now ask it to exit so it
   3508                 // can choose where to stop the animation.
   3509                 SystemProperties.set("service.bootanim.exit", "1");
   3510                 mBootAnimationStopped = true;
   3511             }
   3512 
   3513             if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {
   3514                 if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: Waiting for anim complete");
   3515                 return;
   3516             }
   3517 
   3518             try {
   3519                 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
   3520                 if (surfaceFlinger != null) {
   3521                     Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
   3522                     Parcel data = Parcel.obtain();
   3523                     data.writeInterfaceToken("android.ui.ISurfaceComposer");
   3524                     surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
   3525                             data, null, 0);
   3526                     data.recycle();
   3527                 }
   3528             } catch (RemoteException ex) {
   3529                 Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!");
   3530             }
   3531 
   3532             EventLog.writeEvent(EventLogTags.WM_BOOT_ANIMATION_DONE, SystemClock.uptimeMillis());
   3533             Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
   3534             mDisplayEnabled = true;
   3535             if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, "******************** ENABLING SCREEN!");
   3536 
   3537             // Enable input dispatch.
   3538             mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
   3539         }
   3540 
   3541         try {
   3542             mActivityManager.bootAnimationComplete();
   3543         } catch (RemoteException e) {
   3544         }
   3545 
   3546         mPolicy.enableScreenAfterBoot();
   3547 
   3548         // Make sure the last requested orientation has been applied.
   3549         updateRotationUnchecked(false, false);
   3550     }
   3551 
   3552     private boolean checkBootAnimationCompleteLocked() {
   3553         if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) {
   3554             mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED);
   3555             mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED,
   3556                     BOOT_ANIMATION_POLL_INTERVAL);
   3557             if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Waiting for anim complete");
   3558             return false;
   3559         }
   3560         if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Animation complete!");
   3561         return true;
   3562     }
   3563 
   3564     public void showBootMessage(final CharSequence msg, final boolean always) {
   3565         boolean first = false;
   3566         synchronized(mWindowMap) {
   3567             if (DEBUG_BOOT) {
   3568                 RuntimeException here = new RuntimeException("here");
   3569                 here.fillInStackTrace();
   3570                 Slog.i(TAG_WM, "showBootMessage: msg=" + msg + " always=" + always
   3571                         + " mAllowBootMessages=" + mAllowBootMessages
   3572                         + " mShowingBootMessages=" + mShowingBootMessages
   3573                         + " mSystemBooted=" + mSystemBooted, here);
   3574             }
   3575             if (!mAllowBootMessages) {
   3576                 return;
   3577             }
   3578             if (!mShowingBootMessages) {
   3579                 if (!always) {
   3580                     return;
   3581                 }
   3582                 first = true;
   3583             }
   3584             if (mSystemBooted) {
   3585                 return;
   3586             }
   3587             mShowingBootMessages = true;
   3588             mPolicy.showBootMessage(msg, always);
   3589         }
   3590         if (first) {
   3591             performEnableScreen();
   3592         }
   3593     }
   3594 
   3595     public void hideBootMessagesLocked() {
   3596         if (DEBUG_BOOT) {
   3597             RuntimeException here = new RuntimeException("here");
   3598             here.fillInStackTrace();
   3599             Slog.i(TAG_WM, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
   3600                     + " mForceDisplayEnabled=" + mForceDisplayEnabled
   3601                     + " mShowingBootMessages=" + mShowingBootMessages
   3602                     + " mSystemBooted=" + mSystemBooted, here);
   3603         }
   3604         if (mShowingBootMessages) {
   3605             mShowingBootMessages = false;
   3606             mPolicy.hideBootMessages();
   3607         }
   3608     }
   3609 
   3610     @Override
   3611     public void setInTouchMode(boolean mode) {
   3612         synchronized(mWindowMap) {
   3613             mInTouchMode = mode;
   3614         }
   3615     }
   3616 
   3617     private void updateCircularDisplayMaskIfNeeded() {
   3618         if (mContext.getResources().getConfiguration().isScreenRound()
   3619                 && mContext.getResources().getBoolean(
   3620                 com.android.internal.R.bool.config_windowShowCircularMask)) {
   3621             final int currentUserId;
   3622             synchronized(mWindowMap) {
   3623                 currentUserId = mCurrentUserId;
   3624             }
   3625             // Device configuration calls for a circular display mask, but we only enable the mask
   3626             // if the accessibility color inversion feature is disabled, as the inverted mask
   3627             // causes artifacts.
   3628             int inversionState = Settings.Secure.getIntForUser(mContext.getContentResolver(),
   3629                     Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, currentUserId);
   3630             int showMask = (inversionState == 1) ? 0 : 1;
   3631             Message m = mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK);
   3632             m.arg1 = showMask;
   3633             mH.sendMessage(m);
   3634         }
   3635     }
   3636 
   3637     public void showEmulatorDisplayOverlayIfNeeded() {
   3638         if (mContext.getResources().getBoolean(
   3639                 com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay)
   3640                 && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false)
   3641                 && Build.IS_EMULATOR) {
   3642             mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY));
   3643         }
   3644     }
   3645 
   3646     public void showCircularMask(boolean visible) {
   3647         synchronized(mWindowMap) {
   3648 
   3649             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
   3650                     ">>> OPEN TRANSACTION showCircularMask(visible=" + visible + ")");
   3651             openSurfaceTransaction();
   3652             try {
   3653                 if (visible) {
   3654                     // TODO(multi-display): support multiple displays
   3655                     if (mCircularDisplayMask == null) {
   3656                         int screenOffset = mContext.getResources().getInteger(
   3657                                 com.android.internal.R.integer.config_windowOutsetBottom);
   3658                         int maskThickness = mContext.getResources().getDimensionPixelSize(
   3659                                 com.android.internal.R.dimen.circular_display_mask_thickness);
   3660 
   3661                         mCircularDisplayMask = new CircularDisplayMask(
   3662                                 getDefaultDisplayContentLocked().getDisplay(),
   3663                                 mFxSession,
   3664                                 mPolicy.getWindowLayerFromTypeLw(
   3665                                         WindowManager.LayoutParams.TYPE_POINTER)
   3666                                         * TYPE_LAYER_MULTIPLIER + 10, screenOffset, maskThickness);
   3667                     }
   3668                     mCircularDisplayMask.setVisibility(true);
   3669                 } else if (mCircularDisplayMask != null) {
   3670                     mCircularDisplayMask.setVisibility(false);
   3671                     mCircularDisplayMask = null;
   3672                 }
   3673             } finally {
   3674                 closeSurfaceTransaction();
   3675                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
   3676                         "<<< CLOSE TRANSACTION showCircularMask(visible=" + visible + ")");
   3677             }
   3678         }
   3679     }
   3680 
   3681     public void showEmulatorDisplayOverlay() {
   3682         synchronized(mWindowMap) {
   3683 
   3684             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
   3685                     ">>> OPEN TRANSACTION showEmulatorDisplayOverlay");
   3686             openSurfaceTransaction();
   3687             try {
   3688                 if (mEmulatorDisplayOverlay == null) {
   3689                     mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(
   3690                             mContext,
   3691                             getDefaultDisplayContentLocked().getDisplay(),
   3692                             mFxSession,
   3693                             mPolicy.getWindowLayerFromTypeLw(
   3694                                     WindowManager.LayoutParams.TYPE_POINTER)
   3695                                     * TYPE_LAYER_MULTIPLIER + 10);
   3696                 }
   3697                 mEmulatorDisplayOverlay.setVisibility(true);
   3698             } finally {
   3699                 closeSurfaceTransaction();
   3700                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
   3701                         "<<< CLOSE TRANSACTION showEmulatorDisplayOverlay");
   3702             }
   3703         }
   3704     }
   3705 
   3706     // TODO: more accounting of which pid(s) turned it on, keep count,
   3707     // only allow disables from pids which have count on, etc.
   3708     @Override
   3709     public void showStrictModeViolation(boolean on) {
   3710         final int pid = Binder.getCallingPid();
   3711         if (on) {
   3712             // Show the visualization, and enqueue a second message to tear it
   3713             // down if we don't hear back from the app.
   3714             mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 1, pid));
   3715             mH.sendMessageDelayed(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid),
   3716                     DateUtils.SECOND_IN_MILLIS);
   3717         } else {
   3718             mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid));
   3719         }
   3720     }
   3721 
   3722     private void showStrictModeViolation(int arg, int pid) {
   3723         final boolean on = arg != 0;
   3724         synchronized(mWindowMap) {
   3725             // Ignoring requests to enable the red border from clients which aren't on screen.
   3726             // (e.g. Broadcast Receivers in the background..)
   3727             if (on && !mRoot.canShowStrictModeViolation(pid)) {
   3728                 return;
   3729             }
   3730 
   3731             if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
   3732                     ">>> OPEN TRANSACTION showStrictModeViolation");
   3733             // TODO: Modify this to use the surface trace once it is not going crazy.
   3734             // b/31532461
   3735             SurfaceControl.openTransaction();
   3736             try {
   3737                 // TODO(multi-display): support multiple displays
   3738                 if (mStrictModeFlash == null) {
   3739                     mStrictModeFlash = new StrictModeFlash(
   3740                             getDefaultDisplayContentLocked().getDisplay(), mFxSession);
   3741                 }
   3742                 mStrictModeFlash.setVisibility(on);
   3743             } finally {
   3744                 SurfaceControl.closeTransaction();
   3745                 if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
   3746                         "<<< CLOSE TRANSACTION showStrictModeViolation");
   3747             }
   3748         }
   3749     }
   3750 
   3751     @Override
   3752     public void setStrictModeVisualIndicatorPreference(String value) {
   3753         SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
   3754     }
   3755 
   3756     @Override
   3757     public Bitmap screenshotWallpaper() {
   3758         if (!checkCallingPermission(READ_FRAME_BUFFER,
   3759                 "screenshotWallpaper()")) {
   3760             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
   3761         }
   3762         try {
   3763             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper");
   3764             return screenshotApplications(null /* appToken */, DEFAULT_DISPLAY, -1 /* width */,
   3765                     -1 /* height */, true /* includeFullDisplay */, 1f /* frameScale */,
   3766                     Bitmap.Config.ARGB_8888, true /* wallpaperOnly */, false /* includeDecor */);
   3767         } finally {
   3768             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
   3769         }
   3770     }
   3771 
   3772     /**
   3773      * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
   3774      * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
   3775      * of the target image.
   3776      */
   3777     @Override
   3778     public boolean requestAssistScreenshot(final IAssistScreenshotReceiver receiver) {
   3779         if (!checkCallingPermission(READ_FRAME_BUFFER,
   3780                 "requestAssistScreenshot()")) {
   3781             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
   3782         }
   3783 
   3784         FgThread.getHandler().post(() -> {
   3785             Bitmap bm = screenshotApplications(null /* appToken */, DEFAULT_DISPLAY,
   3786                     -1 /* width */, -1 /* height */, true /* includeFullDisplay */,
   3787                     1f /* frameScale */, Bitmap.Config.ARGB_8888, false /* wallpaperOnly */,
   3788                     false /* includeDecor */);
   3789             try {
   3790                 receiver.send(bm);
   3791             } catch (RemoteException e) {
   3792             }
   3793         });
   3794 
   3795         return true;
   3796     }
   3797 
   3798     public TaskSnapshot getTaskSnapshot(int taskId, int userId, boolean reducedResolution) {
   3799         return mTaskSnapshotController.getSnapshot(taskId, userId, true /* restoreFromDisk */,
   3800                 reducedResolution);
   3801     }
   3802 
   3803     /**
   3804      * In case a task write/delete operation was lost because the system crashed, this makes sure to
   3805      * clean up the directory to remove obsolete files.
   3806      *
   3807      * @param persistentTaskIds A set of task ids that exist in our in-memory model.
   3808      * @param runningUserIds The ids of the list of users that have tasks loaded in our in-memory
   3809      *                       model.
   3810      */
   3811     public void removeObsoleteTaskFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds) {
   3812         synchronized (mWindowMap) {
   3813             mTaskSnapshotController.removeObsoleteTaskFiles(persistentTaskIds, runningUserIds);
   3814         }
   3815     }
   3816 
   3817     /**
   3818      * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
   3819      * In portrait mode, it grabs the full screenshot.
   3820      *
   3821      * @param displayId the Display to take a screenshot of.
   3822      * @param width the width of the target bitmap
   3823      * @param height the height of the target bitmap
   3824      * @param includeFullDisplay true if the screen should not be cropped before capture
   3825      * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
   3826      * @param config of the output bitmap
   3827      * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
   3828      * @param includeDecor whether to include window decors, like the status or navigation bar
   3829      *                     background of the window
   3830      */
   3831     private Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
   3832             int height, boolean includeFullDisplay, float frameScale, Bitmap.Config config,
   3833             boolean wallpaperOnly, boolean includeDecor) {
   3834         final DisplayContent displayContent;
   3835         synchronized(mWindowMap) {
   3836             displayContent = mRoot.getDisplayContentOrCreate(displayId);
   3837             if (displayContent == null) {
   3838                 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
   3839                         + ": returning null. No Display for displayId=" + displayId);
   3840                 return null;
   3841             }
   3842         }
   3843         return displayContent.screenshotApplications(appToken, width, height,
   3844                 includeFullDisplay, frameScale, config, wallpaperOnly, includeDecor);
   3845     }
   3846 
   3847     /**
   3848      * Freeze rotation changes.  (Enable "rotation lock".)
   3849      * Persists across reboots.
   3850      * @param rotation The desired rotation to freeze to, or -1 to use the
   3851      * current rotation.
   3852      */
   3853     @Override
   3854     public void freezeRotation(int rotation) {
   3855         // TODO(multi-display): Track which display is rotated.
   3856         if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
   3857                 "freezeRotation()")) {
   3858             throw new SecurityException("Requires SET_ORIENTATION permission");
   3859         }
   3860         if (rotation < -1 || rotation > Surface.ROTATION_270) {
   3861             throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
   3862                     + "rotation constant.");
   3863         }
   3864 
   3865         final int defaultDisplayRotation = getDefaultDisplayRotation();
   3866         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "freezeRotation: mRotation="
   3867                 + defaultDisplayRotation);
   3868 
   3869         long origId = Binder.clearCallingIdentity();
   3870         try {
   3871             mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
   3872                     rotation == -1 ? defaultDisplayRotation : rotation);
   3873         } finally {
   3874             Binder.restoreCallingIdentity(origId);
   3875         }
   3876 
   3877         updateRotationUnchecked(false, false);
   3878     }
   3879 
   3880     /**
   3881      * Thaw rotation changes.  (Disable "rotation lock".)
   3882      * Persists across reboots.
   3883      */
   3884     @Override
   3885     public void thawRotation() {
   3886         if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
   3887                 "thawRotation()")) {
   3888             throw new SecurityException("Requires SET_ORIENTATION permission");
   3889         }
   3890 
   3891         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "thawRotation: mRotation="
   3892                 + getDefaultDisplayRotation());
   3893 
   3894         long origId = Binder.clearCallingIdentity();
   3895         try {
   3896             mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
   3897                     777); // rot not used
   3898         } finally {
   3899             Binder.restoreCallingIdentity(origId);
   3900         }
   3901 
   3902         updateRotationUnchecked(false, false);
   3903     }
   3904 
   3905     /**
   3906      * Recalculate the current rotation.
   3907      *
   3908      * Called by the window manager policy whenever the state of the system changes
   3909      * such that the current rotation might need to be updated, such as when the
   3910      * device is docked or rotated into a new posture.
   3911      */
   3912     @Override
   3913     public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
   3914         updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
   3915     }
   3916 
   3917     /**
   3918      * Temporarily pauses rotation changes until resumed.
   3919      *
   3920      * This can be used to prevent rotation changes from occurring while the user is
   3921      * performing certain operations, such as drag and drop.
   3922      *
   3923      * This call nests and must be matched by an equal number of calls to
   3924      * {@link #resumeRotationLocked}.
   3925      */
   3926     void pauseRotationLocked() {
   3927         mDeferredRotationPauseCount += 1;
   3928     }
   3929 
   3930     /**
   3931      * Resumes normal rotation changes after being paused.
   3932      */
   3933     void resumeRotationLocked() {
   3934         if (mDeferredRotationPauseCount > 0) {
   3935             mDeferredRotationPauseCount -= 1;
   3936             if (mDeferredRotationPauseCount == 0) {
   3937                 // TODO(multi-display): Update rotation for different displays separately.
   3938                 final DisplayContent displayContent = getDefaultDisplayContentLocked();
   3939                 final boolean changed = displayContent.updateRotationUnchecked(
   3940                         false /* inTransaction */);
   3941                 if (changed) {
   3942                     mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
   3943                             .sendToTarget();
   3944                 }
   3945             }
   3946         }
   3947     }
   3948 
   3949     private void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
   3950         if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked:"
   3951                 + " alwaysSendConfiguration=" + alwaysSendConfiguration
   3952                 + " forceRelayout=" + forceRelayout);
   3953 
   3954         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation");
   3955 
   3956         long origId = Binder.clearCallingIdentity();
   3957 
   3958         try {
   3959             // TODO(multi-display): Update rotation for different displays separately.
   3960             final boolean rotationChanged;
   3961             final int displayId;
   3962             synchronized (mWindowMap) {
   3963                 final DisplayContent displayContent = getDefaultDisplayContentLocked();
   3964                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display");
   3965                 rotationChanged = displayContent.updateRotationUnchecked(
   3966                         false /* inTransaction */);
   3967                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
   3968                 if (!rotationChanged || forceRelayout) {
   3969                     displayContent.setLayoutNeeded();
   3970                     Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
   3971                             "updateRotation: performSurfacePlacement");
   3972                     mWindowPlacerLocked.performSurfacePlacement();
   3973                     Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
   3974                 }
   3975                 displayId = displayContent.getDisplayId();
   3976             }
   3977 
   3978             if (rotationChanged || alwaysSendConfiguration) {
   3979                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: sendNewConfiguration");
   3980                 sendNewConfiguration(displayId);
   3981                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
   3982             }
   3983         } finally {
   3984             Binder.restoreCallingIdentity(origId);
   3985             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
   3986         }
   3987     }
   3988 
   3989     @Override
   3990     public int getDefaultDisplayRotation() {
   3991         synchronized (mWindowMap) {
   3992             return getDefaultDisplayContentLocked().getRotation();
   3993         }
   3994     }
   3995 
   3996     @Override
   3997     public boolean isRotationFrozen() {
   3998         return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
   3999     }
   4000 
   4001     @Override
   4002     public int watchRotation(IRotationWatcher watcher, int displayId) {
   4003         final IBinder watcherBinder = watcher.asBinder();
   4004         IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
   4005             @Override
   4006             public void binderDied() {
   4007                 synchronized (mWindowMap) {
   4008                     for (int i=0; i<mRotationWatchers.size(); i++) {
   4009                         if (watcherBinder == mRotationWatchers.get(i).mWatcher.asBinder()) {
   4010                             RotationWatcher removed = mRotationWatchers.remove(i);
   4011                             IBinder binder = removed.mWatcher.asBinder();
   4012                             if (binder != null) {
   4013                                 binder.unlinkToDeath(this, 0);
   4014                             }
   4015                             i--;
   4016                         }
   4017                     }
   4018                 }
   4019             }
   4020         };
   4021 
   4022         synchronized (mWindowMap) {
   4023             try {
   4024                 watcher.asBinder().linkToDeath(dr, 0);
   4025                 mRotationWatchers.add(new RotationWatcher(watcher, dr, displayId));
   4026             } catch (RemoteException e) {
   4027                 // Client died, no cleanup needed.
   4028             }
   4029 
   4030             return getDefaultDisplayRotation();
   4031         }
   4032     }
   4033 
   4034     @Override
   4035     public void removeRotationWatcher(IRotationWatcher watcher) {
   4036         final IBinder watcherBinder = watcher.asBinder();
   4037         synchronized (mWindowMap) {
   4038             for (int i=0; i<mRotationWatchers.size(); i++) {
   4039                 RotationWatcher rotationWatcher = mRotationWatchers.get(i);
   4040                 if (watcherBinder == rotationWatcher.mWatcher.asBinder()) {
   4041                     RotationWatcher removed = mRotationWatchers.remove(i);
   4042                     IBinder binder = removed.mWatcher.asBinder();
   4043                     if (binder != null) {
   4044                         binder.unlinkToDeath(removed.mDeathRecipient, 0);
   4045                     }
   4046                     i--;
   4047                 }
   4048             }
   4049         }
   4050     }
   4051 
   4052     @Override
   4053     public boolean registerWallpaperVisibilityListener(IWallpaperVisibilityListener listener,
   4054             int displayId) {
   4055         synchronized (mWindowMap) {
   4056             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
   4057             if (displayContent == null) {
   4058                 throw new IllegalArgumentException("Trying to register visibility event "
   4059                         + "for invalid display: " + displayId);
   4060             }
   4061             mWallpaperVisibilityListeners.registerWallpaperVisibilityListener(listener, displayId);
   4062             return displayContent.mWallpaperController.isWallpaperVisible();
   4063         }
   4064     }
   4065 
   4066     @Override
   4067     public void unregisterWallpaperVisibilityListener(IWallpaperVisibilityListener listener,
   4068             int displayId) {
   4069         synchronized (mWindowMap) {
   4070             mWallpaperVisibilityListeners
   4071                     .unregisterWallpaperVisibilityListener(listener, displayId);
   4072         }
   4073     }
   4074 
   4075     /**
   4076      * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
   4077      * theme attribute) on devices that feature a physical options menu key attempt to position
   4078      * their menu panel window along the edge of the screen nearest the physical menu key.
   4079      * This lowers the travel distance between invoking the menu panel and selecting
   4080      * a menu option.
   4081      *
   4082      * This method helps control where that menu is placed. Its current implementation makes
   4083      * assumptions about the menu key and its relationship to the screen based on whether
   4084      * the device's natural orientation is portrait (width < height) or landscape.
   4085      *
   4086      * The menu key is assumed to be located along the bottom edge of natural-portrait
   4087      * devices and along the right edge of natural-landscape devices. If these assumptions
   4088      * do not hold for the target device, this method should be changed to reflect that.
   4089      *
   4090      * @return A {@link Gravity} value for placing the options menu window
   4091      */
   4092     @Override
   4093     public int getPreferredOptionsPanelGravity() {
   4094         synchronized (mWindowMap) {
   4095             // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
   4096             final DisplayContent displayContent = getDefaultDisplayContentLocked();
   4097             final int rotation = displayContent.getRotation();
   4098             if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
   4099                 // On devices with a natural orientation of portrait
   4100                 switch (rotation) {
   4101                     default:
   4102                     case Surface.ROTATION_0:
   4103                         return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
   4104                     case Surface.ROTATION_90:
   4105                         return Gravity.RIGHT | Gravity.BOTTOM;
   4106                     case Surface.ROTATION_180:
   4107                         return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
   4108                     case Surface.ROTATION_270:
   4109                         return Gravity.START | Gravity.BOTTOM;
   4110                 }
   4111             }
   4112 
   4113             // On devices with a natural orientation of landscape
   4114             switch (rotation) {
   4115                 default:
   4116                 case Surface.ROTATION_0:
   4117                     return Gravity.RIGHT | Gravity.BOTTOM;
   4118                 case Surface.ROTATION_90:
   4119                     return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
   4120                 case Surface.ROTATION_180:
   4121                     return Gravity.START | Gravity.BOTTOM;
   4122                 case Surface.ROTATION_270:
   4123                     return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
   4124             }
   4125         }
   4126     }
   4127 
   4128     /**
   4129      * Starts the view server on the specified port.
   4130      *
   4131      * @param port The port to listener to.
   4132      *
   4133      * @return True if the server was successfully started, false otherwise.
   4134      *
   4135      * @see com.android.server.wm.ViewServer
   4136      * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
   4137      */
   4138     @Override
   4139     public boolean startViewServer(int port) {
   4140         if (isSystemSecure()) {
   4141             return false;
   4142         }
   4143 
   4144         if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
   4145             return false;
   4146         }
   4147 
   4148         if (port < 1024) {
   4149             return false;
   4150         }
   4151 
   4152         if (mViewServer != null) {
   4153             if (!mViewServer.isRunning()) {
   4154                 try {
   4155                     return mViewServer.start();
   4156                 } catch (IOException e) {
   4157                     Slog.w(TAG_WM, "View server did not start");
   4158                 }
   4159             }
   4160             return false;
   4161         }
   4162 
   4163         try {
   4164             mViewServer = new ViewServer(this, port);
   4165             return mViewServer.start();
   4166         } catch (IOException e) {
   4167             Slog.w(TAG_WM, "View server did not start");
   4168         }
   4169         return false;
   4170     }
   4171 
   4172     private boolean isSystemSecure() {
   4173         return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
   4174                 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
   4175     }
   4176 
   4177     /**
   4178      * Stops the view server if it exists.
   4179      *
   4180      * @return True if the server stopped, false if it wasn't started or
   4181      *         couldn't be stopped.
   4182      *
   4183      * @see com.android.server.wm.ViewServer
   4184      */
   4185     @Override
   4186     public boolean stopViewServer() {
   4187         if (isSystemSecure()) {
   4188             return false;
   4189         }
   4190 
   4191         if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
   4192             return false;
   4193         }
   4194 
   4195         if (mViewServer != null) {
   4196             return mViewServer.stop();
   4197         }
   4198         return false;
   4199     }
   4200 
   4201     /**
   4202      * Indicates whether the view server is running.
   4203      *
   4204      * @return True if the server is running, false otherwise.
   4205      *
   4206      * @see com.android.server.wm.ViewServer
   4207      */
   4208     @Override
   4209     public boolean isViewServerRunning() {
   4210         if (isSystemSecure()) {
   4211             return false;
   4212         }
   4213 
   4214         if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
   4215             return false;
   4216         }
   4217 
   4218         return mViewServer != null && mViewServer.isRunning();
   4219     }
   4220 
   4221     /**
   4222      * Lists all available windows in the system. The listing is written in the specified Socket's
   4223      * output stream with the following syntax: windowHashCodeInHexadecimal windowName
   4224      * Each line of the output represents a different window.
   4225      *
   4226      * @param client The remote client to send the listing to.
   4227      * @return false if an error occurred, true otherwise.
   4228      */
   4229     boolean viewServerListWindows(Socket client) {
   4230         if (isSystemSecure()) {
   4231             return false;
   4232         }
   4233 
   4234         boolean result = true;
   4235 
   4236         final ArrayList<WindowState> windows = new ArrayList();
   4237         synchronized (mWindowMap) {
   4238             mRoot.forAllWindows(w -> {
   4239                 windows.add(w);
   4240             }, false /* traverseTopToBottom */);
   4241         }
   4242 
   4243         BufferedWriter out = null;
   4244 
   4245         // Any uncaught exception will crash the system process
   4246         try {
   4247             OutputStream clientStream = client.getOutputStream();
   4248             out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
   4249 
   4250             final int count = windows.size();
   4251             for (int i = 0; i < count; i++) {
   4252                 final WindowState w = windows.get(i);
   4253                 out.write(Integer.toHexString(System.identityHashCode(w)));
   4254                 out.write(' ');
   4255                 out.append(w.mAttrs.getTitle());
   4256                 out.write('\n');
   4257             }
   4258 
   4259             out.write("DONE.\n");
   4260             out.flush();
   4261         } catch (Exception e) {
   4262             result = false;
   4263         } finally {
   4264             if (out != null) {
   4265                 try {
   4266                     out.close();
   4267                 } catch (IOException e) {
   4268                     result = false;
   4269                 }
   4270             }
   4271         }
   4272 
   4273         return result;
   4274     }
   4275 
   4276     // TODO(multidisplay): Extend to multiple displays.
   4277     /**
   4278      * Returns the focused window in the following format:
   4279      * windowHashCodeInHexadecimal windowName
   4280      *
   4281      * @param client The remote client to send the listing to.
   4282      * @return False if an error occurred, true otherwise.
   4283      */
   4284     boolean viewServerGetFocusedWindow(Socket client) {
   4285         if (isSystemSecure()) {
   4286             return false;
   4287         }
   4288 
   4289         boolean result = true;
   4290 
   4291         WindowState focusedWindow = getFocusedWindow();
   4292 
   4293         BufferedWriter out = null;
   4294 
   4295         // Any uncaught exception will crash the system process
   4296         try {
   4297             OutputStream clientStream = client.getOutputStream();
   4298             out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
   4299 
   4300             if(focusedWindow != null) {
   4301                 out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
   4302                 out.write(' ');
   4303                 out.append(focusedWindow.mAttrs.getTitle());
   4304             }
   4305             out.write('\n');
   4306             out.flush();
   4307         } catch (Exception e) {
   4308             result = false;
   4309         } finally {
   4310             if (out != null) {
   4311                 try {
   4312                     out.close();
   4313                 } catch (IOException e) {
   4314                     result = false;
   4315                 }
   4316             }
   4317         }
   4318 
   4319         return result;
   4320     }
   4321 
   4322     /**
   4323      * Sends a command to a target window. The result of the command, if any, will be
   4324      * written in the output stream of the specified socket.
   4325      *
   4326      * The parameters must follow this syntax:
   4327      * windowHashcode extra
   4328      *
   4329      * Where XX is the length in characeters of the windowTitle.
   4330      *
   4331      * The first parameter is the target window. The window with the specified hashcode
   4332      * will be the target. If no target can be found, nothing happens. The extra parameters
   4333      * will be delivered to the target window and as parameters to the command itself.
   4334      *
   4335      * @param client The remote client to sent the result, if any, to.
   4336      * @param command The command to execute.
   4337      * @param parameters The command parameters.
   4338      *
   4339      * @return True if the command was successfully delivered, false otherwise. This does
   4340      *         not indicate whether the command itself was successful.
   4341      */
   4342     boolean viewServerWindowCommand(Socket client, String command, String parameters) {
   4343         if (isSystemSecure()) {
   4344             return false;
   4345         }
   4346 
   4347         boolean success = true;
   4348         Parcel data = null;
   4349         Parcel reply = null;
   4350 
   4351         BufferedWriter out = null;
   4352 
   4353         // Any uncaught exception will crash the system process
   4354         try {
   4355             // Find the hashcode of the window
   4356             int index = parameters.indexOf(' ');
   4357             if (index == -1) {
   4358                 index = parameters.length();
   4359             }
   4360             final String code = parameters.substring(0, index);
   4361             int hashCode = (int) Long.parseLong(code, 16);
   4362 
   4363             // Extract the command's parameter after the window description
   4364             if (index < parameters.length()) {
   4365                 parameters = parameters.substring(index + 1);
   4366             } else {
   4367                 parameters = "";
   4368             }
   4369 
   4370             final WindowState window = findWindow(hashCode);
   4371             if (window == null) {
   4372                 return false;
   4373             }
   4374 
   4375             data = Parcel.obtain();
   4376             data.writeInterfaceToken("android.view.IWindow");
   4377             data.writeString(command);
   4378             data.writeString(parameters);
   4379             data.writeInt(1);
   4380             ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
   4381 
   4382             reply = Parcel.obtain();
   4383 
   4384             final IBinder binder = window.mClient.asBinder();
   4385             // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
   4386             binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
   4387 
   4388             reply.readException();
   4389 
   4390             if (!client.isOutputShutdown()) {
   4391                 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
   4392                 out.write("DONE\n");
   4393                 out.flush();
   4394             }
   4395 
   4396         } catch (Exception e) {
   4397             Slog.w(TAG_WM, "Could not send command " + command + " with parameters " + parameters, e);
   4398             success = false;
   4399         } finally {
   4400             if (data != null) {
   4401                 data.recycle();
   4402             }
   4403             if (reply != null) {
   4404                 reply.recycle();
   4405             }
   4406             if (out != null) {
   4407                 try {
   4408                     out.close();
   4409                 } catch (IOException e) {
   4410 
   4411                 }
   4412             }
   4413         }
   4414 
   4415         return success;
   4416     }
   4417 
   4418     public void addWindowChangeListener(WindowChangeListener listener) {
   4419         synchronized(mWindowMap) {
   4420             mWindowChangeListeners.add(listener);
   4421         }
   4422     }
   4423 
   4424     public void removeWindowChangeListener(WindowChangeListener listener) {
   4425         synchronized(mWindowMap) {
   4426             mWindowChangeListeners.remove(listener);
   4427         }
   4428     }
   4429 
   4430     private void notifyWindowsChanged() {
   4431         WindowChangeListener[] windowChangeListeners;
   4432         synchronized(mWindowMap) {
   4433             if(mWindowChangeListeners.isEmpty()) {
   4434                 return;
   4435             }
   4436             windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
   4437             windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
   4438         }
   4439         int N = windowChangeListeners.length;
   4440         for(int i = 0; i < N; i++) {
   4441             windowChangeListeners[i].windowsChanged();
   4442         }
   4443     }
   4444 
   4445     private void notifyFocusChanged() {
   4446         WindowChangeListener[] windowChangeListeners;
   4447         synchronized(mWindowMap) {
   4448             if(mWindowChangeListeners.isEmpty()) {
   4449                 return;
   4450             }
   4451             windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
   4452             windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
   4453         }
   4454         int N = windowChangeListeners.length;
   4455         for(int i = 0; i < N; i++) {
   4456             windowChangeListeners[i].focusChanged();
   4457         }
   4458     }
   4459 
   4460     private WindowState findWindow(int hashCode) {
   4461         if (hashCode == -1) {
   4462             // TODO(multidisplay): Extend to multiple displays.
   4463             return getFocusedWindow();
   4464         }
   4465 
   4466         synchronized (mWindowMap) {
   4467             return mRoot.getWindow((w) -> System.identityHashCode(w) == hashCode);
   4468         }
   4469     }
   4470 
   4471     /**
   4472      * Instruct the Activity Manager to fetch and update the current display's configuration and
   4473      * broadcast them to config-changed listeners if appropriate.
   4474      * NOTE: Can't be called with the window manager lock held since it call into activity manager.
   4475      */
   4476     void sendNewConfiguration(int displayId) {
   4477         try {
   4478             final boolean configUpdated = mActivityManager.updateDisplayOverrideConfiguration(
   4479                     null /* values */, displayId);
   4480             if (!configUpdated) {
   4481                 // Something changed (E.g. device rotation), but no configuration update is needed.
   4482                 // E.g. changing device rotation by 180 degrees. Go ahead and perform surface
   4483                 // placement to unfreeze the display since we froze it when the rotation was updated
   4484                 // in DisplayContent#updateRotationUnchecked.
   4485                 synchronized (mWindowMap) {
   4486                     if (mWaitingForConfig) {
   4487                         mWaitingForConfig = false;
   4488                         mLastFinishedFreezeSource = "config-unchanged";
   4489                         final DisplayContent dc = mRoot.getDisplayContent(displayId);
   4490                         if (dc != null) {
   4491                             dc.setLayoutNeeded();
   4492                         }
   4493                         mWindowPlacerLocked.performSurfacePlacement();
   4494                     }
   4495                 }
   4496             }
   4497         } catch (RemoteException e) {
   4498         }
   4499     }
   4500 
   4501     public Configuration computeNewConfiguration(int displayId) {
   4502         synchronized (mWindowMap) {
   4503             return computeNewConfigurationLocked(displayId);
   4504         }
   4505     }
   4506 
   4507     private Configuration computeNewConfigurationLocked(int displayId) {
   4508         if (!mDisplayReady) {
   4509             return null;
   4510         }
   4511         final Configuration config = new Configuration();
   4512         final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
   4513         displayContent.computeScreenConfiguration(config);
   4514         return config;
   4515     }
   4516 
   4517     void notifyHardKeyboardStatusChange() {
   4518         final boolean available;
   4519         final WindowManagerInternal.OnHardKeyboardStatusChangeListener listener;
   4520         synchronized (mWindowMap) {
   4521             listener = mHardKeyboardStatusChangeListener;
   4522             available = mHardKeyboardAvailable;
   4523         }
   4524         if (listener != null) {
   4525             listener.onHardKeyboardStatusChange(available);
   4526         }
   4527     }
   4528 
   4529     boolean startMovingTask(IWindow window, float startX, float startY) {
   4530         WindowState win = null;
   4531         synchronized (mWindowMap) {
   4532             win = windowForClientLocked(null, window, false);
   4533             // win shouldn't be null here, pass it down to startPositioningLocked
   4534             // to get warning if it's null.
   4535             if (!startPositioningLocked(
   4536                         win, false /*resize*/, false /*preserveOrientation*/, startX, startY)) {
   4537                 return false;
   4538             }
   4539         }
   4540         try {
   4541             mActivityManager.setFocusedTask(win.getTask().mTaskId);
   4542         } catch(RemoteException e) {}
   4543         return true;
   4544     }
   4545 
   4546     private void handleTapOutsideTask(DisplayContent displayContent, int x, int y) {
   4547         int taskId = -1;
   4548         synchronized (mWindowMap) {
   4549             final Task task = displayContent.findTaskForResizePoint(x, y);
   4550             if (task != null) {
   4551                 if (!startPositioningLocked(task.getTopVisibleAppMainWindow(), true /*resize*/,
   4552                             task.preserveOrientationOnResize(), x, y)) {
   4553                     return;
   4554                 }
   4555                 taskId = task.mTaskId;
   4556             } else {
   4557                 taskId = displayContent.taskIdFromPoint(x, y);
   4558             }
   4559         }
   4560         if (taskId >= 0) {
   4561             try {
   4562                 mActivityManager.setFocusedTask(taskId);
   4563             } catch(RemoteException e) {}
   4564         }
   4565     }
   4566 
   4567     private boolean startPositioningLocked(WindowState win, boolean resize,
   4568             boolean preserveOrientation, float startX, float startY) {
   4569         if (DEBUG_TASK_POSITIONING)
   4570             Slog.d(TAG_WM, "startPositioningLocked: "
   4571                             + "win=" + win + ", resize=" + resize + ", preserveOrientation="
   4572                             + preserveOrientation + ", {" + startX + ", " + startY + "}");
   4573 
   4574         if (win == null || win.getAppToken() == null) {
   4575             Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win);
   4576             return false;
   4577         }
   4578         if (win.mInputChannel == null) {
   4579             Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, "
   4580                     + " probably being removed");
   4581             return false;
   4582         }
   4583 
   4584         final DisplayContent displayContent = win.getDisplayContent();
   4585         if (displayContent == null) {
   4586             Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win);
   4587             return false;
   4588         }
   4589 
   4590         Display display = displayContent.getDisplay();
   4591         mTaskPositioner = new TaskPositioner(this);
   4592         mTaskPositioner.register(display);
   4593         mInputMonitor.updateInputWindowsLw(true /*force*/);
   4594 
   4595         // We need to grab the touch focus so that the touch events during the
   4596         // resizing/scrolling are not sent to the app. 'win' is the main window
   4597         // of the app, it may not have focus since there might be other windows
   4598         // on top (eg. a dialog window).
   4599         WindowState transferFocusFromWin = win;
   4600         if (mCurrentFocus != null && mCurrentFocus != win
   4601                 && mCurrentFocus.mAppToken == win.mAppToken) {
   4602             transferFocusFromWin = mCurrentFocus;
   4603         }
   4604         if (!mInputManager.transferTouchFocus(
   4605                 transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) {
   4606             Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
   4607             mTaskPositioner.unregister();
   4608             mTaskPositioner = null;
   4609             mInputMonitor.updateInputWindowsLw(true /*force*/);
   4610             return false;
   4611         }
   4612 
   4613         mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY);
   4614         return true;
   4615     }
   4616 
   4617     private void finishPositioning() {
   4618         if (DEBUG_TASK_POSITIONING) {
   4619             Slog.d(TAG_WM, "finishPositioning");
   4620         }
   4621         synchronized (mWindowMap) {
   4622             if (mTaskPositioner != null) {
   4623                 mTaskPositioner.unregister();
   4624                 mTaskPositioner = null;
   4625                 mInputMonitor.updateInputWindowsLw(true /*force*/);
   4626             }
   4627         }
   4628     }
   4629 
   4630     // -------------------------------------------------------------
   4631     // Drag and drop
   4632     // -------------------------------------------------------------
   4633 
   4634     IBinder prepareDragSurface(IWindow window, SurfaceSession session,
   4635             int flags, int width, int height, Surface outSurface) {
   4636         if (DEBUG_DRAG) {
   4637             Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height
   4638                     + " flags=" + Integer.toHexString(flags) + " win=" + window
   4639                     + " asbinder=" + window.asBinder());
   4640         }
   4641 
   4642         final int callerPid = Binder.getCallingPid();
   4643         final int callerUid = Binder.getCallingUid();
   4644         final long origId = Binder.clearCallingIdentity();
   4645         IBinder token = null;
   4646 
   4647         try {
   4648             synchronized (mWindowMap) {
   4649                 try {
   4650                     if (mDragState == null) {
   4651                         // TODO(multi-display): support other displays
   4652                         final DisplayContent displayContent = getDefaultDisplayContentLocked();
   4653                         final Display display = displayContent.getDisplay();
   4654 
   4655                         SurfaceControl surface = new SurfaceControl(session, "drag surface",
   4656                                 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
   4657                         surface.setLayerStack(display.getLayerStack());
   4658                         float alpha = 1;
   4659                         if ((flags & View.DRAG_FLAG_OPAQUE) == 0) {
   4660                             alpha = DRAG_SHADOW_ALPHA_TRANSPARENT;
   4661                         }
   4662                         surface.setAlpha(alpha);
   4663 
   4664                         if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  DRAG "
   4665                                 + surface + ": CREATE");
   4666                         outSurface.copyFrom(surface);
   4667                         final IBinder winBinder = window.asBinder();
   4668                         token = new Binder();
   4669                         mDragState = new DragState(this, token, surface, flags, winBinder);
   4670                         mDragState.mPid = callerPid;
   4671                         mDragState.mUid = callerUid;
   4672                         mDragState.mOriginalAlpha = alpha;
   4673                         token = mDragState.mToken = new Binder();
   4674 
   4675                         // 5 second timeout for this window to actually begin the drag
   4676                         mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
   4677                         Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
   4678                         mH.sendMessageDelayed(msg, 5000);
   4679                     } else {
   4680                         Slog.w(TAG_WM, "Drag already in progress");
   4681                     }
   4682                 } catch (OutOfResourcesException e) {
   4683                     Slog.e(TAG_WM, "Can't allocate drag surface w=" + width + " h=" + height, e);
   4684                     if (mDragState != null) {
   4685                         mDragState.reset();
   4686                         mDragState = null;
   4687                     }
   4688                 }
   4689             }
   4690         } finally {
   4691             Binder.restoreCallingIdentity(origId);
   4692         }
   4693 
   4694         return token;
   4695     }
   4696 
   4697     // -------------------------------------------------------------
   4698     // Input Events and Focus Management
   4699     // -------------------------------------------------------------
   4700 
   4701     final InputMonitor mInputMonitor = new InputMonitor(this);
   4702     private boolean mEventDispatchingEnabled;
   4703 
   4704     @Override
   4705     public void setEventDispatching(boolean enabled) {
   4706         if (!checkCallingPermission(MANAGE_APP_TOKENS, "setEventDispatching()")) {
   4707             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
   4708         }
   4709 
   4710         synchronized (mWindowMap) {
   4711             mEventDispatchingEnabled = enabled;
   4712             if (mDisplayEnabled) {
   4713                 mInputMonitor.setEventDispatchingLw(enabled);
   4714             }
   4715         }
   4716     }
   4717 
   4718     private WindowState getFocusedWindow() {
   4719         synchronized (mWindowMap) {
   4720             return getFocusedWindowLocked();
   4721         }
   4722     }
   4723 
   4724     private WindowState getFocusedWindowLocked() {
   4725         return mCurrentFocus;
   4726     }
   4727 
   4728     TaskStack getImeFocusStackLocked() {
   4729         // Don't use mCurrentFocus.getStack() because it returns home stack for system windows.
   4730         // Also don't use mInputMethodTarget's stack, because some window with FLAG_NOT_FOCUSABLE
   4731         // and FLAG_ALT_FOCUSABLE_IM flags both set might be set to IME target so they're moved
   4732         // to make room for IME, but the window is not the focused window that's taking input.
   4733         return (mFocusedApp != null && mFocusedApp.getTask() != null) ?
   4734                 mFocusedApp.getTask().mStack : null;
   4735     }
   4736 
   4737     public boolean detectSafeMode() {
   4738         if (!mInputMonitor.waitForInputDevicesReady(
   4739                 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
   4740             Slog.w(TAG_WM, "Devices still not ready after waiting "
   4741                    + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
   4742                    + " milliseconds before attempting to detect safe mode.");
   4743         }
   4744 
   4745         if (Settings.Global.getInt(
   4746                 mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) {
   4747             return false;
   4748         }
   4749 
   4750         int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
   4751                 KeyEvent.KEYCODE_MENU);
   4752         int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
   4753         int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
   4754                 KeyEvent.KEYCODE_DPAD_CENTER);
   4755         int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
   4756                 InputManagerService.BTN_MOUSE);
   4757         int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
   4758                 KeyEvent.KEYCODE_VOLUME_DOWN);
   4759         mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
   4760                 || volumeDownState > 0;
   4761         try {
   4762             if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0
   4763                     || SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) != 0) {
   4764                 mSafeMode = true;
   4765                 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
   4766             }
   4767         } catch (IllegalArgumentException e) {
   4768         }
   4769         if (mSafeMode) {
   4770             Log.i(TAG_WM, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
   4771                     + " dpad=" + dpadState + " trackball=" + trackballState + ")");
   4772             SystemProperties.set(ShutdownThread.RO_SAFEMODE_PROPERTY, "1");
   4773         } else {
   4774             Log.i(TAG_WM, "SAFE MODE not enabled");
   4775         }
   4776         mPolicy.setSafeMode(mSafeMode);
   4777         return mSafeMode;
   4778     }
   4779 
   4780     public void displayReady() {
   4781         for (Display display : mDisplays) {
   4782             displayReady(display.getDisplayId());
   4783         }
   4784 
   4785         synchronized(mWindowMap) {
   4786             final DisplayContent displayContent = getDefaultDisplayContentLocked();
   4787             if (mMaxUiWidth > 0) {
   4788                 displayContent.setMaxUiWidth(mMaxUiWidth);
   4789             }
   4790             readForcedDisplayPropertiesLocked(displayContent);
   4791             mDisplayReady = true;
   4792         }
   4793 
   4794         try {
   4795             mActivityManager.updateConfiguration(null);
   4796         } catch (RemoteException e) {
   4797         }
   4798 
   4799         synchronized(mWindowMap) {
   4800             mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
   4801                     PackageManager.FEATURE_TOUCHSCREEN);
   4802             configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
   4803         }
   4804 
   4805         try {
   4806             mActivityManager.updateConfiguration(null);
   4807         } catch (RemoteException e) {
   4808         }
   4809 
   4810         updateCircularDisplayMaskIfNeeded();
   4811     }
   4812 
   4813     private void displayReady(int displayId) {
   4814         synchronized(mWindowMap) {
   4815             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
   4816             if (displayContent != null) {
   4817                 mAnimator.addDisplayLocked(displayId);
   4818                 displayContent.initializeDisplayBaseInfo();
   4819             }
   4820         }
   4821     }
   4822 
   4823     public void systemReady() {
   4824         mPolicy.systemReady();
   4825         mTaskSnapshotController.systemReady();
   4826         mHasWideColorGamutSupport = queryWideColorGamutSupport();
   4827     }
   4828 
   4829     private static boolean queryWideColorGamutSupport() {
   4830         try {
   4831             ISurfaceFlingerConfigs surfaceFlinger = ISurfaceFlingerConfigs.getService();
   4832             OptionalBool hasWideColor = surfaceFlinger.hasWideColorDisplay();
   4833             if (hasWideColor != null) {
   4834                 return hasWideColor.value;
   4835             }
   4836         } catch (RemoteException e) {
   4837             // Ignore, we're in big trouble if we can't talk to SurfaceFlinger's config store
   4838         }
   4839         return false;
   4840     }
   4841 
   4842     // -------------------------------------------------------------
   4843     // Async Handler
   4844     // -------------------------------------------------------------
   4845 
   4846     final class H extends android.os.Handler {
   4847         public static final int REPORT_FOCUS_CHANGE = 2;
   4848         public static final int REPORT_LOSING_FOCUS = 3;
   4849         public static final int WINDOW_FREEZE_TIMEOUT = 11;
   4850 
   4851         public static final int APP_TRANSITION_TIMEOUT = 13;
   4852         public static final int PERSIST_ANIMATION_SCALE = 14;
   4853         public static final int FORCE_GC = 15;
   4854         public static final int ENABLE_SCREEN = 16;
   4855         public static final int APP_FREEZE_TIMEOUT = 17;
   4856         public static final int SEND_NEW_CONFIGURATION = 18;
   4857         public static final int REPORT_WINDOWS_CHANGE = 19;
   4858         public static final int DRAG_START_TIMEOUT = 20;
   4859         public static final int DRAG_END_TIMEOUT = 21;
   4860         public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
   4861         public static final int BOOT_TIMEOUT = 23;
   4862         public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
   4863         public static final int SHOW_STRICT_MODE_VIOLATION = 25;
   4864         public static final int DO_ANIMATION_CALLBACK = 26;
   4865 
   4866         public static final int CLIENT_FREEZE_TIMEOUT = 30;
   4867         public static final int TAP_OUTSIDE_TASK = 31;
   4868         public static final int NOTIFY_ACTIVITY_DRAWN = 32;
   4869 
   4870         public static final int ALL_WINDOWS_DRAWN = 33;
   4871 
   4872         public static final int NEW_ANIMATOR_SCALE = 34;
   4873 
   4874         public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35;
   4875         public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36;
   4876 
   4877         public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37;
   4878         public static final int RESET_ANR_MESSAGE = 38;
   4879         public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39;
   4880 
   4881         public static final int FINISH_TASK_POSITIONING = 40;
   4882 
   4883         public static final int UPDATE_DOCKED_STACK_DIVIDER = 41;
   4884 
   4885         public static final int TEAR_DOWN_DRAG_AND_DROP_INPUT = 44;
   4886 
   4887         public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
   4888 
   4889         public static final int NOTIFY_APP_TRANSITION_STARTING = 47;
   4890         public static final int NOTIFY_APP_TRANSITION_CANCELLED = 48;
   4891         public static final int NOTIFY_APP_TRANSITION_FINISHED = 49;
   4892         public static final int UPDATE_ANIMATION_SCALE = 51;
   4893         public static final int WINDOW_HIDE_TIMEOUT = 52;
   4894         public static final int NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED = 53;
   4895         public static final int SEAMLESS_ROTATION_TIMEOUT = 54;
   4896         public static final int RESTORE_POINTER_ICON = 55;
   4897         public static final int NOTIFY_KEYGUARD_FLAGS_CHANGED = 56;
   4898         public static final int NOTIFY_KEYGUARD_TRUSTED_CHANGED = 57;
   4899         public static final int SET_HAS_OVERLAY_UI = 58;
   4900 
   4901         /**
   4902          * Used to denote that an integer field in a message will not be used.
   4903          */
   4904         public static final int UNUSED = 0;
   4905 
   4906         @Override
   4907         public void handleMessage(Message msg) {
   4908             if (DEBUG_WINDOW_TRACE) {
   4909                 Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what);
   4910             }
   4911             switch (msg.what) {
   4912                 case REPORT_FOCUS_CHANGE: {
   4913                     WindowState lastFocus;
   4914                     WindowState newFocus;
   4915 
   4916                     AccessibilityController accessibilityController = null;
   4917 
   4918                     synchronized(mWindowMap) {
   4919                         // TODO(multidisplay): Accessibility supported only of default desiplay.
   4920                         if (mAccessibilityController != null && getDefaultDisplayContentLocked()
   4921                                 .getDisplayId() == DEFAULT_DISPLAY) {
   4922                             accessibilityController = mAccessibilityController;
   4923                         }
   4924 
   4925                         lastFocus = mLastFocus;
   4926                         newFocus = mCurrentFocus;
   4927                         if (lastFocus == newFocus) {
   4928                             // Focus is not changing, so nothing to do.
   4929                             return;
   4930                         }
   4931                         mLastFocus = newFocus;
   4932                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Focus moving from " + lastFocus +
   4933                                 " to " + newFocus);
   4934                         if (newFocus != null && lastFocus != null
   4935                                 && !newFocus.isDisplayedLw()) {
   4936                             //Slog.i(TAG_WM, "Delaying loss of focus...");
   4937                             mLosingFocus.add(lastFocus);
   4938                             lastFocus = null;
   4939                         }
   4940                     }
   4941 
   4942                     // First notify the accessibility manager for the change so it has
   4943                     // the windows before the newly focused one starts firing eventgs.
   4944                     if (accessibilityController != null) {
   4945                         accessibilityController.onWindowFocusChangedNotLocked();
   4946                     }
   4947 
   4948                     //System.out.println("Changing focus from " + lastFocus
   4949                     //                   + " to " + newFocus);
   4950                     if (newFocus != null) {
   4951                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Gaining focus: " + newFocus);
   4952                         newFocus.reportFocusChangedSerialized(true, mInTouchMode);
   4953                         notifyFocusChanged();
   4954                     }
   4955 
   4956                     if (lastFocus != null) {
   4957                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing focus: " + lastFocus);
   4958                         lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
   4959                     }
   4960                 } break;
   4961 
   4962                 case REPORT_LOSING_FOCUS: {
   4963                     ArrayList<WindowState> losers;
   4964 
   4965                     synchronized(mWindowMap) {
   4966                         losers = mLosingFocus;
   4967                         mLosingFocus = new ArrayList<WindowState>();
   4968                     }
   4969 
   4970                     final int N = losers.size();
   4971                     for (int i=0; i<N; i++) {
   4972                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing delayed focus: " +
   4973                                 losers.get(i));
   4974                         losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
   4975                     }
   4976                 } break;
   4977 
   4978                 case WINDOW_FREEZE_TIMEOUT: {
   4979                     // TODO(multidisplay): Can non-default displays rotate?
   4980                     synchronized (mWindowMap) {
   4981                         getDefaultDisplayContentLocked().onWindowFreezeTimeout();
   4982                     }
   4983                     break;
   4984                 }
   4985 
   4986                 case APP_TRANSITION_TIMEOUT: {
   4987                     synchronized (mWindowMap) {
   4988                         if (mAppTransition.isTransitionSet() || !mOpeningApps.isEmpty()
   4989                                     || !mClosingApps.isEmpty()) {
   4990                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "*** APP TRANSITION TIMEOUT."
   4991                                     + " isTransitionSet()=" + mAppTransition.isTransitionSet()
   4992                                     + " mOpeningApps.size()=" + mOpeningApps.size()
   4993                                     + " mClosingApps.size()=" + mClosingApps.size());
   4994                             mAppTransition.setTimeout();
   4995                             mWindowPlacerLocked.performSurfacePlacement();
   4996                         }
   4997                     }
   4998                     break;
   4999                 }
   5000 
   5001                 case PERSIST_ANIMATION_SCALE: {
   5002                     Settings.Global.putFloat(mContext.getContentResolver(),
   5003                             Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
   5004                     Settings.Global.putFloat(mContext.getContentResolver(),
   5005                             Settings.Global.TRANSITION_ANIMATION_SCALE,
   5006                             mTransitionAnimationScaleSetting);
   5007                     Settings.Global.putFloat(mContext.getContentResolver(),
   5008                             Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting);
   5009                     break;
   5010                 }
   5011 
   5012                 case UPDATE_ANIMATION_SCALE: {
   5013                     @UpdateAnimationScaleMode
   5014                     final int mode = msg.arg1;
   5015                     switch (mode) {
   5016                         case WINDOW_ANIMATION_SCALE: {
   5017                             mWindowAnimationScaleSetting = Settings.Global.getFloat(
   5018                                     mContext.getContentResolver(),
   5019                                     Settings.Global.WINDOW_ANIMATION_SCALE,
   5020                                     mWindowAnimationScaleSetting);
   5021                             break;
   5022                         }
   5023                         case TRANSITION_ANIMATION_SCALE: {
   5024                             mTransitionAnimationScaleSetting = Settings.Global.getFloat(
   5025                                     mContext.getContentResolver(),
   5026                                     Settings.Global.TRANSITION_ANIMATION_SCALE,
   5027                                     mTransitionAnimationScaleSetting);
   5028                             break;
   5029                         }
   5030                         case ANIMATION_DURATION_SCALE: {
   5031                             mAnimatorDurationScaleSetting = Settings.Global.getFloat(
   5032                                     mContext.getContentResolver(),
   5033                                     Settings.Global.ANIMATOR_DURATION_SCALE,
   5034                                     mAnimatorDurationScaleSetting);
   5035                             dispatchNewAnimatorScaleLocked(null);
   5036                             break;
   5037                         }
   5038                     }
   5039                     break;
   5040                 }
   5041 
   5042                 case FORCE_GC: {
   5043                     synchronized (mWindowMap) {
   5044                         // Since we're holding both mWindowMap and mAnimator we don't need to
   5045                         // hold mAnimator.mLayoutToAnim.
   5046                         if (mAnimator.isAnimating() || mAnimator.isAnimationScheduled()) {
   5047                             // If we are animating, don't do the gc now but
   5048                             // delay a bit so we don't interrupt the animation.
   5049                             sendEmptyMessageDelayed(H.FORCE_GC, 2000);
   5050                             return;
   5051                         }
   5052                         // If we are currently rotating the display, it will
   5053                         // schedule a new message when done.
   5054                         if (mDisplayFrozen) {
   5055                             return;
   5056                         }
   5057                     }
   5058                     Runtime.getRuntime().gc();
   5059                     break;
   5060                 }
   5061 
   5062                 case ENABLE_SCREEN: {
   5063                     performEnableScreen();
   5064                     break;
   5065                 }
   5066 
   5067                 case APP_FREEZE_TIMEOUT: {
   5068                     synchronized (mWindowMap) {
   5069                         Slog.w(TAG_WM, "App freeze timeout expired.");
   5070                         mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
   5071                         for (int i = mAppFreezeListeners.size() - 1; i >=0 ; --i) {
   5072                             mAppFreezeListeners.get(i).onAppFreezeTimeout();
   5073                         }
   5074                     }
   5075                     break;
   5076                 }
   5077 
   5078                 case CLIENT_FREEZE_TIMEOUT: {
   5079                     synchronized (mWindowMap) {
   5080                         if (mClientFreezingScreen) {
   5081                             mClientFreezingScreen = false;
   5082                             mLastFinishedFreezeSource = "client-timeout";
   5083                             stopFreezingDisplayLocked();
   5084                         }
   5085                     }
   5086                     break;
   5087                 }
   5088 
   5089                 case SEND_NEW_CONFIGURATION: {
   5090                     removeMessages(SEND_NEW_CONFIGURATION, msg.obj);
   5091                     final int displayId = (Integer) msg.obj;
   5092                     if (mRoot.getDisplayContent(displayId) != null) {
   5093                         sendNewConfiguration(displayId);
   5094                     } else {
   5095                         // Message could come after display has already been removed.
   5096                         if (DEBUG_CONFIGURATION) {
   5097                             Slog.w(TAG, "Trying to send configuration to non-existing displayId="
   5098                                     + displayId);
   5099                         }
   5100                     }
   5101                     break;
   5102                 }
   5103 
   5104                 case REPORT_WINDOWS_CHANGE: {
   5105                     if (mWindowsChanged) {
   5106                         synchronized (mWindowMap) {
   5107                             mWindowsChanged = false;
   5108                         }
   5109                         notifyWindowsChanged();
   5110                     }
   5111                     break;
   5112                 }
   5113 
   5114                 case DRAG_START_TIMEOUT: {
   5115                     IBinder win = (IBinder)msg.obj;
   5116                     if (DEBUG_DRAG) {
   5117                         Slog.w(TAG_WM, "Timeout starting drag by win " + win);
   5118                     }
   5119                     synchronized (mWindowMap) {
   5120                         // !!! TODO: ANR the app that has failed to start the drag in time
   5121                         if (mDragState != null) {
   5122                             mDragState.unregister();
   5123                             mDragState.reset();
   5124                             mDragState = null;
   5125                         }
   5126                     }
   5127                     break;
   5128                 }
   5129 
   5130                 case DRAG_END_TIMEOUT: {
   5131                     IBinder win = (IBinder)msg.obj;
   5132                     if (DEBUG_DRAG) {
   5133                         Slog.w(TAG_WM, "Timeout ending drag to win " + win);
   5134                     }
   5135                     synchronized (mWindowMap) {
   5136                         // !!! TODO: ANR the drag-receiving app
   5137                         if (mDragState != null) {
   5138                             mDragState.mDragResult = false;
   5139                             mDragState.endDragLw();
   5140                         }
   5141                     }
   5142                     break;
   5143                 }
   5144 
   5145                 case TEAR_DOWN_DRAG_AND_DROP_INPUT: {
   5146                     if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ending; tearing down input channel");
   5147                     DragState.InputInterceptor interceptor = (DragState.InputInterceptor) msg.obj;
   5148                     if (interceptor != null) {
   5149                         synchronized (mWindowMap) {
   5150                             interceptor.tearDown();
   5151                         }
   5152                     }
   5153                 }
   5154                 break;
   5155 
   5156                 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
   5157                     notifyHardKeyboardStatusChange();
   5158                     break;
   5159                 }
   5160 
   5161                 case BOOT_TIMEOUT: {
   5162                     performBootTimeout();
   5163                     break;
   5164                 }
   5165 
   5166                 case WAITING_FOR_DRAWN_TIMEOUT: {
   5167                     Runnable callback = null;
   5168                     synchronized (mWindowMap) {
   5169                         Slog.w(TAG_WM, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
   5170                         mWaitingForDrawn.clear();
   5171                         callback = mWaitingForDrawnCallback;
   5172                         mWaitingForDrawnCallback = null;
   5173                     }
   5174                     if (callback != null) {
   5175                         callback.run();
   5176                     }
   5177                     break;
   5178                 }
   5179 
   5180                 case SHOW_STRICT_MODE_VIOLATION: {
   5181                     showStrictModeViolation(msg.arg1, msg.arg2);
   5182                     break;
   5183                 }
   5184 
   5185                 case SHOW_CIRCULAR_DISPLAY_MASK: {
   5186                     showCircularMask(msg.arg1 == 1);
   5187                     break;
   5188                 }
   5189 
   5190                 case SHOW_EMULATOR_DISPLAY_OVERLAY: {
   5191                     showEmulatorDisplayOverlay();
   5192                     break;
   5193                 }
   5194 
   5195                 case DO_ANIMATION_CALLBACK: {
   5196                     try {
   5197                         ((IRemoteCallback)msg.obj).sendResult(null);
   5198                     } catch (RemoteException e) {
   5199                     }
   5200                     break;
   5201                 }
   5202 
   5203                 case TAP_OUTSIDE_TASK: {
   5204                     handleTapOutsideTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
   5205                 }
   5206                 break;
   5207 
   5208                 case FINISH_TASK_POSITIONING: {
   5209                     finishPositioning();
   5210                 }
   5211                 break;
   5212 
   5213                 case NOTIFY_ACTIVITY_DRAWN:
   5214                     try {
   5215                         mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
   5216                     } catch (RemoteException e) {
   5217                     }
   5218                     break;
   5219                 case ALL_WINDOWS_DRAWN: {
   5220                     Runnable callback;
   5221                     synchronized (mWindowMap) {
   5222                         callback = mWaitingForDrawnCallback;
   5223                         mWaitingForDrawnCallback = null;
   5224                     }
   5225                     if (callback != null) {
   5226                         callback.run();
   5227                     }
   5228                     break;
   5229                 }
   5230                 case NEW_ANIMATOR_SCALE: {
   5231                     float scale = getCurrentAnimatorScale();
   5232                     ValueAnimator.setDurationScale(scale);
   5233                     Session session = (Session)msg.obj;
   5234                     if (session != null) {
   5235                         try {
   5236                             session.mCallback.onAnimatorScaleChanged(scale);
   5237                         } catch (RemoteException e) {
   5238                         }
   5239                     } else {
   5240                         ArrayList<IWindowSessionCallback> callbacks
   5241                                 = new ArrayList<IWindowSessionCallback>();
   5242                         synchronized (mWindowMap) {
   5243                             for (int i=0; i<mSessions.size(); i++) {
   5244                                 callbacks.add(mSessions.valueAt(i).mCallback);
   5245                             }
   5246 
   5247                         }
   5248                         for (int i=0; i<callbacks.size(); i++) {
   5249                             try {
   5250                                 callbacks.get(i).onAnimatorScaleChanged(scale);
   5251                             } catch (RemoteException e) {
   5252                             }
   5253                         }
   5254                     }
   5255                 }
   5256                 break;
   5257                 case CHECK_IF_BOOT_ANIMATION_FINISHED: {
   5258                     final boolean bootAnimationComplete;
   5259                     synchronized (mWindowMap) {
   5260                         if (DEBUG_BOOT) Slog.i(TAG_WM, "CHECK_IF_BOOT_ANIMATION_FINISHED:");
   5261                         bootAnimationComplete = checkBootAnimationCompleteLocked();
   5262                     }
   5263                     if (bootAnimationComplete) {
   5264                         performEnableScreen();
   5265                     }
   5266                 }
   5267                 break;
   5268                 case RESET_ANR_MESSAGE: {
   5269                     synchronized (mWindowMap) {
   5270                         mLastANRState = null;
   5271                     }
   5272                     mAmInternal.clearSavedANRState();
   5273                 }
   5274                 break;
   5275                 case WALLPAPER_DRAW_PENDING_TIMEOUT: {
   5276                     synchronized (mWindowMap) {
   5277                         if (mRoot.mWallpaperController.processWallpaperDrawPendingTimeout()) {
   5278                             mWindowPlacerLocked.performSurfacePlacement();
   5279                         }
   5280                     }
   5281                 }
   5282                 break;
   5283                 case UPDATE_DOCKED_STACK_DIVIDER: {
   5284                     synchronized (mWindowMap) {
   5285                         final DisplayContent displayContent = getDefaultDisplayContentLocked();
   5286                         displayContent.getDockedDividerController().reevaluateVisibility(false);
   5287                         displayContent.adjustForImeIfNeeded();
   5288                     }
   5289                 }
   5290                 break;
   5291                 case WINDOW_REPLACEMENT_TIMEOUT: {
   5292                     synchronized (mWindowMap) {
   5293                         for (int i = mWindowReplacementTimeouts.size() - 1; i >= 0; i--) {
   5294                             final AppWindowToken token = mWindowReplacementTimeouts.get(i);
   5295                             token.onWindowReplacementTimeout();
   5296                         }
   5297                         mWindowReplacementTimeouts.clear();
   5298                     }
   5299                 }
   5300                 break;
   5301                 case NOTIFY_APP_TRANSITION_STARTING: {
   5302                     mAmInternal.notifyAppTransitionStarting((SparseIntArray) msg.obj,
   5303                             msg.getWhen());
   5304                 }
   5305                 break;
   5306                 case NOTIFY_APP_TRANSITION_CANCELLED: {
   5307                     mAmInternal.notifyAppTransitionCancelled();
   5308                 }
   5309                 break;
   5310                 case NOTIFY_APP_TRANSITION_FINISHED: {
   5311                     mAmInternal.notifyAppTransitionFinished();
   5312                 }
   5313                 break;
   5314                 case WINDOW_HIDE_TIMEOUT: {
   5315                     final WindowState window = (WindowState) msg.obj;
   5316                     synchronized(mWindowMap) {
   5317                         // TODO: This is all about fixing b/21693547
   5318                         // where partially initialized Toasts get stuck
   5319                         // around and keep the screen on. We'd like
   5320                         // to just remove the toast...but this can cause clients
   5321                         // who miss the timeout due to normal circumstances (e.g.
   5322                         // running under debugger) to crash (b/29105388). The windows will
   5323                         // eventually be removed when the client process finishes.
   5324                         // The best we can do for now is remove the FLAG_KEEP_SCREEN_ON
   5325                         // and prevent the symptoms of b/21693547. Since apps don't
   5326                         // support windows being removed under them we hide the window
   5327                         // and it will be removed when the app dies.
   5328                         window.mAttrs.flags &= ~FLAG_KEEP_SCREEN_ON;
   5329                         window.hidePermanentlyLw();
   5330                         window.setDisplayLayoutNeeded();
   5331                         mWindowPlacerLocked.performSurfacePlacement();
   5332                     }
   5333                 }
   5334                 break;
   5335                 case NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED: {
   5336                     mAmInternal.notifyDockedStackMinimizedChanged(msg.arg1 == 1);
   5337                 }
   5338                 break;
   5339                 case RESTORE_POINTER_ICON: {
   5340                     synchronized (mWindowMap) {
   5341                         restorePointerIconLocked((DisplayContent)msg.obj, msg.arg1, msg.arg2);
   5342                     }
   5343                 }
   5344                 break;
   5345                 case SEAMLESS_ROTATION_TIMEOUT: {
   5346                     // Rotation only supported on primary display.
   5347                     // TODO(multi-display)
   5348                     synchronized(mWindowMap) {
   5349                         final DisplayContent dc = getDefaultDisplayContentLocked();
   5350                         dc.onSeamlessRotationTimeout();
   5351                     }
   5352                 }
   5353                 break;
   5354                 case NOTIFY_KEYGUARD_FLAGS_CHANGED: {
   5355                     mAmInternal.notifyKeyguardFlagsChanged((Runnable) msg.obj);
   5356                 }
   5357                 break;
   5358                 case NOTIFY_KEYGUARD_TRUSTED_CHANGED: {
   5359                     mAmInternal.notifyKeyguardTrustedChanged();
   5360                 }
   5361                 break;
   5362                 case SET_HAS_OVERLAY_UI: {
   5363                     mAmInternal.setHasOverlayUi(msg.arg1, msg.arg2 == 1);
   5364                 }
   5365                 break;
   5366             }
   5367             if (DEBUG_WINDOW_TRACE) {
   5368                 Slog.v(TAG_WM, "handleMessage: exit");
   5369             }
   5370         }
   5371     }
   5372 
   5373     void destroyPreservedSurfaceLocked() {
   5374         for (int i = mDestroyPreservedSurface.size() - 1; i >= 0 ; i--) {
   5375             final WindowState w = mDestroyPreservedSurface.get(i);
   5376             w.mWinAnimator.destroyPreservedSurfaceLocked();
   5377         }
   5378         mDestroyPreservedSurface.clear();
   5379     }
   5380 
   5381     void stopUsingSavedSurfaceLocked() {
   5382         for (int i = mFinishedEarlyAnim.size() - 1; i >= 0 ; i--) {
   5383             final AppWindowToken wtoken = mFinishedEarlyAnim.get(i);
   5384             wtoken.stopUsingSavedSurfaceLocked();
   5385         }
   5386         mFinishedEarlyAnim.clear();
   5387     }
   5388 
   5389     // -------------------------------------------------------------
   5390     // IWindowManager API
   5391     // -------------------------------------------------------------
   5392 
   5393     @Override
   5394     public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
   5395             IInputContext inputContext) {
   5396         if (client == null) throw new IllegalArgumentException("null client");
   5397         if (inputContext == null) throw new IllegalArgumentException("null inputContext");
   5398         Session session = new Session(this, callback, client, inputContext);
   5399         return session;
   5400     }
   5401 
   5402     @Override
   5403     public boolean inputMethodClientHasFocus(IInputMethodClient client) {
   5404         synchronized (mWindowMap) {
   5405             // TODO: multi-display
   5406             if (getDefaultDisplayContentLocked().inputMethodClientHasFocus(client)) {
   5407                 return true;
   5408             }
   5409 
   5410             // Okay, how about this...  what is the current focus?
   5411             // It seems in some cases we may not have moved the IM
   5412             // target window, such as when it was in a pop-up window,
   5413             // so let's also look at the current focus.  (An example:
   5414             // go to Gmail, start searching so the keyboard goes up,
   5415             // press home.  Sometimes the IME won't go down.)
   5416             // Would be nice to fix this more correctly, but it's
   5417             // way at the end of a release, and this should be good enough.
   5418             if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
   5419                     && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
   5420                 return true;
   5421             }
   5422         }
   5423         return false;
   5424     }
   5425 
   5426     @Override
   5427     public void getInitialDisplaySize(int displayId, Point size) {
   5428         synchronized (mWindowMap) {
   5429             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
   5430             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
   5431                 size.x = displayContent.mInitialDisplayWidth;
   5432                 size.y = displayContent.mInitialDisplayHeight;
   5433             }
   5434         }
   5435     }
   5436 
   5437     @Override
   5438     public void getBaseDisplaySize(int displayId, Point size) {
   5439         synchronized (mWindowMap) {
   5440             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
   5441             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
   5442                 size.x = displayContent.mBaseDisplayWidth;
   5443                 size.y = displayContent.mBaseDisplayHeight;
   5444             }
   5445         }
   5446     }
   5447 
   5448     @Override
   5449     public void setForcedDisplaySize(int displayId, int width, int height) {
   5450         if (mContext.checkCallingOrSelfPermission(
   5451                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
   5452                 PackageManager.PERMISSION_GRANTED) {
   5453             throw new SecurityException("Must hold permission " +
   5454                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
   5455         }
   5456         if (displayId != DEFAULT_DISPLAY) {
   5457             throw new IllegalArgumentException("Can only set the default display");
   5458         }
   5459         final long ident = Binder.clearCallingIdentity();
   5460         try {
   5461             synchronized(mWindowMap) {
   5462                 // Set some sort of reasonable bounds on the size of the display that we
   5463                 // will try to emulate.
   5464                 final int MIN_WIDTH = 200;
   5465                 final int MIN_HEIGHT = 200;
   5466                 final int MAX_SCALE = 2;
   5467                 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
   5468                 if (displayContent != null) {
   5469                     width = Math.min(Math.max(width, MIN_WIDTH),
   5470                             displayContent.mInitialDisplayWidth * MAX_SCALE);
   5471                     height = Math.min(Math.max(height, MIN_HEIGHT),
   5472                             displayContent.mInitialDisplayHeight * MAX_SCALE);
   5473                     setForcedDisplaySizeLocked(displayContent, width, height);
   5474                     Settings.Global.putString(mContext.getContentResolver(),
   5475                             Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
   5476                 }
   5477             }
   5478         } finally {
   5479             Binder.restoreCallingIdentity(ident);
   5480         }
   5481     }
   5482 
   5483     @Override
   5484     public void setForcedDisplayScalingMode(int displayId, int mode) {
   5485         if (mContext.checkCallingOrSelfPermission(
   5486                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
   5487                 PackageManager.PERMISSION_GRANTED) {
   5488             throw new SecurityException("Must hold permission " +
   5489                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
   5490         }
   5491         if (displayId != DEFAULT_DISPLAY) {
   5492             throw new IllegalArgumentException("Can only set the default display");
   5493         }
   5494         final long ident = Binder.clearCallingIdentity();
   5495         try {
   5496             synchronized(mWindowMap) {
   5497                 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
   5498                 if (displayContent != null) {
   5499                     if (mode < 0 || mode > 1) {
   5500                         mode = 0;
   5501                     }
   5502                     setForcedDisplayScalingModeLocked(displayContent, mode);
   5503                     Settings.Global.putInt(mContext.getContentResolver(),
   5504                             Settings.Global.DISPLAY_SCALING_FORCE, mode);
   5505                 }
   5506             }
   5507         } finally {
   5508             Binder.restoreCallingIdentity(ident);
   5509         }
   5510     }
   5511 
   5512     private void setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode) {
   5513         Slog.i(TAG_WM, "Using display scaling mode: " + (mode == 0 ? "auto" : "off"));
   5514         displayContent.mDisplayScalingDisabled = (mode != 0);
   5515         reconfigureDisplayLocked(displayContent);
   5516     }
   5517 
   5518     private void readForcedDisplayPropertiesLocked(final DisplayContent displayContent) {
   5519         // Display size.
   5520         String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
   5521                 Settings.Global.DISPLAY_SIZE_FORCED);
   5522         if (sizeStr == null || sizeStr.length() == 0) {
   5523             sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
   5524         }
   5525         if (sizeStr != null && sizeStr.length() > 0) {
   5526             final int pos = sizeStr.indexOf(',');
   5527             if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
   5528                 int width, height;
   5529                 try {
   5530                     width = Integer.parseInt(sizeStr.substring(0, pos));
   5531                     height = Integer.parseInt(sizeStr.substring(pos+1));
   5532                     if (displayContent.mBaseDisplayWidth != width
   5533                             || displayContent.mBaseDisplayHeight != height) {
   5534                         Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
   5535                         displayContent.updateBaseDisplayMetrics(width, height,
   5536                                 displayContent.mBaseDisplayDensity);
   5537                     }
   5538                 } catch (NumberFormatException ex) {
   5539                 }
   5540             }
   5541         }
   5542 
   5543         // Display density.
   5544         final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId);
   5545         if (density != 0) {
   5546             displayContent.mBaseDisplayDensity = density;
   5547         }
   5548 
   5549         // Display scaling mode.
   5550         int mode = Settings.Global.getInt(mContext.getContentResolver(),
   5551                 Settings.Global.DISPLAY_SCALING_FORCE, 0);
   5552         if (mode != 0) {
   5553             Slog.i(TAG_WM, "FORCED DISPLAY SCALING DISABLED");
   5554             displayContent.mDisplayScalingDisabled = true;
   5555         }
   5556     }
   5557 
   5558     // displayContent must not be null
   5559     private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
   5560         Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
   5561         displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity);
   5562         reconfigureDisplayLocked(displayContent);
   5563     }
   5564 
   5565     @Override
   5566     public void clearForcedDisplaySize(int displayId) {
   5567         if (mContext.checkCallingOrSelfPermission(
   5568                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
   5569                 PackageManager.PERMISSION_GRANTED) {
   5570             throw new SecurityException("Must hold permission " +
   5571                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
   5572         }
   5573         if (displayId != DEFAULT_DISPLAY) {
   5574             throw new IllegalArgumentException("Can only set the default display");
   5575         }
   5576         final long ident = Binder.clearCallingIdentity();
   5577         try {
   5578             synchronized(mWindowMap) {
   5579                 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
   5580                 if (displayContent != null) {
   5581                     setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
   5582                             displayContent.mInitialDisplayHeight);
   5583                     Settings.Global.putString(mContext.getContentResolver(),
   5584                             Settings.Global.DISPLAY_SIZE_FORCED, "");
   5585                 }
   5586             }
   5587         } finally {
   5588             Binder.restoreCallingIdentity(ident);
   5589         }
   5590     }
   5591 
   5592     @Override
   5593     public int getInitialDisplayDensity(int displayId) {
   5594         synchronized (mWindowMap) {
   5595             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
   5596             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
   5597                 return displayContent.mInitialDisplayDensity;
   5598             }
   5599         }
   5600         return -1;
   5601     }
   5602 
   5603     @Override
   5604     public int getBaseDisplayDensity(int displayId) {
   5605         synchronized (mWindowMap) {
   5606             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
   5607             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
   5608                 return displayContent.mBaseDisplayDensity;
   5609             }
   5610         }
   5611         return -1;
   5612     }
   5613 
   5614     @Override
   5615     public void setForcedDisplayDensityForUser(int displayId, int density, int userId) {
   5616         if (mContext.checkCallingOrSelfPermission(
   5617                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
   5618                 PackageManager.PERMISSION_GRANTED) {
   5619             throw new SecurityException("Must hold permission " +
   5620                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
   5621         }
   5622         if (displayId != DEFAULT_DISPLAY) {
   5623             throw new IllegalArgumentException("Can only set the default display");
   5624         }
   5625 
   5626         final int targetUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
   5627                 Binder.getCallingUid(), userId, false, true, "setForcedDisplayDensityForUser",
   5628                 null);
   5629         final long ident = Binder.clearCallingIdentity();
   5630         try {
   5631             synchronized(mWindowMap) {
   5632                 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
   5633                 if (displayContent != null && mCurrentUserId == targetUserId) {
   5634                     setForcedDisplayDensityLocked(displayContent, density);
   5635                 }
   5636                 Settings.Secure.putStringForUser(mContext.getContentResolver(),
   5637                         Settings.Secure.DISPLAY_DENSITY_FORCED,
   5638                         Integer.toString(density), targetUserId);
   5639             }
   5640         } finally {
   5641             Binder.restoreCallingIdentity(ident);
   5642         }
   5643     }
   5644 
   5645     @Override
   5646     public void clearForcedDisplayDensityForUser(int displayId, int userId) {
   5647         if (mContext.checkCallingOrSelfPermission(
   5648                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
   5649                 PackageManager.PERMISSION_GRANTED) {
   5650             throw new SecurityException("Must hold permission " +
   5651                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
   5652         }
   5653         if (displayId != DEFAULT_DISPLAY) {
   5654             throw new IllegalArgumentException("Can only set the default display");
   5655         }
   5656 
   5657         final int callingUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
   5658                 Binder.getCallingUid(), userId, false, true, "clearForcedDisplayDensityForUser",
   5659                 null);
   5660         final long ident = Binder.clearCallingIdentity();
   5661         try {
   5662             synchronized(mWindowMap) {
   5663                 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
   5664                 if (displayContent != null && mCurrentUserId == callingUserId) {
   5665                     setForcedDisplayDensityLocked(displayContent,
   5666                             displayContent.mInitialDisplayDensity);
   5667                 }
   5668                 Settings.Secure.putStringForUser(mContext.getContentResolver(),
   5669                         Settings.Secure.DISPLAY_DENSITY_FORCED, "", callingUserId);
   5670             }
   5671         } finally {
   5672             Binder.restoreCallingIdentity(ident);
   5673         }
   5674     }
   5675 
   5676     /**
   5677      * @param userId the ID of the user
   5678      * @return the forced display density for the specified user, if set, or
   5679      *         {@code 0} if not set
   5680      */
   5681     private int getForcedDisplayDensityForUserLocked(int userId) {
   5682         String densityStr = Settings.Secure.getStringForUser(mContext.getContentResolver(),
   5683                 Settings.Secure.DISPLAY_DENSITY_FORCED, userId);
   5684         if (densityStr == null || densityStr.length() == 0) {
   5685             densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
   5686         }
   5687         if (densityStr != null && densityStr.length() > 0) {
   5688             try {
   5689                 return Integer.parseInt(densityStr);
   5690             } catch (NumberFormatException ex) {
   5691             }
   5692         }
   5693         return 0;
   5694     }
   5695 
   5696     /**
   5697      * Forces the given display to the use the specified density.
   5698      *
   5699      * @param displayContent the display to modify
   5700      * @param density the density in DPI to use
   5701      */
   5702     private void setForcedDisplayDensityLocked(@NonNull DisplayContent displayContent,
   5703             int density) {
   5704         displayContent.mBaseDisplayDensity = density;
   5705         reconfigureDisplayLocked(displayContent);
   5706     }
   5707 
   5708     void reconfigureDisplayLocked(@NonNull DisplayContent displayContent) {
   5709         if (!mDisplayReady) {
   5710             return;
   5711         }
   5712         configureDisplayPolicyLocked(displayContent);
   5713         displayContent.setLayoutNeeded();
   5714 
   5715         final int displayId = displayContent.getDisplayId();
   5716         boolean configChanged = updateOrientationFromAppTokensLocked(false /* inTransaction */,
   5717                 displayId);
   5718         final Configuration currentDisplayConfig = displayContent.getConfiguration();
   5719         mTempConfiguration.setTo(currentDisplayConfig);
   5720         displayContent.computeScreenConfiguration(mTempConfiguration);
   5721         configChanged |= currentDisplayConfig.diff(mTempConfiguration) != 0;
   5722 
   5723         if (configChanged) {
   5724             mWaitingForConfig = true;
   5725             startFreezingDisplayLocked(false /* inTransaction */, 0 /* exitAnim */,
   5726                     0 /* enterAnim */, displayContent);
   5727             mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
   5728         }
   5729 
   5730         mWindowPlacerLocked.performSurfacePlacement();
   5731     }
   5732 
   5733     void configureDisplayPolicyLocked(DisplayContent displayContent) {
   5734         mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
   5735                 displayContent.mBaseDisplayWidth,
   5736                 displayContent.mBaseDisplayHeight,
   5737                 displayContent.mBaseDisplayDensity);
   5738 
   5739         DisplayInfo displayInfo = displayContent.getDisplayInfo();
   5740         mPolicy.setDisplayOverscan(displayContent.getDisplay(),
   5741                 displayInfo.overscanLeft, displayInfo.overscanTop,
   5742                 displayInfo.overscanRight, displayInfo.overscanBottom);
   5743     }
   5744 
   5745     /**
   5746      * Get an array with display ids ordered by focus priority - last items should be given
   5747      * focus first. Sparse array just maps position to displayId.
   5748      */
   5749     // TODO: Maintain display list in focus order in ActivityManager and remove this call.
   5750     public void getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder) {
   5751         synchronized(mWindowMap) {
   5752             mRoot.getDisplaysInFocusOrder(displaysInFocusOrder);
   5753         }
   5754     }
   5755 
   5756     @Override
   5757     public void setOverscan(int displayId, int left, int top, int right, int bottom) {
   5758         if (mContext.checkCallingOrSelfPermission(
   5759                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
   5760                 PackageManager.PERMISSION_GRANTED) {
   5761             throw new SecurityException("Must hold permission " +
   5762                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
   5763         }
   5764         final long ident = Binder.clearCallingIdentity();
   5765         try {
   5766             synchronized(mWindowMap) {
   5767                 DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
   5768                 if (displayContent != null) {
   5769                     setOverscanLocked(displayContent, left, top, right, bottom);
   5770                 }
   5771             }
   5772         } finally {
   5773             Binder.restoreCallingIdentity(ident);
   5774         }
   5775     }
   5776 
   5777     private void setOverscanLocked(DisplayContent displayContent,
   5778             int left, int top, int right, int bottom) {
   5779         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
   5780         displayInfo.overscanLeft = left;
   5781         displayInfo.overscanTop = top;
   5782         displayInfo.overscanRight = right;
   5783         displayInfo.overscanBottom = bottom;
   5784 
   5785         mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, displayInfo.name, left, top,
   5786                 right, bottom);
   5787         mDisplaySettings.writeSettingsLocked();
   5788 
   5789         reconfigureDisplayLocked(displayContent);
   5790     }
   5791 
   5792     // -------------------------------------------------------------
   5793     // Internals
   5794     // -------------------------------------------------------------
   5795 
   5796     final WindowState windowForClientLocked(Session session, IWindow client, boolean throwOnError) {
   5797         return windowForClientLocked(session, client.asBinder(), throwOnError);
   5798     }
   5799 
   5800     final WindowState windowForClientLocked(Session session, IBinder client, boolean throwOnError) {
   5801         WindowState win = mWindowMap.get(client);
   5802         if (localLOGV) Slog.v(TAG_WM, "Looking up client " + client + ": " + win);
   5803         if (win == null) {
   5804             if (throwOnError) {
   5805                 throw new IllegalArgumentException(
   5806                         "Requested window " + client + " does not exist");
   5807             }
   5808             Slog.w(TAG_WM, "Failed looking up window callers=" + Debug.getCallers(3));
   5809             return null;
   5810         }
   5811         if (session != null && win.mSession != session) {
   5812             if (throwOnError) {
   5813                 throw new IllegalArgumentException("Requested window " + client + " is in session "
   5814                         + win.mSession + ", not " + session);
   5815             }
   5816             Slog.w(TAG_WM, "Failed looking up window callers=" + Debug.getCallers(3));
   5817             return null;
   5818         }
   5819 
   5820         return win;
   5821     }
   5822 
   5823     void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
   5824         // If the screen is currently frozen or off, then keep
   5825         // it frozen/off until this window draws at its new
   5826         // orientation.
   5827         if (!w.mToken.okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
   5828             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w);
   5829             w.setOrientationChanging(true);
   5830             w.mLastFreezeDuration = 0;
   5831             mRoot.mOrientationChangeComplete = false;
   5832             if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) {
   5833                 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
   5834                 // XXX should probably keep timeout from
   5835                 // when we first froze the display.
   5836                 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
   5837                 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
   5838                         WINDOW_FREEZE_TIMEOUT_DURATION);
   5839             }
   5840         }
   5841     }
   5842 
   5843     /**
   5844      * @return bitmap indicating if another pass through layout must be made.
   5845      */
   5846     int handleAnimatingStoppedAndTransitionLocked() {
   5847         int changes = 0;
   5848 
   5849         mAppTransition.setIdle();
   5850 
   5851         for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) {
   5852             final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i);
   5853             mAppTransition.notifyAppTransitionFinishedLocked(token);
   5854         }
   5855         mNoAnimationNotifyOnTransitionFinished.clear();
   5856 
   5857         // TODO: multi-display.
   5858         final DisplayContent dc = getDefaultDisplayContentLocked();
   5859 
   5860         dc.mWallpaperController.hideDeferredWallpapersIfNeeded();
   5861 
   5862         dc.onAppTransitionDone();
   5863 
   5864         changes |= FINISH_LAYOUT_REDO_LAYOUT;
   5865         if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM,
   5866                 "Wallpaper layer changed: assigning layers + relayout");
   5867         dc.computeImeTarget(true /* updateImeTarget */);
   5868         mRoot.mWallpaperMayChange = true;
   5869         // Since the window list has been rebuilt, focus might have to be recomputed since the
   5870         // actual order of windows might have changed again.
   5871         mFocusMayChange = true;
   5872 
   5873         return changes;
   5874     }
   5875 
   5876     void checkDrawnWindowsLocked() {
   5877         if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
   5878             return;
   5879         }
   5880         for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
   5881             WindowState win = mWaitingForDrawn.get(j);
   5882             if (DEBUG_SCREEN_ON) Slog.i(TAG_WM, "Waiting for drawn " + win +
   5883                     ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
   5884                     " mHasSurface=" + win.mHasSurface +
   5885                     " drawState=" + win.mWinAnimator.mDrawState);
   5886             if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) {
   5887                 // Window has been removed or hidden; no draw will now happen, so stop waiting.
   5888                 if (DEBUG_SCREEN_ON) Slog.w(TAG_WM, "Aborted waiting for drawn: " + win);
   5889                 mWaitingForDrawn.remove(win);
   5890             } else if (win.hasDrawnLw()) {
   5891                 // Window is now drawn (and shown).
   5892                 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "Window drawn win=" + win);
   5893                 mWaitingForDrawn.remove(win);
   5894             }
   5895         }
   5896         if (mWaitingForDrawn.isEmpty()) {
   5897             if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "All windows drawn!");
   5898             mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
   5899             mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
   5900         }
   5901     }
   5902 
   5903     void setHoldScreenLocked(final Session newHoldScreen) {
   5904         final boolean hold = newHoldScreen != null;
   5905 
   5906         if (hold && mHoldingScreenOn != newHoldScreen) {
   5907             mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
   5908         }
   5909         mHoldingScreenOn = newHoldScreen;
   5910 
   5911         final boolean state = mHoldingScreenWakeLock.isHeld();
   5912         if (hold != state) {
   5913             if (hold) {
   5914                 if (DEBUG_KEEP_SCREEN_ON) {
   5915                     Slog.d(TAG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to "
   5916                             + mRoot.mHoldScreenWindow);
   5917                 }
   5918                 mLastWakeLockHoldingWindow = mRoot.mHoldScreenWindow;
   5919                 mLastWakeLockObscuringWindow = null;
   5920                 mHoldingScreenWakeLock.acquire();
   5921                 mPolicy.keepScreenOnStartedLw();
   5922             } else {
   5923                 if (DEBUG_KEEP_SCREEN_ON) {
   5924                     Slog.d(TAG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by "
   5925                             + mRoot.mObscuringWindow);
   5926                 }
   5927                 mLastWakeLockHoldingWindow = null;
   5928                 mLastWakeLockObscuringWindow = mRoot.mObscuringWindow;
   5929                 mPolicy.keepScreenOnStoppedLw();
   5930                 mHoldingScreenWakeLock.release();
   5931             }
   5932         }
   5933     }
   5934 
   5935     void requestTraversal() {
   5936         synchronized (mWindowMap) {
   5937             mWindowPlacerLocked.requestTraversal();
   5938         }
   5939     }
   5940 
   5941     /** Note that Locked in this case is on mLayoutToAnim */
   5942     void scheduleAnimationLocked() {
   5943         mAnimator.scheduleAnimation();
   5944     }
   5945 
   5946     // TODO: Move to DisplayContent
   5947     boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
   5948         WindowState newFocus = mRoot.computeFocusedWindow();
   5949         if (mCurrentFocus != newFocus) {
   5950             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
   5951             // This check makes sure that we don't already have the focus
   5952             // change message pending.
   5953             mH.removeMessages(H.REPORT_FOCUS_CHANGE);
   5954             mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
   5955             // TODO(multidisplay): Focused windows on default display only.
   5956             final DisplayContent displayContent = getDefaultDisplayContentLocked();
   5957             boolean imWindowChanged = false;
   5958             if (mInputMethodWindow != null) {
   5959                 final WindowState prevTarget = mInputMethodTarget;
   5960                 final WindowState newTarget =
   5961                         displayContent.computeImeTarget(true /* updateImeTarget*/);
   5962 
   5963                 imWindowChanged = prevTarget != newTarget;
   5964 
   5965                 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
   5966                         && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) {
   5967                     final int prevImeAnimLayer = mInputMethodWindow.mWinAnimator.mAnimLayer;
   5968                     displayContent.assignWindowLayers(false /* setLayoutNeeded */);
   5969                     imWindowChanged |=
   5970                             prevImeAnimLayer != mInputMethodWindow.mWinAnimator.mAnimLayer;
   5971                 }
   5972             }
   5973 
   5974             if (imWindowChanged) {
   5975                 mWindowsChanged = true;
   5976                 displayContent.setLayoutNeeded();
   5977                 newFocus = mRoot.computeFocusedWindow();
   5978             }
   5979 
   5980             if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG_WM, "Changing focus from " +
   5981                     mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
   5982             final WindowState oldFocus = mCurrentFocus;
   5983             mCurrentFocus = newFocus;
   5984             mLosingFocus.remove(newFocus);
   5985 
   5986             if (mCurrentFocus != null) {
   5987                 mWinAddedSinceNullFocus.clear();
   5988                 mWinRemovedSinceNullFocus.clear();
   5989             }
   5990 
   5991             int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
   5992 
   5993             if (imWindowChanged && oldFocus != mInputMethodWindow) {
   5994                 // Focus of the input method window changed. Perform layout if needed.
   5995                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
   5996                     displayContent.performLayout(true /*initial*/,  updateInputWindows);
   5997                     focusChanged &= ~FINISH_LAYOUT_REDO_LAYOUT;
   5998                 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
   5999                     // Client will do the layout, but we need to assign layers
   6000                     // for handleNewWindowLocked() below.
   6001                     displayContent.assignWindowLayers(false /* setLayoutNeeded */);
   6002                 }
   6003             }
   6004 
   6005             if ((focusChanged & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
   6006                 // The change in focus caused us to need to do a layout.  Okay.
   6007                 displayContent.setLayoutNeeded();
   6008                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
   6009                     displayContent.performLayout(true /*initial*/, updateInputWindows);
   6010                 }
   6011             }
   6012 
   6013             if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
   6014                 // If we defer assigning layers, then the caller is responsible for
   6015                 // doing this part.
   6016                 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
   6017             }
   6018 
   6019             displayContent.adjustForImeIfNeeded();
   6020 
   6021             // We may need to schedule some toast windows to be removed. The toasts for an app that
   6022             // does not have input focus are removed within a timeout to prevent apps to redress
   6023             // other apps' UI.
   6024             displayContent.scheduleToastWindowsTimeoutIfNeededLocked(oldFocus, newFocus);
   6025 
   6026             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
   6027             return true;
   6028         }
   6029         return false;
   6030     }
   6031 
   6032     void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
   6033         startFreezingDisplayLocked(inTransaction, exitAnim, enterAnim,
   6034                 getDefaultDisplayContentLocked());
   6035     }
   6036 
   6037     void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim,
   6038             DisplayContent displayContent) {
   6039         if (mDisplayFrozen) {
   6040             return;
   6041         }
   6042 
   6043         if (!displayContent.isReady() || !mPolicy.isScreenOn() || !displayContent.okToAnimate()) {
   6044             // No need to freeze the screen before the display is ready,  if the screen is off,
   6045             // or we can't currently animate.
   6046             return;
   6047         }
   6048 
   6049         if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
   6050                 "startFreezingDisplayLocked: inTransaction=" + inTransaction
   6051                 + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim
   6052                 + " called by " + Debug.getCallers(8));
   6053         mScreenFrozenLock.acquire();
   6054 
   6055         mDisplayFrozen = true;
   6056         mDisplayFreezeTime = SystemClock.elapsedRealtime();
   6057         mLastFinishedFreezeSource = null;
   6058 
   6059         // {@link mDisplayFrozen} prevents us from freezing on multiple displays at the same time.
   6060         // As a result, we only track the display that has initially froze the screen.
   6061         mFrozenDisplayId = displayContent.getDisplayId();
   6062 
   6063         mInputMonitor.freezeInputDispatchingLw();
   6064 
   6065         // Clear the last input window -- that is just used for
   6066         // clean transitions between IMEs, and if we are freezing
   6067         // the screen then the whole world is changing behind the scenes.
   6068         mPolicy.setLastInputMethodWindowLw(null, null);
   6069 
   6070         if (mAppTransition.isTransitionSet()) {
   6071             mAppTransition.freeze();
   6072         }
   6073 
   6074         if (PROFILE_ORIENTATION) {
   6075             File file = new File("/data/system/frozen");
   6076             Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
   6077         }
   6078 
   6079         // TODO(multidisplay): rotation on non-default displays
   6080         if (CUSTOM_SCREEN_ROTATION && displayContent.isDefaultDisplay) {
   6081             mExitAnimId = exitAnim;
   6082             mEnterAnimId = enterAnim;
   6083             ScreenRotationAnimation screenRotationAnimation =
   6084                     mAnimator.getScreenRotationAnimationLocked(mFrozenDisplayId);
   6085             if (screenRotationAnimation != null) {
   6086                 screenRotationAnimation.kill();
   6087             }
   6088 
   6089             // Check whether the current screen contains any secure content.
   6090             boolean isSecure = displayContent.hasSecureWindowOnScreen();
   6091 
   6092             displayContent.updateDisplayInfo();
   6093             screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
   6094                     mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure,
   6095                     this);
   6096             mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
   6097                     screenRotationAnimation);
   6098         }
   6099     }
   6100 
   6101     void stopFreezingDisplayLocked() {
   6102         if (!mDisplayFrozen) {
   6103             return;
   6104         }
   6105 
   6106         if (mWaitingForConfig || mAppsFreezingScreen > 0
   6107                 || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE
   6108                 || mClientFreezingScreen || !mOpeningApps.isEmpty()) {
   6109             if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
   6110                 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
   6111                 + ", mAppsFreezingScreen=" + mAppsFreezingScreen
   6112                 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
   6113                 + ", mClientFreezingScreen=" + mClientFreezingScreen
   6114                 + ", mOpeningApps.size()=" + mOpeningApps.size());
   6115             return;
   6116         }
   6117 
   6118         if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
   6119                 "stopFreezingDisplayLocked: Unfreezing now");
   6120 
   6121         final DisplayContent displayContent = mRoot.getDisplayContent(mFrozenDisplayId);
   6122 
   6123         // We must make a local copy of the displayId as it can be potentially overwritten later on
   6124         // in this method. For example, {@link startFreezingDisplayLocked} may be called as a result
   6125         // of update rotation, but we reference the frozen display after that call in this method.
   6126         final int displayId = mFrozenDisplayId;
   6127         mFrozenDisplayId = INVALID_DISPLAY;
   6128         mDisplayFrozen = false;
   6129         mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
   6130         StringBuilder sb = new StringBuilder(128);
   6131         sb.append("Screen frozen for ");
   6132         TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
   6133         if (mLastFinishedFreezeSource != null) {
   6134             sb.append(" due to ");
   6135             sb.append(mLastFinishedFreezeSource);
   6136         }
   6137         Slog.i(TAG_WM, sb.toString());
   6138         mH.removeMessages(H.APP_FREEZE_TIMEOUT);
   6139         mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
   6140         if (PROFILE_ORIENTATION) {
   6141             Debug.stopMethodTracing();
   6142         }
   6143 
   6144         boolean updateRotation = false;
   6145 
   6146         ScreenRotationAnimation screenRotationAnimation =
   6147                 mAnimator.getScreenRotationAnimationLocked(displayId);
   6148         if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
   6149                 && screenRotationAnimation.hasScreenshot()) {
   6150             if (DEBUG_ORIENTATION) Slog.i(TAG_WM, "**** Dismissing screen rotation animation");
   6151             // TODO(multidisplay): rotation on main screen only.
   6152             DisplayInfo displayInfo = displayContent.getDisplayInfo();
   6153             // Get rotation animation again, with new top window
   6154             boolean isDimming = displayContent.isDimming();
   6155             if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
   6156                 mExitAnimId = mEnterAnimId = 0;
   6157             }
   6158             if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
   6159                     getTransitionAnimationScaleLocked(), displayInfo.logicalWidth,
   6160                         displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
   6161                 scheduleAnimationLocked();
   6162             } else {
   6163                 screenRotationAnimation.kill();
   6164                 mAnimator.setScreenRotationAnimationLocked(displayId, null);
   6165                 updateRotation = true;
   6166             }
   6167         } else {
   6168             if (screenRotationAnimation != null) {
   6169                 screenRotationAnimation.kill();
   6170                 mAnimator.setScreenRotationAnimationLocked(displayId, null);
   6171             }
   6172             updateRotation = true;
   6173         }
   6174 
   6175         mInputMonitor.thawInputDispatchingLw();
   6176 
   6177         boolean configChanged;
   6178 
   6179         // While the display is frozen we don't re-compute the orientation
   6180         // to avoid inconsistent states.  However, something interesting
   6181         // could have actually changed during that time so re-evaluate it
   6182         // now to catch that.
   6183         configChanged = updateOrientationFromAppTokensLocked(false, displayId);
   6184 
   6185         // A little kludge: a lot could have happened while the
   6186         // display was frozen, so now that we are coming back we
   6187         // do a gc so that any remote references the system
   6188         // processes holds on others can be released if they are
   6189         // no longer needed.
   6190         mH.removeMessages(H.FORCE_GC);
   6191         mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
   6192 
   6193         mScreenFrozenLock.release();
   6194 
   6195         if (updateRotation) {
   6196             if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation");
   6197             configChanged |= displayContent.updateRotationUnchecked(
   6198                     false /* inTransaction */);
   6199         }
   6200 
   6201         if (configChanged) {
   6202             mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
   6203         }
   6204     }
   6205 
   6206     static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
   6207             DisplayMetrics dm) {
   6208         if (index < tokens.length) {
   6209             String str = tokens[index];
   6210             if (str != null && str.length() > 0) {
   6211                 try {
   6212                     int val = Integer.parseInt(str);
   6213                     return val;
   6214                 } catch (Exception e) {
   6215                 }
   6216             }
   6217         }
   6218         if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
   6219             return defDps;
   6220         }
   6221         int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
   6222         return val;
   6223     }
   6224 
   6225     void createWatermarkInTransaction() {
   6226         if (mWatermark != null) {
   6227             return;
   6228         }
   6229 
   6230         File file = new File("/system/etc/setup.conf");
   6231         FileInputStream in = null;
   6232         DataInputStream ind = null;
   6233         try {
   6234             in = new FileInputStream(file);
   6235             ind = new DataInputStream(in);
   6236             String line = ind.readLine();
   6237             if (line != null) {
   6238                 String[] toks = line.split("%");
   6239                 if (toks != null && toks.length > 0) {
   6240                     // TODO(multi-display): Show watermarks on secondary displays.
   6241                     final DisplayContent displayContent = getDefaultDisplayContentLocked();
   6242                     mWatermark = new Watermark(displayContent.getDisplay(),
   6243                             displayContent.mRealDisplayMetrics, mFxSession, toks);
   6244                 }
   6245             }
   6246         } catch (FileNotFoundException e) {
   6247         } catch (IOException e) {
   6248         } finally {
   6249             if (ind != null) {
   6250                 try {
   6251                     ind.close();
   6252                 } catch (IOException e) {
   6253                 }
   6254             } else if (in != null) {
   6255                 try {
   6256                     in.close();
   6257                 } catch (IOException e) {
   6258                 }
   6259             }
   6260         }
   6261     }
   6262 
   6263     @Override
   6264     public void setRecentsVisibility(boolean visible) {
   6265         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
   6266                 != PackageManager.PERMISSION_GRANTED) {
   6267             throw new SecurityException("Caller does not hold permission "
   6268                     + android.Manifest.permission.STATUS_BAR);
   6269         }
   6270 
   6271         synchronized (mWindowMap) {
   6272             mPolicy.setRecentsVisibilityLw(visible);
   6273         }
   6274     }
   6275 
   6276     @Override
   6277     public void setPipVisibility(boolean visible) {
   6278         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
   6279                 != PackageManager.PERMISSION_GRANTED) {
   6280             throw new SecurityException("Caller does not hold permission "
   6281                     + android.Manifest.permission.STATUS_BAR);
   6282         }
   6283 
   6284         synchronized (mWindowMap) {
   6285             mPolicy.setPipVisibilityLw(visible);
   6286         }
   6287     }
   6288 
   6289     @Override
   6290     public void statusBarVisibilityChanged(int visibility) {
   6291         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
   6292                 != PackageManager.PERMISSION_GRANTED) {
   6293             throw new SecurityException("Caller does not hold permission "
   6294                     + android.Manifest.permission.STATUS_BAR);
   6295         }
   6296 
   6297         synchronized (mWindowMap) {
   6298             mLastStatusBarVisibility = visibility;
   6299             visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
   6300             updateStatusBarVisibilityLocked(visibility);
   6301         }
   6302     }
   6303 
   6304     // TODO(multidisplay): StatusBar on multiple screens?
   6305     private boolean updateStatusBarVisibilityLocked(int visibility) {
   6306         if (mLastDispatchedSystemUiVisibility == visibility) {
   6307             return false;
   6308         }
   6309         final int globalDiff = (visibility ^ mLastDispatchedSystemUiVisibility)
   6310                 // We are only interested in differences of one of the
   6311                 // clearable flags...
   6312                 & View.SYSTEM_UI_CLEARABLE_FLAGS
   6313                 // ...if it has actually been cleared.
   6314                 & ~visibility;
   6315 
   6316         mLastDispatchedSystemUiVisibility = visibility;
   6317         mInputManager.setSystemUiVisibility(visibility);
   6318         getDefaultDisplayContentLocked().updateSystemUiVisibility(visibility, globalDiff);
   6319         return true;
   6320     }
   6321 
   6322     @Override
   6323     public void reevaluateStatusBarVisibility() {
   6324         synchronized (mWindowMap) {
   6325             int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
   6326             if (updateStatusBarVisibilityLocked(visibility)) {
   6327                 mWindowPlacerLocked.requestTraversal();
   6328             }
   6329         }
   6330     }
   6331 
   6332     /**
   6333      * Used by ActivityManager to determine where to position an app with aspect ratio shorter then
   6334      * the screen is.
   6335      * @see WindowManagerPolicy#getNavBarPosition()
   6336      */
   6337     public int getNavBarPosition() {
   6338         synchronized (mWindowMap) {
   6339             // Perform layout if it was scheduled before to make sure that we get correct nav bar
   6340             // position when doing rotations.
   6341             final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
   6342             defaultDisplayContent.performLayout(false /* initial */,
   6343                     false /* updateInputWindows */);
   6344             return mPolicy.getNavBarPosition();
   6345         }
   6346     }
   6347 
   6348     @Override
   6349     public WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name,
   6350             InputEventReceiver.Factory inputEventReceiverFactory) {
   6351         synchronized (mWindowMap) {
   6352             return mInputMonitor.createInputConsumer(looper, name, inputEventReceiverFactory);
   6353         }
   6354     }
   6355 
   6356     @Override
   6357     public void createInputConsumer(String name, InputChannel inputChannel) {
   6358         synchronized (mWindowMap) {
   6359             mInputMonitor.createInputConsumer(name, inputChannel);
   6360         }
   6361     }
   6362 
   6363     @Override
   6364     public boolean destroyInputConsumer(String name) {
   6365         synchronized (mWindowMap) {
   6366             return mInputMonitor.destroyInputConsumer(name);
   6367         }
   6368     }
   6369 
   6370     @Override
   6371     public Region getCurrentImeTouchRegion() {
   6372         if (mContext.checkCallingOrSelfPermission(RESTRICTED_VR_ACCESS) != PERMISSION_GRANTED) {
   6373             throw new SecurityException("getCurrentImeTouchRegion is restricted to VR services");
   6374         }
   6375         synchronized (mWindowMap) {
   6376             final Region r = new Region();
   6377             if (mInputMethodWindow != null) {
   6378                 mInputMethodWindow.getTouchableRegion(r);
   6379             }
   6380             return r;
   6381         }
   6382     }
   6383 
   6384     @Override
   6385     public boolean hasNavigationBar() {
   6386         return mPolicy.hasNavigationBar();
   6387     }
   6388 
   6389     @Override
   6390     public void lockNow(Bundle options) {
   6391         mPolicy.lockNow(options);
   6392     }
   6393 
   6394     public void showRecentApps(boolean fromHome) {
   6395         mPolicy.showRecentApps(fromHome);
   6396     }
   6397 
   6398     @Override
   6399     public boolean isSafeModeEnabled() {
   6400         return mSafeMode;
   6401     }
   6402 
   6403     @Override
   6404     public boolean clearWindowContentFrameStats(IBinder token) {
   6405         if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
   6406                 "clearWindowContentFrameStats()")) {
   6407             throw new SecurityException("Requires FRAME_STATS permission");
   6408         }
   6409         synchronized (mWindowMap) {
   6410             WindowState windowState = mWindowMap.get(token);
   6411             if (windowState == null) {
   6412                 return false;
   6413             }
   6414             WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
   6415             if (surfaceController == null) {
   6416                 return false;
   6417             }
   6418             return surfaceController.clearWindowContentFrameStats();
   6419         }
   6420     }
   6421 
   6422     @Override
   6423     public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
   6424         if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
   6425                 "getWindowContentFrameStats()")) {
   6426             throw new SecurityException("Requires FRAME_STATS permission");
   6427         }
   6428         synchronized (mWindowMap) {
   6429             WindowState windowState = mWindowMap.get(token);
   6430             if (windowState == null) {
   6431                 return null;
   6432             }
   6433             WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
   6434             if (surfaceController == null) {
   6435                 return null;
   6436             }
   6437             if (mTempWindowRenderStats == null) {
   6438                 mTempWindowRenderStats = new WindowContentFrameStats();
   6439             }
   6440             WindowContentFrameStats stats = mTempWindowRenderStats;
   6441             if (!surfaceController.getWindowContentFrameStats(stats)) {
   6442                 return null;
   6443             }
   6444             return stats;
   6445         }
   6446     }
   6447 
   6448     public void notifyAppRelaunching(IBinder token) {
   6449         synchronized (mWindowMap) {
   6450             final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
   6451             if (appWindow != null) {
   6452                 appWindow.startRelaunching();
   6453             }
   6454         }
   6455     }
   6456 
   6457     public void notifyAppRelaunchingFinished(IBinder token) {
   6458         synchronized (mWindowMap) {
   6459             final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
   6460             if (appWindow != null) {
   6461                 appWindow.finishRelaunching();
   6462             }
   6463         }
   6464     }
   6465 
   6466     public void notifyAppRelaunchesCleared(IBinder token) {
   6467         synchronized (mWindowMap) {
   6468             final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
   6469             if (appWindow != null) {
   6470                 appWindow.clearRelaunching();
   6471             }
   6472         }
   6473     }
   6474 
   6475     public void notifyAppResumedFinished(IBinder token) {
   6476         synchronized (mWindowMap) {
   6477             final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
   6478             if (appWindow != null) {
   6479                 mUnknownAppVisibilityController.notifyAppResumedFinished(appWindow);
   6480             }
   6481         }
   6482     }
   6483 
   6484     /**
   6485      * Called when a task has been removed from the recent tasks list.
   6486      * <p>
   6487      * Note: This doesn't go through {@link TaskWindowContainerController} yet as the window
   6488      * container may not exist when this happens.
   6489      */
   6490     public void notifyTaskRemovedFromRecents(int taskId, int userId) {
   6491         synchronized (mWindowMap) {
   6492             mTaskSnapshotController.notifyTaskRemovedFromRecents(taskId, userId);
   6493         }
   6494     }
   6495 
   6496     @Override
   6497     public int getDockedDividerInsetsLw() {
   6498         return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets();
   6499     }
   6500 
   6501     private void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
   6502         pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
   6503         mPolicy.dump("    ", pw, args);
   6504     }
   6505 
   6506     private void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
   6507         pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
   6508         mAnimator.dumpLocked(pw, "    ", dumpAll);
   6509     }
   6510 
   6511     private void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
   6512         pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
   6513         mRoot.dumpTokens(pw, dumpAll);
   6514         if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty()) {
   6515             pw.println();
   6516             if (mOpeningApps.size() > 0) {
   6517                 pw.print("  mOpeningApps="); pw.println(mOpeningApps);
   6518             }
   6519             if (mClosingApps.size() > 0) {
   6520                 pw.print("  mClosingApps="); pw.println(mClosingApps);
   6521             }
   6522         }
   6523     }
   6524 
   6525     private void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
   6526         pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
   6527         for (int i=0; i<mSessions.size(); i++) {
   6528             Session s = mSessions.valueAt(i);
   6529             pw.print("  Session "); pw.print(s); pw.println(':');
   6530             s.dump(pw, "    ");
   6531         }
   6532     }
   6533 
   6534     private void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
   6535             ArrayList<WindowState> windows) {
   6536         pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
   6537         dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
   6538     }
   6539 
   6540     private void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
   6541             ArrayList<WindowState> windows) {
   6542         mRoot.dumpWindowsNoHeader(pw, dumpAll, windows);
   6543 
   6544         if (!mHidingNonSystemOverlayWindows.isEmpty()) {
   6545             pw.println();
   6546             pw.println("  Hiding System Alert Windows:");
   6547             for (int i = mHidingNonSystemOverlayWindows.size() - 1; i >= 0; i--) {
   6548                 final WindowState w = mHidingNonSystemOverlayWindows.get(i);
   6549                 pw.print("  #"); pw.print(i); pw.print(' ');
   6550                 pw.print(w);
   6551                 if (dumpAll) {
   6552                     pw.println(":");
   6553                     w.dump(pw, "    ", true);
   6554                 } else {
   6555                     pw.println();
   6556                 }
   6557             }
   6558         }
   6559         if (mPendingRemove.size() > 0) {
   6560             pw.println();
   6561             pw.println("  Remove pending for:");
   6562             for (int i=mPendingRemove.size()-1; i>=0; i--) {
   6563                 WindowState w = mPendingRemove.get(i);
   6564                 if (windows == null || windows.contains(w)) {
   6565                     pw.print("  Remove #"); pw.print(i); pw.print(' ');
   6566                             pw.print(w);
   6567                     if (dumpAll) {
   6568                         pw.println(":");
   6569                         w.dump(pw, "    ", true);
   6570                     } else {
   6571                         pw.println();
   6572                     }
   6573                 }
   6574             }
   6575         }
   6576         if (mForceRemoves != null && mForceRemoves.size() > 0) {
   6577             pw.println();
   6578             pw.println("  Windows force removing:");
   6579             for (int i=mForceRemoves.size()-1; i>=0; i--) {
   6580                 WindowState w = mForceRemoves.get(i);
   6581                 pw.print("  Removing #"); pw.print(i); pw.print(' ');
   6582                         pw.print(w);
   6583                 if (dumpAll) {
   6584                     pw.println(":");
   6585                     w.dump(pw, "    ", true);
   6586                 } else {
   6587                     pw.println();
   6588                 }
   6589             }
   6590         }
   6591         if (mDestroySurface.size() > 0) {
   6592             pw.println();
   6593             pw.println("  Windows waiting to destroy their surface:");
   6594             for (int i=mDestroySurface.size()-1; i>=0; i--) {
   6595                 WindowState w = mDestroySurface.get(i);
   6596                 if (windows == null || windows.contains(w)) {
   6597                     pw.print("  Destroy #"); pw.print(i); pw.print(' ');
   6598                             pw.print(w);
   6599                     if (dumpAll) {
   6600                         pw.println(":");
   6601                         w.dump(pw, "    ", true);
   6602                     } else {
   6603                         pw.println();
   6604                     }
   6605                 }
   6606             }
   6607         }
   6608         if (mLosingFocus.size() > 0) {
   6609             pw.println();
   6610             pw.println("  Windows losing focus:");
   6611             for (int i=mLosingFocus.size()-1; i>=0; i--) {
   6612                 WindowState w = mLosingFocus.get(i);
   6613                 if (windows == null || windows.contains(w)) {
   6614                     pw.print("  Losing #"); pw.print(i); pw.print(' ');
   6615                             pw.print(w);
   6616                     if (dumpAll) {
   6617                         pw.println(":");
   6618                         w.dump(pw, "    ", true);
   6619                     } else {
   6620                         pw.println();
   6621                     }
   6622                 }
   6623             }
   6624         }
   6625         if (mResizingWindows.size() > 0) {
   6626             pw.println();
   6627             pw.println("  Windows waiting to resize:");
   6628             for (int i=mResizingWindows.size()-1; i>=0; i--) {
   6629                 WindowState w = mResizingWindows.get(i);
   6630                 if (windows == null || windows.contains(w)) {
   6631                     pw.print("  Resizing #"); pw.print(i); pw.print(' ');
   6632                             pw.print(w);
   6633                     if (dumpAll) {
   6634                         pw.println(":");
   6635                         w.dump(pw, "    ", true);
   6636                     } else {
   6637                         pw.println();
   6638                     }
   6639                 }
   6640             }
   6641         }
   6642         if (mWaitingForDrawn.size() > 0) {
   6643             pw.println();
   6644             pw.println("  Clients waiting for these windows to be drawn:");
   6645             for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
   6646                 WindowState win = mWaitingForDrawn.get(i);
   6647                 pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
   6648             }
   6649         }
   6650         pw.println();
   6651         pw.print("  mGlobalConfiguration="); pw.println(mRoot.getConfiguration());
   6652         pw.print("  mHasPermanentDpad="); pw.println(mHasPermanentDpad);
   6653         pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
   6654         if (mLastFocus != mCurrentFocus) {
   6655             pw.print("  mLastFocus="); pw.println(mLastFocus);
   6656         }
   6657         pw.print("  mFocusedApp="); pw.println(mFocusedApp);
   6658         if (mInputMethodTarget != null) {
   6659             pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
   6660         }
   6661         pw.print("  mInTouchMode="); pw.print(mInTouchMode);
   6662                 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
   6663         pw.print("  mLastDisplayFreezeDuration=");
   6664                 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
   6665                 if ( mLastFinishedFreezeSource != null) {
   6666                     pw.print(" due to ");
   6667                     pw.print(mLastFinishedFreezeSource);
   6668                 }
   6669                 pw.println();
   6670         pw.print("  mLastWakeLockHoldingWindow=");pw.print(mLastWakeLockHoldingWindow);
   6671                 pw.print(" mLastWakeLockObscuringWindow="); pw.print(mLastWakeLockObscuringWindow);
   6672                 pw.println();
   6673 
   6674         mInputMonitor.dump(pw, "  ");
   6675         mUnknownAppVisibilityController.dump(pw, "  ");
   6676         mTaskSnapshotController.dump(pw, "  ");
   6677 
   6678         if (dumpAll) {
   6679             pw.print("  mSystemDecorLayer="); pw.print(mSystemDecorLayer);
   6680                     pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
   6681             if (mLastStatusBarVisibility != 0) {
   6682                 pw.print("  mLastStatusBarVisibility=0x");
   6683                         pw.println(Integer.toHexString(mLastStatusBarVisibility));
   6684             }
   6685             if (mInputMethodWindow != null) {
   6686                 pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
   6687             }
   6688             mWindowPlacerLocked.dump(pw, "  ");
   6689             mRoot.mWallpaperController.dump(pw, "  ");
   6690             pw.print("  mSystemBooted="); pw.print(mSystemBooted);
   6691                     pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
   6692 
   6693             mRoot.dumpLayoutNeededDisplayIds(pw);
   6694 
   6695             pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
   6696             pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
   6697                     pw.print(" windows="); pw.print(mWindowsFreezingScreen);
   6698                     pw.print(" client="); pw.print(mClientFreezingScreen);
   6699                     pw.print(" apps="); pw.print(mAppsFreezingScreen);
   6700                     pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
   6701             final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
   6702             pw.print("  mRotation="); pw.print(defaultDisplayContent.getRotation());
   6703                     pw.print(" mAltOrientation=");
   6704                             pw.println(defaultDisplayContent.getAltOrientation());
   6705             pw.print("  mLastWindowForcedOrientation=");
   6706                     pw.print(defaultDisplayContent.getLastWindowForcedOrientation());
   6707                     pw.print(" mLastOrientation=");
   6708                             pw.println(defaultDisplayContent.getLastOrientation());
   6709             pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
   6710             pw.print("  Animation settings: disabled="); pw.print(mAnimationsDisabled);
   6711                     pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
   6712                     pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
   6713                     pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting);
   6714             pw.print("  mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation);
   6715             pw.println("  mLayoutToAnim:");
   6716             mAppTransition.dump(pw, "    ");
   6717         }
   6718     }
   6719 
   6720     private boolean dumpWindows(PrintWriter pw, String name, String[] args, int opti,
   6721             boolean dumpAll) {
   6722         final ArrayList<WindowState> windows = new ArrayList();
   6723         if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
   6724             final boolean appsOnly = name.contains("apps");
   6725             final boolean visibleOnly = name.contains("visible");
   6726             synchronized(mWindowMap) {
   6727                 if (appsOnly) {
   6728                     mRoot.dumpDisplayContents(pw);
   6729                 }
   6730 
   6731                 mRoot.forAllWindows((w) -> {
   6732                     if ((!visibleOnly || w.mWinAnimator.getShown())
   6733                             && (!appsOnly || w.mAppToken != null)) {
   6734                         windows.add(w);
   6735                     }
   6736                 }, true /* traverseTopToBottom */);
   6737             }
   6738         } else {
   6739             synchronized(mWindowMap) {
   6740                 mRoot.getWindowsByName(windows, name);
   6741             }
   6742         }
   6743 
   6744         if (windows.size() <= 0) {
   6745             return false;
   6746         }
   6747 
   6748         synchronized(mWindowMap) {
   6749             dumpWindowsLocked(pw, dumpAll, windows);
   6750         }
   6751         return true;
   6752     }
   6753 
   6754     private void dumpLastANRLocked(PrintWriter pw) {
   6755         pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
   6756         if (mLastANRState == null) {
   6757             pw.println("  <no ANR has occurred since boot>");
   6758         } else {
   6759             pw.println(mLastANRState);
   6760         }
   6761     }
   6762 
   6763     /**
   6764      * Saves information about the state of the window manager at
   6765      * the time an ANR occurred before anything else in the system changes
   6766      * in response.
   6767      *
   6768      * @param appWindowToken The application that ANR'd, may be null.
   6769      * @param windowState The window that ANR'd, may be null.
   6770      * @param reason The reason for the ANR, may be null.
   6771      */
   6772     void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, String reason) {
   6773         StringWriter sw = new StringWriter();
   6774         PrintWriter pw = new FastPrintWriter(sw, false, 1024);
   6775         pw.println("  ANR time: " + DateFormat.getDateTimeInstance().format(new Date()));
   6776         if (appWindowToken != null) {
   6777             pw.println("  Application at fault: " + appWindowToken.stringName);
   6778         }
   6779         if (windowState != null) {
   6780             pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
   6781         }
   6782         if (reason != null) {
   6783             pw.println("  Reason: " + reason);
   6784         }
   6785         if (!mWinAddedSinceNullFocus.isEmpty()) {
   6786             pw.println("  Windows added since null focus: " + mWinAddedSinceNullFocus);
   6787         }
   6788         if (!mWinRemovedSinceNullFocus.isEmpty()) {
   6789             pw.println("  Windows removed since null focus: " + mWinRemovedSinceNullFocus);
   6790         }
   6791         pw.println();
   6792         dumpWindowsNoHeaderLocked(pw, true, null);
   6793         pw.println();
   6794         pw.println("Last ANR continued");
   6795         mRoot.dumpDisplayContents(pw);
   6796         pw.close();
   6797         mLastANRState = sw.toString();
   6798 
   6799         mH.removeMessages(H.RESET_ANR_MESSAGE);
   6800         mH.sendEmptyMessageDelayed(H.RESET_ANR_MESSAGE, LAST_ANR_LIFETIME_DURATION_MSECS);
   6801     }
   6802 
   6803     @Override
   6804     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   6805         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
   6806 
   6807         boolean dumpAll = false;
   6808 
   6809         int opti = 0;
   6810         while (opti < args.length) {
   6811             String opt = args[opti];
   6812             if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
   6813                 break;
   6814             }
   6815             opti++;
   6816             if ("-a".equals(opt)) {
   6817                 dumpAll = true;
   6818             } else if ("-h".equals(opt)) {
   6819                 pw.println("Window manager dump options:");
   6820                 pw.println("  [-a] [-h] [cmd] ...");
   6821                 pw.println("  cmd may be one of:");
   6822                 pw.println("    l[astanr]: last ANR information");
   6823                 pw.println("    p[policy]: policy state");
   6824                 pw.println("    a[animator]: animator state");
   6825                 pw.println("    s[essions]: active sessions");
   6826                 pw.println("    surfaces: active surfaces (debugging enabled only)");
   6827                 pw.println("    d[isplays]: active display contents");
   6828                 pw.println("    t[okens]: token list");
   6829                 pw.println("    w[indows]: window list");
   6830                 pw.println("  cmd may also be a NAME to dump windows.  NAME may");
   6831                 pw.println("    be a partial substring in a window name, a");
   6832                 pw.println("    Window hex object identifier, or");
   6833                 pw.println("    \"all\" for all windows, or");
   6834                 pw.println("    \"visible\" for the visible windows.");
   6835                 pw.println("    \"visible-apps\" for the visible app windows.");
   6836                 pw.println("  -a: include all available server state.");
   6837                 return;
   6838             } else {
   6839                 pw.println("Unknown argument: " + opt + "; use -h for help");
   6840             }
   6841         }
   6842 
   6843         // Is the caller requesting to dump a particular piece of data?
   6844         if (opti < args.length) {
   6845             String cmd = args[opti];
   6846             opti++;
   6847             if ("lastanr".equals(cmd) || "l".equals(cmd)) {
   6848                 synchronized(mWindowMap) {
   6849                     dumpLastANRLocked(pw);
   6850                 }
   6851                 return;
   6852             } else if ("policy".equals(cmd) || "p".equals(cmd)) {
   6853                 synchronized(mWindowMap) {
   6854                     dumpPolicyLocked(pw, args, true);
   6855                 }
   6856                 return;
   6857             } else if ("animator".equals(cmd) || "a".equals(cmd)) {
   6858                 synchronized(mWindowMap) {
   6859                     dumpAnimatorLocked(pw, args, true);
   6860                 }
   6861                 return;
   6862             } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
   6863                 synchronized(mWindowMap) {
   6864                     dumpSessionsLocked(pw, true);
   6865                 }
   6866                 return;
   6867             } else if ("surfaces".equals(cmd)) {
   6868                 synchronized(mWindowMap) {
   6869                     WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, null);
   6870                 }
   6871                 return;
   6872             } else if ("displays".equals(cmd) || "d".equals(cmd)) {
   6873                 synchronized(mWindowMap) {
   6874                     mRoot.dumpDisplayContents(pw);
   6875                 }
   6876                 return;
   6877             } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
   6878                 synchronized(mWindowMap) {
   6879                     dumpTokensLocked(pw, true);
   6880                 }
   6881                 return;
   6882             } else if ("windows".equals(cmd) || "w".equals(cmd)) {
   6883                 synchronized(mWindowMap) {
   6884                     dumpWindowsLocked(pw, true, null);
   6885                 }
   6886                 return;
   6887             } else if ("all".equals(cmd) || "a".equals(cmd)) {
   6888                 synchronized(mWindowMap) {
   6889                     dumpWindowsLocked(pw, true, null);
   6890                 }
   6891                 return;
   6892             } else if ("containers".equals(cmd)) {
   6893                 synchronized(mWindowMap) {
   6894                     StringBuilder output = new StringBuilder();
   6895                     mRoot.dumpChildrenNames(output, " ");
   6896                     pw.println(output.toString());
   6897                     pw.println(" ");
   6898                     mRoot.forAllWindows(w -> {pw.println(w);}, true /* traverseTopToBottom */);
   6899                 }
   6900                 return;
   6901             } else {
   6902                 // Dumping a single name?
   6903                 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
   6904                     pw.println("Bad window command, or no windows match: " + cmd);
   6905                     pw.println("Use -h for help.");
   6906                 }
   6907                 return;
   6908             }
   6909         }
   6910 
   6911         synchronized(mWindowMap) {
   6912             pw.println();
   6913             if (dumpAll) {
   6914                 pw.println("-------------------------------------------------------------------------------");
   6915             }
   6916             dumpLastANRLocked(pw);
   6917             pw.println();
   6918             if (dumpAll) {
   6919                 pw.println("-------------------------------------------------------------------------------");
   6920             }
   6921             dumpPolicyLocked(pw, args, dumpAll);
   6922             pw.println();
   6923             if (dumpAll) {
   6924                 pw.println("-------------------------------------------------------------------------------");
   6925             }
   6926             dumpAnimatorLocked(pw, args, dumpAll);
   6927             pw.println();
   6928             if (dumpAll) {
   6929                 pw.println("-------------------------------------------------------------------------------");
   6930             }
   6931             dumpSessionsLocked(pw, dumpAll);
   6932             pw.println();
   6933             if (dumpAll) {
   6934                 pw.println("-------------------------------------------------------------------------------");
   6935             }
   6936             WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ?
   6937                     "-------------------------------------------------------------------------------"
   6938                     : null);
   6939             pw.println();
   6940             if (dumpAll) {
   6941                 pw.println("-------------------------------------------------------------------------------");
   6942             }
   6943             mRoot.dumpDisplayContents(pw);
   6944             pw.println();
   6945             if (dumpAll) {
   6946                 pw.println("-------------------------------------------------------------------------------");
   6947             }
   6948             dumpTokensLocked(pw, dumpAll);
   6949             pw.println();
   6950             if (dumpAll) {
   6951                 pw.println("-------------------------------------------------------------------------------");
   6952             }
   6953             dumpWindowsLocked(pw, dumpAll, null);
   6954         }
   6955     }
   6956 
   6957     // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
   6958     @Override
   6959     public void monitor() {
   6960         synchronized (mWindowMap) { }
   6961     }
   6962 
   6963     // TODO: All the display method below should probably be moved into the RootWindowContainer...
   6964     private void createDisplayContentLocked(final Display display) {
   6965         if (display == null) {
   6966             throw new IllegalArgumentException("getDisplayContent: display must not be null");
   6967         }
   6968         mRoot.getDisplayContentOrCreate(display.getDisplayId());
   6969     }
   6970 
   6971     // There is an inherent assumption that this will never return null.
   6972     // TODO(multi-display): Inspect all the call-points of this method to see if they make sense to
   6973     // support non-default display.
   6974     DisplayContent getDefaultDisplayContentLocked() {
   6975         return mRoot.getDisplayContentOrCreate(DEFAULT_DISPLAY);
   6976     }
   6977 
   6978     public void onDisplayAdded(int displayId) {
   6979         synchronized (mWindowMap) {
   6980             final Display display = mDisplayManager.getDisplay(displayId);
   6981             if (display != null) {
   6982                 createDisplayContentLocked(display);
   6983                 displayReady(displayId);
   6984             }
   6985             mWindowPlacerLocked.requestTraversal();
   6986         }
   6987     }
   6988 
   6989     public void onDisplayRemoved(int displayId) {
   6990         synchronized (mWindowMap) {
   6991             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
   6992             if (displayContent != null) {
   6993                 displayContent.removeIfPossible();
   6994             }
   6995             mAnimator.removeDisplayLocked(displayId);
   6996             mWindowPlacerLocked.requestTraversal();
   6997         }
   6998     }
   6999 
   7000     public void onDisplayChanged(int displayId) {
   7001         synchronized (mWindowMap) {
   7002             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
   7003             if (displayContent != null) {
   7004                 displayContent.updateDisplayInfo();
   7005             }
   7006             mWindowPlacerLocked.requestTraversal();
   7007         }
   7008     }
   7009 
   7010     @Override
   7011     public Object getWindowManagerLock() {
   7012         return mWindowMap;
   7013     }
   7014 
   7015     /**
   7016      * Hint to a token that its activity will relaunch, which will trigger removal and addition of
   7017      * a window.
   7018      * @param token Application token for which the activity will be relaunched.
   7019      */
   7020     public void setWillReplaceWindow(IBinder token, boolean animate) {
   7021         synchronized (mWindowMap) {
   7022             final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
   7023             if (appWindowToken == null || !appWindowToken.hasContentToDisplay()) {
   7024                 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
   7025                         + token);
   7026                 return;
   7027             }
   7028             appWindowToken.setWillReplaceWindows(animate);
   7029         }
   7030     }
   7031 
   7032     /**
   7033      * Hint to a token that its windows will be replaced across activity relaunch.
   7034      * The windows would otherwise be removed  shortly following this as the
   7035      * activity is torn down.
   7036      * @param token Application token for which the activity will be relaunched.
   7037      * @param childrenOnly Whether to mark only child windows for replacement
   7038      *                     (for the case where main windows are being preserved/
   7039      *                     reused rather than replaced).
   7040      *
   7041      */
   7042     // TODO: The s at the end of the method name is the only difference with the name of the method
   7043     // above. We should combine them or find better names.
   7044     void setWillReplaceWindows(IBinder token, boolean childrenOnly) {
   7045         synchronized (mWindowMap) {
   7046             final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
   7047             if (appWindowToken == null || !appWindowToken.hasContentToDisplay()) {
   7048                 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
   7049                         + token);
   7050                 return;
   7051             }
   7052 
   7053             if (childrenOnly) {
   7054                 appWindowToken.setWillReplaceChildWindows();
   7055             } else {
   7056                 appWindowToken.setWillReplaceWindows(false /* animate */);
   7057             }
   7058 
   7059             scheduleClearWillReplaceWindows(token, true /* replacing */);
   7060         }
   7061     }
   7062 
   7063     /**
   7064      * If we're replacing the window, schedule a timer to clear the replaced window
   7065      * after a timeout, in case the replacing window is not coming.
   7066      *
   7067      * If we're not replacing the window, clear the replace window settings of the app.
   7068      *
   7069      * @param token Application token for the activity whose window might be replaced.
   7070      * @param replacing Whether the window is being replaced or not.
   7071      */
   7072     public void scheduleClearWillReplaceWindows(IBinder token, boolean replacing) {
   7073         synchronized (mWindowMap) {
   7074             final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
   7075             if (appWindowToken == null) {
   7076                 Slog.w(TAG_WM, "Attempted to reset replacing window on non-existing app token "
   7077                         + token);
   7078                 return;
   7079             }
   7080             if (replacing) {
   7081                 scheduleWindowReplacementTimeouts(appWindowToken);
   7082             } else {
   7083                 appWindowToken.clearWillReplaceWindows();
   7084             }
   7085         }
   7086     }
   7087 
   7088     void scheduleWindowReplacementTimeouts(AppWindowToken appWindowToken) {
   7089         if (!mWindowReplacementTimeouts.contains(appWindowToken)) {
   7090             mWindowReplacementTimeouts.add(appWindowToken);
   7091         }
   7092         mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
   7093         mH.sendEmptyMessageDelayed(
   7094                 H.WINDOW_REPLACEMENT_TIMEOUT, WINDOW_REPLACEMENT_TIMEOUT_DURATION);
   7095     }
   7096 
   7097     @Override
   7098     public int getDockedStackSide() {
   7099         synchronized (mWindowMap) {
   7100             final TaskStack dockedStack = getDefaultDisplayContentLocked()
   7101                     .getDockedStackIgnoringVisibility();
   7102             return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide();
   7103         }
   7104     }
   7105 
   7106     @Override
   7107     public void setDockedStackResizing(boolean resizing) {
   7108         synchronized (mWindowMap) {
   7109             getDefaultDisplayContentLocked().getDockedDividerController().setResizing(resizing);
   7110             requestTraversal();
   7111         }
   7112     }
   7113 
   7114     @Override
   7115     public void setDockedStackDividerTouchRegion(Rect touchRegion) {
   7116         synchronized (mWindowMap) {
   7117             getDefaultDisplayContentLocked().getDockedDividerController()
   7118                     .setTouchRegion(touchRegion);
   7119             setFocusTaskRegionLocked(null);
   7120         }
   7121     }
   7122 
   7123     @Override
   7124     public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
   7125         synchronized (mWindowMap) {
   7126             getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer(
   7127                     visible, targetStackId, alpha);
   7128         }
   7129     }
   7130 
   7131     public void setForceResizableTasks(boolean forceResizableTasks) {
   7132         synchronized (mWindowMap) {
   7133             mForceResizableTasks = forceResizableTasks;
   7134         }
   7135     }
   7136 
   7137     public void setSupportsPictureInPicture(boolean supportsPictureInPicture) {
   7138         synchronized (mWindowMap) {
   7139             mSupportsPictureInPicture = supportsPictureInPicture;
   7140         }
   7141     }
   7142 
   7143     static int dipToPixel(int dip, DisplayMetrics displayMetrics) {
   7144         return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics);
   7145     }
   7146 
   7147     @Override
   7148     public void registerDockedStackListener(IDockedStackListener listener) {
   7149         if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS,
   7150                 "registerDockedStackListener()")) {
   7151             return;
   7152         }
   7153         synchronized (mWindowMap) {
   7154             // TODO(multi-display): The listener is registered on the default display only.
   7155             getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener(
   7156                     listener);
   7157         }
   7158     }
   7159 
   7160     @Override
   7161     public void registerPinnedStackListener(int displayId, IPinnedStackListener listener) {
   7162         if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS,
   7163                 "registerPinnedStackListener()")) {
   7164             return;
   7165         }
   7166         if (!mSupportsPictureInPicture) {
   7167             return;
   7168         }
   7169         synchronized (mWindowMap) {
   7170             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
   7171             displayContent.getPinnedStackController().registerPinnedStackListener(listener);
   7172         }
   7173     }
   7174 
   7175     @Override
   7176     public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
   7177         try {
   7178             WindowState focusedWindow = getFocusedWindow();
   7179             if (focusedWindow != null && focusedWindow.mClient != null) {
   7180                 getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId);
   7181             }
   7182         } catch (RemoteException e) {
   7183         }
   7184     }
   7185 
   7186     @Override
   7187     public void getStableInsets(int displayId, Rect outInsets) throws RemoteException {
   7188         synchronized (mWindowMap) {
   7189             getStableInsetsLocked(displayId, outInsets);
   7190         }
   7191     }
   7192 
   7193     void getStableInsetsLocked(int displayId, Rect outInsets) {
   7194         outInsets.setEmpty();
   7195         final DisplayContent dc = mRoot.getDisplayContent(displayId);
   7196         if (dc != null) {
   7197             final DisplayInfo di = dc.getDisplayInfo();
   7198             mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
   7199         }
   7200     }
   7201 
   7202     void intersectDisplayInsetBounds(Rect display, Rect insets, Rect inOutBounds) {
   7203         mTmpRect3.set(display);
   7204         mTmpRect3.inset(insets);
   7205         inOutBounds.intersect(mTmpRect3);
   7206     }
   7207 
   7208     MousePositionTracker mMousePositionTracker = new MousePositionTracker();
   7209 
   7210     private static class MousePositionTracker implements PointerEventListener {
   7211         private boolean mLatestEventWasMouse;
   7212         private float mLatestMouseX;
   7213         private float mLatestMouseY;
   7214 
   7215         void updatePosition(float x, float y) {
   7216             synchronized (this) {
   7217                 mLatestEventWasMouse = true;
   7218                 mLatestMouseX = x;
   7219                 mLatestMouseY = y;
   7220             }
   7221         }
   7222 
   7223         @Override
   7224         public void onPointerEvent(MotionEvent motionEvent) {
   7225             if (motionEvent.isFromSource(InputDevice.SOURCE_MOUSE)) {
   7226                 updatePosition(motionEvent.getRawX(), motionEvent.getRawY());
   7227             } else {
   7228                 synchronized (this) {
   7229                     mLatestEventWasMouse = false;
   7230                 }
   7231             }
   7232         }
   7233     };
   7234 
   7235     void updatePointerIcon(IWindow client) {
   7236         float mouseX, mouseY;
   7237 
   7238         synchronized(mMousePositionTracker) {
   7239             if (!mMousePositionTracker.mLatestEventWasMouse) {
   7240                 return;
   7241             }
   7242             mouseX = mMousePositionTracker.mLatestMouseX;
   7243             mouseY = mMousePositionTracker.mLatestMouseY;
   7244         }
   7245 
   7246         synchronized (mWindowMap) {
   7247             if (mDragState != null) {
   7248                 // Drag cursor overrides the app cursor.
   7249                 return;
   7250             }
   7251             WindowState callingWin = windowForClientLocked(null, client, false);
   7252             if (callingWin == null) {
   7253                 Slog.w(TAG_WM, "Bad requesting window " + client);
   7254                 return;
   7255             }
   7256             final DisplayContent displayContent = callingWin.getDisplayContent();
   7257             if (displayContent == null) {
   7258                 return;
   7259             }
   7260             WindowState windowUnderPointer =
   7261                     displayContent.getTouchableWinAtPointLocked(mouseX, mouseY);
   7262             if (windowUnderPointer != callingWin) {
   7263                 return;
   7264             }
   7265             try {
   7266                 windowUnderPointer.mClient.updatePointerIcon(
   7267                         windowUnderPointer.translateToWindowX(mouseX),
   7268                         windowUnderPointer.translateToWindowY(mouseY));
   7269             } catch (RemoteException e) {
   7270                 Slog.w(TAG_WM, "unable to update pointer icon");
   7271             }
   7272         }
   7273     }
   7274 
   7275     void restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY) {
   7276         // Mouse position tracker has not been getting updates while dragging, update it now.
   7277         mMousePositionTracker.updatePosition(latestX, latestY);
   7278 
   7279         WindowState windowUnderPointer =
   7280                 displayContent.getTouchableWinAtPointLocked(latestX, latestY);
   7281         if (windowUnderPointer != null) {
   7282             try {
   7283                 windowUnderPointer.mClient.updatePointerIcon(
   7284                         windowUnderPointer.translateToWindowX(latestX),
   7285                         windowUnderPointer.translateToWindowY(latestY));
   7286             } catch (RemoteException e) {
   7287                 Slog.w(TAG_WM, "unable to restore pointer icon");
   7288             }
   7289         } else {
   7290             InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_DEFAULT);
   7291         }
   7292     }
   7293 
   7294     @Override
   7295     public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
   7296             throws RemoteException {
   7297         if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS, "registerShortcutKey")) {
   7298             throw new SecurityException(
   7299                     "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission");
   7300         }
   7301         mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver);
   7302     }
   7303 
   7304     void markForSeamlessRotation(WindowState w, boolean seamlesslyRotated) {
   7305         if (seamlesslyRotated == w.mSeamlesslyRotated) {
   7306             return;
   7307         }
   7308         w.mSeamlesslyRotated = seamlesslyRotated;
   7309         if (seamlesslyRotated) {
   7310             mSeamlessRotationCount++;
   7311         } else {
   7312             mSeamlessRotationCount--;
   7313         }
   7314         if (mSeamlessRotationCount == 0) {
   7315             if (DEBUG_ORIENTATION) {
   7316                 Slog.i(TAG, "Performing post-rotate rotation after seamless rotation");
   7317             }
   7318             final DisplayContent displayContent = w.getDisplayContent();
   7319             if (displayContent.updateRotationUnchecked(false /* inTransaction */)) {
   7320                 mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
   7321                         .sendToTarget();
   7322             }
   7323         }
   7324     }
   7325 
   7326     private final class LocalService extends WindowManagerInternal {
   7327         @Override
   7328         public void requestTraversalFromDisplayManager() {
   7329             requestTraversal();
   7330         }
   7331 
   7332         @Override
   7333         public void setMagnificationSpec(MagnificationSpec spec) {
   7334             synchronized (mWindowMap) {
   7335                 if (mAccessibilityController != null) {
   7336                     mAccessibilityController.setMagnificationSpecLocked(spec);
   7337                 } else {
   7338                     throw new IllegalStateException("Magnification callbacks not set!");
   7339                 }
   7340             }
   7341             if (Binder.getCallingPid() != myPid()) {
   7342                 spec.recycle();
   7343             }
   7344         }
   7345 
   7346         @Override
   7347         public void setForceShowMagnifiableBounds(boolean show) {
   7348             synchronized (mWindowMap) {
   7349                 if (mAccessibilityController != null) {
   7350                     mAccessibilityController.setForceShowMagnifiableBoundsLocked(show);
   7351                 } else {
   7352                     throw new IllegalStateException("Magnification callbacks not set!");
   7353                 }
   7354             }
   7355         }
   7356 
   7357         @Override
   7358         public void getMagnificationRegion(@NonNull Region magnificationRegion) {
   7359             synchronized (mWindowMap) {
   7360                 if (mAccessibilityController != null) {
   7361                     mAccessibilityController.getMagnificationRegionLocked(magnificationRegion);
   7362                 } else {
   7363                     throw new IllegalStateException("Magnification callbacks not set!");
   7364                 }
   7365             }
   7366         }
   7367 
   7368         @Override
   7369         public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
   7370             synchronized (mWindowMap) {
   7371                 WindowState windowState = mWindowMap.get(windowToken);
   7372                 if (windowState == null) {
   7373                     return null;
   7374                 }
   7375                 MagnificationSpec spec = null;
   7376                 if (mAccessibilityController != null) {
   7377                     spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState);
   7378                 }
   7379                 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
   7380                     return null;
   7381                 }
   7382                 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
   7383                 spec.scale *= windowState.mGlobalScale;
   7384                 return spec;
   7385             }
   7386         }
   7387 
   7388         @Override
   7389         public void setMagnificationCallbacks(@Nullable MagnificationCallbacks callbacks) {
   7390             synchronized (mWindowMap) {
   7391                 if (mAccessibilityController == null) {
   7392                     mAccessibilityController = new AccessibilityController(
   7393                             WindowManagerService.this);
   7394                 }
   7395                 mAccessibilityController.setMagnificationCallbacksLocked(callbacks);
   7396                 if (!mAccessibilityController.hasCallbacksLocked()) {
   7397                     mAccessibilityController = null;
   7398                 }
   7399             }
   7400         }
   7401 
   7402         @Override
   7403         public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) {
   7404             synchronized (mWindowMap) {
   7405                 if (mAccessibilityController == null) {
   7406                     mAccessibilityController = new AccessibilityController(
   7407                             WindowManagerService.this);
   7408                 }
   7409                 mAccessibilityController.setWindowsForAccessibilityCallback(callback);
   7410                 if (!mAccessibilityController.hasCallbacksLocked()) {
   7411                     mAccessibilityController = null;
   7412                 }
   7413             }
   7414         }
   7415 
   7416         @Override
   7417         public void setInputFilter(IInputFilter filter) {
   7418             mInputManager.setInputFilter(filter);
   7419         }
   7420 
   7421         @Override
   7422         public IBinder getFocusedWindowToken() {
   7423             synchronized (mWindowMap) {
   7424                 WindowState windowState = getFocusedWindowLocked();
   7425                 if (windowState != null) {
   7426                     return windowState.mClient.asBinder();
   7427                 }
   7428                 return null;
   7429             }
   7430         }
   7431 
   7432         @Override
   7433         public boolean isKeyguardLocked() {
   7434             return WindowManagerService.this.isKeyguardLocked();
   7435         }
   7436 
   7437         @Override
   7438         public boolean isKeyguardShowingAndNotOccluded() {
   7439             return WindowManagerService.this.isKeyguardShowingAndNotOccluded();
   7440         }
   7441 
   7442         @Override
   7443         public void showGlobalActions() {
   7444             WindowManagerService.this.showGlobalActions();
   7445         }
   7446 
   7447         @Override
   7448         public void getWindowFrame(IBinder token, Rect outBounds) {
   7449             synchronized (mWindowMap) {
   7450                 WindowState windowState = mWindowMap.get(token);
   7451                 if (windowState != null) {
   7452                     outBounds.set(windowState.mFrame);
   7453                 } else {
   7454                     outBounds.setEmpty();
   7455                 }
   7456             }
   7457         }
   7458 
   7459         @Override
   7460         public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
   7461             boolean allWindowsDrawn = false;
   7462             synchronized (mWindowMap) {
   7463                 mWaitingForDrawnCallback = callback;
   7464                 getDefaultDisplayContentLocked().waitForAllWindowsDrawn();
   7465                 mWindowPlacerLocked.requestTraversal();
   7466                 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
   7467                 if (mWaitingForDrawn.isEmpty()) {
   7468                     allWindowsDrawn = true;
   7469                 } else {
   7470                     mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
   7471                     checkDrawnWindowsLocked();
   7472                 }
   7473             }
   7474             if (allWindowsDrawn) {
   7475                 callback.run();
   7476             }
   7477         }
   7478 
   7479         @Override
   7480         public void addWindowToken(IBinder token, int type, int displayId) {
   7481             WindowManagerService.this.addWindowToken(token, type, displayId);
   7482         }
   7483 
   7484         @Override
   7485         public void removeWindowToken(IBinder binder, boolean removeWindows, int displayId) {
   7486             synchronized(mWindowMap) {
   7487                 if (removeWindows) {
   7488                     final DisplayContent dc = mRoot.getDisplayContent(displayId);
   7489                     if (dc == null) {
   7490                         Slog.w(TAG_WM, "removeWindowToken: Attempted to remove token: " + binder
   7491                                 + " for non-exiting displayId=" + displayId);
   7492                         return;
   7493                     }
   7494 
   7495                     final WindowToken token = dc.removeWindowToken(binder);
   7496                     if (token == null) {
   7497                         Slog.w(TAG_WM, "removeWindowToken: Attempted to remove non-existing token: "
   7498                                 + binder);
   7499                         return;
   7500                     }
   7501 
   7502                     token.removeAllWindowsIfPossible();
   7503                 }
   7504                 WindowManagerService.this.removeWindowToken(binder, displayId);
   7505             }
   7506         }
   7507 
   7508         @Override
   7509         public void registerAppTransitionListener(AppTransitionListener listener) {
   7510             synchronized (mWindowMap) {
   7511                 mAppTransition.registerListenerLocked(listener);
   7512             }
   7513         }
   7514 
   7515         @Override
   7516         public int getInputMethodWindowVisibleHeight() {
   7517             synchronized (mWindowMap) {
   7518                 return mPolicy.getInputMethodWindowVisibleHeightLw();
   7519             }
   7520         }
   7521 
   7522         @Override
   7523         public void saveLastInputMethodWindowForTransition() {
   7524             synchronized (mWindowMap) {
   7525                 if (mInputMethodWindow != null) {
   7526                     mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
   7527                 }
   7528             }
   7529         }
   7530 
   7531         @Override
   7532         public void clearLastInputMethodWindowForTransition() {
   7533             synchronized (mWindowMap) {
   7534                 mPolicy.setLastInputMethodWindowLw(null, null);
   7535             }
   7536         }
   7537 
   7538         @Override
   7539         public void updateInputMethodWindowStatus(@NonNull IBinder imeToken,
   7540                 boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed,
   7541                 @Nullable IBinder targetWindowToken) {
   7542             // TODO (b/34628091): Use this method to address the window animation issue.
   7543             if (DEBUG_INPUT_METHOD) {
   7544                 Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken=" + imeToken
   7545                         + " dismissImeOnBackKeyPressed=" + dismissImeOnBackKeyPressed
   7546                         + " imeWindowVisible=" + imeWindowVisible
   7547                         + " targetWindowToken=" + targetWindowToken);
   7548             }
   7549             mPolicy.setDismissImeOnBackKeyPressed(dismissImeOnBackKeyPressed);
   7550         }
   7551 
   7552         @Override
   7553         public boolean isHardKeyboardAvailable() {
   7554             synchronized (mWindowMap) {
   7555                 return mHardKeyboardAvailable;
   7556             }
   7557         }
   7558 
   7559         @Override
   7560         public void setOnHardKeyboardStatusChangeListener(
   7561                 OnHardKeyboardStatusChangeListener listener) {
   7562             synchronized (mWindowMap) {
   7563                 mHardKeyboardStatusChangeListener = listener;
   7564             }
   7565         }
   7566 
   7567         @Override
   7568         public boolean isStackVisible(int stackId) {
   7569             synchronized (mWindowMap) {
   7570                 final DisplayContent dc = getDefaultDisplayContentLocked();
   7571                 return dc.isStackVisible(stackId);
   7572             }
   7573         }
   7574 
   7575         @Override
   7576         public boolean isDockedDividerResizing() {
   7577             synchronized (mWindowMap) {
   7578                 return getDefaultDisplayContentLocked().getDockedDividerController().isResizing();
   7579             }
   7580         }
   7581 
   7582         @Override
   7583         public void computeWindowsForAccessibility() {
   7584             final AccessibilityController accessibilityController;
   7585             synchronized (mWindowMap) {
   7586                 accessibilityController = mAccessibilityController;
   7587             }
   7588             if (accessibilityController != null) {
   7589                 accessibilityController.performComputeChangedWindowsNotLocked();
   7590             }
   7591         }
   7592 
   7593         @Override
   7594         public void setVr2dDisplayId(int vr2dDisplayId) {
   7595             if (DEBUG_DISPLAY) {
   7596                 Slog.d(TAG, "setVr2dDisplayId called for: " + vr2dDisplayId);
   7597             }
   7598             synchronized (WindowManagerService.this) {
   7599                 mVr2dDisplayId = vr2dDisplayId;
   7600             }
   7601         }
   7602     }
   7603 
   7604     void registerAppFreezeListener(AppFreezeListener listener) {
   7605         if (!mAppFreezeListeners.contains(listener)) {
   7606             mAppFreezeListeners.add(listener);
   7607         }
   7608     }
   7609 
   7610     void unregisterAppFreezeListener(AppFreezeListener listener) {
   7611         mAppFreezeListeners.remove(listener);
   7612     }
   7613 
   7614     /**
   7615      * WARNING: This interrupts surface updates, be careful! Don't
   7616      * execute within the transaction for longer than you would
   7617      * execute on an animation thread.
   7618      * WARNING: This holds the WindowManager lock, so if exec will acquire
   7619      * the ActivityManager lock, you should hold it BEFORE calling this
   7620      * otherwise there is a risk of deadlock if another thread holding the AM
   7621      * lock waits on the WM lock.
   7622      * WARNING: This method contains locks known to the State of California
   7623      * to cause Deadlocks and other conditions.
   7624      *
   7625      * Begins a surface transaction with which the AM can batch operations.
   7626      * All Surface updates performed by the WindowManager following this
   7627      * will not appear on screen until after the call to
   7628      * closeSurfaceTransaction.
   7629      *
   7630      * ActivityManager can use this to ensure multiple 'commands' will all
   7631      * be reflected in a single frame. For example when reparenting a window
   7632      * which was previously hidden due to it's parent properties, we may
   7633      * need to ensure it is hidden in the same frame that the properties
   7634      * from the new parent are inherited, otherwise it could be revealed
   7635      * mistakenly.
   7636      *
   7637      * TODO(b/36393204): We can investigate totally replacing #deferSurfaceLayout
   7638      * with something like this but it seems that some existing cases of
   7639      * deferSurfaceLayout may be a little too broad, in particular the total
   7640      * enclosure of startActivityUnchecked which could run for quite some time.
   7641      */
   7642     public void inSurfaceTransaction(Runnable exec) {
   7643         // We hold the WindowManger lock to ensure relayoutWindow
   7644         // does not return while a Surface transaction is opening.
   7645         // The client depends on us to have resized the surface
   7646         // by that point (b/36462635)
   7647 
   7648         synchronized (mWindowMap) {
   7649             SurfaceControl.openTransaction();
   7650             try {
   7651                 exec.run();
   7652             } finally {
   7653                 SurfaceControl.closeTransaction();
   7654             }
   7655         }
   7656     }
   7657 
   7658     /** Called to inform window manager if non-Vr UI shoul be disabled or not. */
   7659     public void disableNonVrUi(boolean disable) {
   7660         synchronized (mWindowMap) {
   7661             // Allow alert window notifications to be shown if non-vr UI is enabled.
   7662             final boolean showAlertWindowNotifications = !disable;
   7663             if (showAlertWindowNotifications == mShowAlertWindowNotifications) {
   7664                 return;
   7665             }
   7666             mShowAlertWindowNotifications = showAlertWindowNotifications;
   7667 
   7668             for (int i = mSessions.size() - 1; i >= 0; --i) {
   7669                 final Session s = mSessions.valueAt(i);
   7670                 s.setShowingAlertWindowNotificationAllowed(mShowAlertWindowNotifications);
   7671             }
   7672         }
   7673     }
   7674 
   7675     boolean hasWideColorGamutSupport() {
   7676         return mHasWideColorGamutSupport &&
   7677                 !SystemProperties.getBoolean("persist.sys.sf.native_mode", false);
   7678     }
   7679 
   7680     void updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown) {
   7681         if (!win.hideNonSystemOverlayWindowsWhenVisible()) {
   7682             return;
   7683         }
   7684         final boolean systemAlertWindowsHidden = !mHidingNonSystemOverlayWindows.isEmpty();
   7685         if (surfaceShown) {
   7686             if (!mHidingNonSystemOverlayWindows.contains(win)) {
   7687                 mHidingNonSystemOverlayWindows.add(win);
   7688             }
   7689         } else {
   7690             mHidingNonSystemOverlayWindows.remove(win);
   7691         }
   7692 
   7693         final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
   7694 
   7695         if (systemAlertWindowsHidden == hideSystemAlertWindows) {
   7696             return;
   7697         }
   7698 
   7699         mRoot.forAllWindows((w) -> {
   7700             w.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
   7701         }, false /* traverseTopToBottom */);
   7702     }
   7703 }
   7704