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