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