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