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