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