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