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