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