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                     // If this screen is wider than normal HVGA, or taller
   5034                     // than FWVGA, then for old apps we want to run in size
   5035                     // compatibility mode.
   5036                     if (shortSize > 321 || longSize > 570) {
   5037                         mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
   5038                     }
   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 keyCode, boolean down,
   5254                 int policyFlags, boolean isScreenOn) {
   5255             return mPolicy.interceptKeyBeforeQueueing(whenNanos,
   5256                     keyCode, down, 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 metaState, int repeatCount,
   5263                 int policyFlags) {
   5264             WindowState windowState = getWindowStateForInputChannel(focus);
   5265             return mPolicy.interceptKeyBeforeDispatching(windowState, action, flags,
   5266                     keyCode, 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         WindowState(Session s, IWindow c, WindowToken token,
   6007                WindowState attachedWindow, WindowManager.LayoutParams a,
   6008                int viewVisibility) {
   6009             mSession = s;
   6010             mClient = c;
   6011             mToken = token;
   6012             mAttrs.copyFrom(a);
   6013             mViewVisibility = viewVisibility;
   6014             DeathRecipient deathRecipient = new DeathRecipient();
   6015             mAlpha = a.alpha;
   6016             if (localLOGV) Slog.v(
   6017                 TAG, "Window " + this + " client=" + c.asBinder()
   6018                 + " token=" + token + " (" + mAttrs.token + ")");
   6019             try {
   6020                 c.asBinder().linkToDeath(deathRecipient, 0);
   6021             } catch (RemoteException e) {
   6022                 mDeathRecipient = null;
   6023                 mAttachedWindow = null;
   6024                 mLayoutAttached = false;
   6025                 mIsImWindow = false;
   6026                 mIsWallpaper = false;
   6027                 mIsFloatingLayer = false;
   6028                 mBaseLayer = 0;
   6029                 mSubLayer = 0;
   6030                 return;
   6031             }
   6032             mDeathRecipient = deathRecipient;
   6033 
   6034             if ((mAttrs.type >= FIRST_SUB_WINDOW &&
   6035                     mAttrs.type <= LAST_SUB_WINDOW)) {
   6036                 // The multiplier here is to reserve space for multiple
   6037                 // windows in the same type layer.
   6038                 mBaseLayer = mPolicy.windowTypeToLayerLw(
   6039                         attachedWindow.mAttrs.type) * TYPE_LAYER_MULTIPLIER
   6040                         + TYPE_LAYER_OFFSET;
   6041                 mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
   6042                 mAttachedWindow = attachedWindow;
   6043                 mAttachedWindow.mChildWindows.add(this);
   6044                 mLayoutAttached = mAttrs.type !=
   6045                         WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
   6046                 mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
   6047                         || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
   6048                 mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
   6049                 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
   6050             } else {
   6051                 // The multiplier here is to reserve space for multiple
   6052                 // windows in the same type layer.
   6053                 mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
   6054                         * TYPE_LAYER_MULTIPLIER
   6055                         + TYPE_LAYER_OFFSET;
   6056                 mSubLayer = 0;
   6057                 mAttachedWindow = null;
   6058                 mLayoutAttached = false;
   6059                 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
   6060                         || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
   6061                 mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
   6062                 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
   6063             }
   6064 
   6065             WindowState appWin = this;
   6066             while (appWin.mAttachedWindow != null) {
   6067                 appWin = mAttachedWindow;
   6068             }
   6069             WindowToken appToken = appWin.mToken;
   6070             while (appToken.appWindowToken == null) {
   6071                 WindowToken parent = mTokenMap.get(appToken.token);
   6072                 if (parent == null || appToken == parent) {
   6073                     break;
   6074                 }
   6075                 appToken = parent;
   6076             }
   6077             mRootToken = appToken;
   6078             mAppToken = appToken.appWindowToken;
   6079 
   6080             mSurface = null;
   6081             mRequestedWidth = 0;
   6082             mRequestedHeight = 0;
   6083             mLastRequestedWidth = 0;
   6084             mLastRequestedHeight = 0;
   6085             mXOffset = 0;
   6086             mYOffset = 0;
   6087             mLayer = 0;
   6088             mAnimLayer = 0;
   6089             mLastLayer = 0;
   6090         }
   6091 
   6092         void attach() {
   6093             if (localLOGV) Slog.v(
   6094                 TAG, "Attaching " + this + " token=" + mToken
   6095                 + ", list=" + mToken.windows);
   6096             mSession.windowAddedLocked();
   6097         }
   6098 
   6099         public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
   6100             mHaveFrame = true;
   6101 
   6102             final Rect container = mContainingFrame;
   6103             container.set(pf);
   6104 
   6105             final Rect display = mDisplayFrame;
   6106             display.set(df);
   6107 
   6108             if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
   6109                 container.intersect(mCompatibleScreenFrame);
   6110                 if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
   6111                     display.intersect(mCompatibleScreenFrame);
   6112                 }
   6113             }
   6114 
   6115             final int pw = container.right - container.left;
   6116             final int ph = container.bottom - container.top;
   6117 
   6118             int w,h;
   6119             if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
   6120                 w = mAttrs.width < 0 ? pw : mAttrs.width;
   6121                 h = mAttrs.height< 0 ? ph : mAttrs.height;
   6122             } else {
   6123                 w = mAttrs.width == mAttrs.MATCH_PARENT ? pw : mRequestedWidth;
   6124                 h = mAttrs.height== mAttrs.MATCH_PARENT ? ph : mRequestedHeight;
   6125             }
   6126 
   6127             final Rect content = mContentFrame;
   6128             content.set(cf);
   6129 
   6130             final Rect visible = mVisibleFrame;
   6131             visible.set(vf);
   6132 
   6133             final Rect frame = mFrame;
   6134             final int fw = frame.width();
   6135             final int fh = frame.height();
   6136 
   6137             //System.out.println("In: w=" + w + " h=" + h + " container=" +
   6138             //                   container + " x=" + mAttrs.x + " y=" + mAttrs.y);
   6139 
   6140             Gravity.apply(mAttrs.gravity, w, h, container,
   6141                     (int) (mAttrs.x + mAttrs.horizontalMargin * pw),
   6142                     (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame);
   6143 
   6144             //System.out.println("Out: " + mFrame);
   6145 
   6146             // Now make sure the window fits in the overall display.
   6147             Gravity.applyDisplay(mAttrs.gravity, df, frame);
   6148 
   6149             // Make sure the content and visible frames are inside of the
   6150             // final window frame.
   6151             if (content.left < frame.left) content.left = frame.left;
   6152             if (content.top < frame.top) content.top = frame.top;
   6153             if (content.right > frame.right) content.right = frame.right;
   6154             if (content.bottom > frame.bottom) content.bottom = frame.bottom;
   6155             if (visible.left < frame.left) visible.left = frame.left;
   6156             if (visible.top < frame.top) visible.top = frame.top;
   6157             if (visible.right > frame.right) visible.right = frame.right;
   6158             if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
   6159 
   6160             final Rect contentInsets = mContentInsets;
   6161             contentInsets.left = content.left-frame.left;
   6162             contentInsets.top = content.top-frame.top;
   6163             contentInsets.right = frame.right-content.right;
   6164             contentInsets.bottom = frame.bottom-content.bottom;
   6165 
   6166             final Rect visibleInsets = mVisibleInsets;
   6167             visibleInsets.left = visible.left-frame.left;
   6168             visibleInsets.top = visible.top-frame.top;
   6169             visibleInsets.right = frame.right-visible.right;
   6170             visibleInsets.bottom = frame.bottom-visible.bottom;
   6171 
   6172             if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
   6173                 updateWallpaperOffsetLocked(this, mDisplay.getWidth(),
   6174                         mDisplay.getHeight(), false);
   6175             }
   6176 
   6177             if (localLOGV) {
   6178                 //if ("com.google.android.youtube".equals(mAttrs.packageName)
   6179                 //        && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
   6180                     Slog.v(TAG, "Resolving (mRequestedWidth="
   6181                             + mRequestedWidth + ", mRequestedheight="
   6182                             + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
   6183                             + "): frame=" + mFrame.toShortString()
   6184                             + " ci=" + contentInsets.toShortString()
   6185                             + " vi=" + visibleInsets.toShortString());
   6186                 //}
   6187             }
   6188         }
   6189 
   6190         public Rect getFrameLw() {
   6191             return mFrame;
   6192         }
   6193 
   6194         public Rect getShownFrameLw() {
   6195             return mShownFrame;
   6196         }
   6197 
   6198         public Rect getDisplayFrameLw() {
   6199             return mDisplayFrame;
   6200         }
   6201 
   6202         public Rect getContentFrameLw() {
   6203             return mContentFrame;
   6204         }
   6205 
   6206         public Rect getVisibleFrameLw() {
   6207             return mVisibleFrame;
   6208         }
   6209 
   6210         public boolean getGivenInsetsPendingLw() {
   6211             return mGivenInsetsPending;
   6212         }
   6213 
   6214         public Rect getGivenContentInsetsLw() {
   6215             return mGivenContentInsets;
   6216         }
   6217 
   6218         public Rect getGivenVisibleInsetsLw() {
   6219             return mGivenVisibleInsets;
   6220         }
   6221 
   6222         public WindowManager.LayoutParams getAttrs() {
   6223             return mAttrs;
   6224         }
   6225 
   6226         public int getSurfaceLayer() {
   6227             return mLayer;
   6228         }
   6229 
   6230         public IApplicationToken getAppToken() {
   6231             return mAppToken != null ? mAppToken.appToken : null;
   6232         }
   6233 
   6234         public long getInputDispatchingTimeoutNanos() {
   6235             return mAppToken != null
   6236                     ? mAppToken.inputDispatchingTimeoutNanos
   6237                     : DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
   6238         }
   6239 
   6240         public boolean hasAppShownWindows() {
   6241             return mAppToken != null ? mAppToken.firstWindowDrawn : false;
   6242         }
   6243 
   6244         public void setAnimation(Animation anim) {
   6245             if (localLOGV) Slog.v(
   6246                 TAG, "Setting animation in " + this + ": " + anim);
   6247             mAnimating = false;
   6248             mLocalAnimating = false;
   6249             mAnimation = anim;
   6250             mAnimation.restrictDuration(MAX_ANIMATION_DURATION);
   6251             mAnimation.scaleCurrentDuration(mWindowAnimationScale);
   6252         }
   6253 
   6254         public void clearAnimation() {
   6255             if (mAnimation != null) {
   6256                 mAnimating = true;
   6257                 mLocalAnimating = false;
   6258                 mAnimation = null;
   6259             }
   6260         }
   6261 
   6262         Surface createSurfaceLocked() {
   6263             if (mSurface == null) {
   6264                 mReportDestroySurface = false;
   6265                 mSurfacePendingDestroy = false;
   6266                 mDrawPending = true;
   6267                 mCommitDrawPending = false;
   6268                 mReadyToShow = false;
   6269                 if (mAppToken != null) {
   6270                     mAppToken.allDrawn = false;
   6271                 }
   6272 
   6273                 int flags = 0;
   6274                 if (mAttrs.memoryType == MEMORY_TYPE_PUSH_BUFFERS) {
   6275                     flags |= Surface.PUSH_BUFFERS;
   6276                 }
   6277 
   6278                 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
   6279                     flags |= Surface.SECURE;
   6280                 }
   6281                 if (DEBUG_VISIBILITY) Slog.v(
   6282                     TAG, "Creating surface in session "
   6283                     + mSession.mSurfaceSession + " window " + this
   6284                     + " w=" + mFrame.width()
   6285                     + " h=" + mFrame.height() + " format="
   6286                     + mAttrs.format + " flags=" + flags);
   6287 
   6288                 int w = mFrame.width();
   6289                 int h = mFrame.height();
   6290                 if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
   6291                     // for a scaled surface, we always want the requested
   6292                     // size.
   6293                     w = mRequestedWidth;
   6294                     h = mRequestedHeight;
   6295                 }
   6296 
   6297                 // Something is wrong and SurfaceFlinger will not like this,
   6298                 // try to revert to sane values
   6299                 if (w <= 0) w = 1;
   6300                 if (h <= 0) h = 1;
   6301 
   6302                 mSurfaceShown = false;
   6303                 mSurfaceLayer = 0;
   6304                 mSurfaceAlpha = 1;
   6305                 mSurfaceX = 0;
   6306                 mSurfaceY = 0;
   6307                 mSurfaceW = w;
   6308                 mSurfaceH = h;
   6309                 try {
   6310                     mSurface = new Surface(
   6311                             mSession.mSurfaceSession, mSession.mPid,
   6312                             mAttrs.getTitle().toString(),
   6313                             0, w, h, mAttrs.format, flags);
   6314                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  CREATE SURFACE "
   6315                             + mSurface + " IN SESSION "
   6316                             + mSession.mSurfaceSession
   6317                             + ": pid=" + mSession.mPid + " format="
   6318                             + mAttrs.format + " flags=0x"
   6319                             + Integer.toHexString(flags)
   6320                             + " / " + this);
   6321                 } catch (Surface.OutOfResourcesException e) {
   6322                     Slog.w(TAG, "OutOfResourcesException creating surface");
   6323                     reclaimSomeSurfaceMemoryLocked(this, "create");
   6324                     return null;
   6325                 } catch (Exception e) {
   6326                     Slog.e(TAG, "Exception creating surface", e);
   6327                     return null;
   6328                 }
   6329 
   6330                 if (localLOGV) Slog.v(
   6331                     TAG, "Got surface: " + mSurface
   6332                     + ", set left=" + mFrame.left + " top=" + mFrame.top
   6333                     + ", animLayer=" + mAnimLayer);
   6334                 if (SHOW_TRANSACTIONS) {
   6335                     Slog.i(TAG, ">>> OPEN TRANSACTION");
   6336                     if (SHOW_TRANSACTIONS) logSurface(this,
   6337                             "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" +
   6338                             mFrame.width() + "x" + mFrame.height() + "), layer=" +
   6339                             mAnimLayer + " HIDE", null);
   6340                 }
   6341                 Surface.openTransaction();
   6342                 try {
   6343                     try {
   6344                         mSurfaceX = mFrame.left + mXOffset;
   6345                         mSurfaceY = mFrame.top + mYOffset;
   6346                         mSurface.setPosition(mSurfaceX, mSurfaceY);
   6347                         mSurfaceLayer = mAnimLayer;
   6348                         mSurface.setLayer(mAnimLayer);
   6349                         mSurfaceShown = false;
   6350                         mSurface.hide();
   6351                         if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
   6352                             if (SHOW_TRANSACTIONS) logSurface(this, "DITHER", null);
   6353                             mSurface.setFlags(Surface.SURFACE_DITHER,
   6354                                     Surface.SURFACE_DITHER);
   6355                         }
   6356                     } catch (RuntimeException e) {
   6357                         Slog.w(TAG, "Error creating surface in " + w, e);
   6358                         reclaimSomeSurfaceMemoryLocked(this, "create-init");
   6359                     }
   6360                     mLastHidden = true;
   6361                 } finally {
   6362                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
   6363                     Surface.closeTransaction();
   6364                 }
   6365                 if (localLOGV) Slog.v(
   6366                         TAG, "Created surface " + this);
   6367             }
   6368             return mSurface;
   6369         }
   6370 
   6371         void destroySurfaceLocked() {
   6372             if (mAppToken != null && this == mAppToken.startingWindow) {
   6373                 mAppToken.startingDisplayed = false;
   6374             }
   6375 
   6376             if (mSurface != null) {
   6377                 mDrawPending = false;
   6378                 mCommitDrawPending = false;
   6379                 mReadyToShow = false;
   6380 
   6381                 int i = mChildWindows.size();
   6382                 while (i > 0) {
   6383                     i--;
   6384                     WindowState c = mChildWindows.get(i);
   6385                     c.mAttachedHidden = true;
   6386                 }
   6387 
   6388                 if (mReportDestroySurface) {
   6389                     mReportDestroySurface = false;
   6390                     mSurfacePendingDestroy = true;
   6391                     try {
   6392                         mClient.dispatchGetNewSurface();
   6393                         // We'll really destroy on the next time around.
   6394                         return;
   6395                     } catch (RemoteException e) {
   6396                     }
   6397                 }
   6398 
   6399                 try {
   6400                     if (DEBUG_VISIBILITY) {
   6401                         RuntimeException e = null;
   6402                         if (!HIDE_STACK_CRAWLS) {
   6403                             e = new RuntimeException();
   6404                             e.fillInStackTrace();
   6405                         }
   6406                         Slog.w(TAG, "Window " + this + " destroying surface "
   6407                                 + mSurface + ", session " + mSession, e);
   6408                     }
   6409                     if (SHOW_TRANSACTIONS) {
   6410                         RuntimeException e = null;
   6411                         if (!HIDE_STACK_CRAWLS) {
   6412                             e = new RuntimeException();
   6413                             e.fillInStackTrace();
   6414                         }
   6415                         if (SHOW_TRANSACTIONS) logSurface(this, "DESTROY", e);
   6416                     }
   6417                     mSurface.destroy();
   6418                 } catch (RuntimeException e) {
   6419                     Slog.w(TAG, "Exception thrown when destroying Window " + this
   6420                         + " surface " + mSurface + " session " + mSession
   6421                         + ": " + e.toString());
   6422                 }
   6423 
   6424                 mSurfaceShown = false;
   6425                 mSurface = null;
   6426             }
   6427         }
   6428 
   6429         boolean finishDrawingLocked() {
   6430             if (mDrawPending) {
   6431                 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Slog.v(
   6432                     TAG, "finishDrawingLocked: " + mSurface);
   6433                 mCommitDrawPending = true;
   6434                 mDrawPending = false;
   6435                 return true;
   6436             }
   6437             return false;
   6438         }
   6439 
   6440         // This must be called while inside a transaction.
   6441         boolean commitFinishDrawingLocked(long currentTime) {
   6442             //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface);
   6443             if (!mCommitDrawPending) {
   6444                 return false;
   6445             }
   6446             mCommitDrawPending = false;
   6447             mReadyToShow = true;
   6448             final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
   6449             final AppWindowToken atoken = mAppToken;
   6450             if (atoken == null || atoken.allDrawn || starting) {
   6451                 performShowLocked();
   6452             }
   6453             return true;
   6454         }
   6455 
   6456         // This must be called while inside a transaction.
   6457         boolean performShowLocked() {
   6458             if (DEBUG_VISIBILITY) {
   6459                 RuntimeException e = null;
   6460                 if (!HIDE_STACK_CRAWLS) {
   6461                     e = new RuntimeException();
   6462                     e.fillInStackTrace();
   6463                 }
   6464                 Slog.v(TAG, "performShow on " + this
   6465                         + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
   6466                         + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
   6467             }
   6468             if (mReadyToShow && isReadyForDisplay()) {
   6469                 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) logSurface(this,
   6470                         "SHOW (performShowLocked)", null);
   6471                 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
   6472                         + " during animation: policyVis=" + mPolicyVisibility
   6473                         + " attHidden=" + mAttachedHidden
   6474                         + " tok.hiddenRequested="
   6475                         + (mAppToken != null ? mAppToken.hiddenRequested : false)
   6476                         + " tok.hidden="
   6477                         + (mAppToken != null ? mAppToken.hidden : false)
   6478                         + " animating=" + mAnimating
   6479                         + " tok animating="
   6480                         + (mAppToken != null ? mAppToken.animating : false));
   6481                 if (!showSurfaceRobustlyLocked(this)) {
   6482                     return false;
   6483                 }
   6484                 mLastAlpha = -1;
   6485                 mHasDrawn = true;
   6486                 mLastHidden = false;
   6487                 mReadyToShow = false;
   6488                 enableScreenIfNeededLocked();
   6489 
   6490                 applyEnterAnimationLocked(this);
   6491 
   6492                 int i = mChildWindows.size();
   6493                 while (i > 0) {
   6494                     i--;
   6495                     WindowState c = mChildWindows.get(i);
   6496                     if (c.mAttachedHidden) {
   6497                         c.mAttachedHidden = false;
   6498                         if (c.mSurface != null) {
   6499                             c.performShowLocked();
   6500                             // It hadn't been shown, which means layout not
   6501                             // performed on it, so now we want to make sure to
   6502                             // do a layout.  If called from within the transaction
   6503                             // loop, this will cause it to restart with a new
   6504                             // layout.
   6505                             mLayoutNeeded = true;
   6506                         }
   6507                     }
   6508                 }
   6509 
   6510                 if (mAttrs.type != TYPE_APPLICATION_STARTING
   6511                         && mAppToken != null) {
   6512                     mAppToken.firstWindowDrawn = true;
   6513 
   6514                     if (mAppToken.startingData != null) {
   6515                         if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG,
   6516                                 "Finish starting " + mToken
   6517                                 + ": first real window is shown, no animation");
   6518                         // If this initial window is animating, stop it -- we
   6519                         // will do an animation to reveal it from behind the
   6520                         // starting window, so there is no need for it to also
   6521                         // be doing its own stuff.
   6522                         if (mAnimation != null) {
   6523                             mAnimation = null;
   6524                             // Make sure we clean up the animation.
   6525                             mAnimating = true;
   6526                         }
   6527                         mFinishedStarting.add(mAppToken);
   6528                         mH.sendEmptyMessage(H.FINISHED_STARTING);
   6529                     }
   6530                     mAppToken.updateReportedVisibilityLocked();
   6531                 }
   6532             }
   6533             return true;
   6534         }
   6535 
   6536         // This must be called while inside a transaction.  Returns true if
   6537         // there is more animation to run.
   6538         boolean stepAnimationLocked(long currentTime, int dw, int dh) {
   6539             if (!mDisplayFrozen && mPolicy.isScreenOn()) {
   6540                 // We will run animations as long as the display isn't frozen.
   6541 
   6542                 if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
   6543                     mHasTransformation = true;
   6544                     mHasLocalTransformation = true;
   6545                     if (!mLocalAnimating) {
   6546                         if (DEBUG_ANIM) Slog.v(
   6547                             TAG, "Starting animation in " + this +
   6548                             " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
   6549                             " dw=" + dw + " dh=" + dh + " scale=" + mWindowAnimationScale);
   6550                         mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
   6551                         mAnimation.setStartTime(currentTime);
   6552                         mLocalAnimating = true;
   6553                         mAnimating = true;
   6554                     }
   6555                     mTransformation.clear();
   6556                     final boolean more = mAnimation.getTransformation(
   6557                         currentTime, mTransformation);
   6558                     if (DEBUG_ANIM) Slog.v(
   6559                         TAG, "Stepped animation in " + this +
   6560                         ": more=" + more + ", xform=" + mTransformation);
   6561                     if (more) {
   6562                         // we're not done!
   6563                         return true;
   6564                     }
   6565                     if (DEBUG_ANIM) Slog.v(
   6566                         TAG, "Finished animation in " + this +
   6567                         " @ " + currentTime);
   6568                     mAnimation = null;
   6569                     //WindowManagerService.this.dump();
   6570                 }
   6571                 mHasLocalTransformation = false;
   6572                 if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
   6573                         && mAppToken.animation != null) {
   6574                     // When our app token is animating, we kind-of pretend like
   6575                     // we are as well.  Note the mLocalAnimating mAnimationIsEntrance
   6576                     // part of this check means that we will only do this if
   6577                     // our window is not currently exiting, or it is not
   6578                     // locally animating itself.  The idea being that one that
   6579                     // is exiting and doing a local animation should be removed
   6580                     // once that animation is done.
   6581                     mAnimating = true;
   6582                     mHasTransformation = true;
   6583                     mTransformation.clear();
   6584                     return false;
   6585                 } else if (mHasTransformation) {
   6586                     // Little trick to get through the path below to act like
   6587                     // we have finished an animation.
   6588                     mAnimating = true;
   6589                 } else if (isAnimating()) {
   6590                     mAnimating = true;
   6591                 }
   6592             } else if (mAnimation != null) {
   6593                 // If the display is frozen, and there is a pending animation,
   6594                 // clear it and make sure we run the cleanup code.
   6595                 mAnimating = true;
   6596                 mLocalAnimating = true;
   6597                 mAnimation = null;
   6598             }
   6599 
   6600             if (!mAnimating && !mLocalAnimating) {
   6601                 return false;
   6602             }
   6603 
   6604             if (DEBUG_ANIM) Slog.v(
   6605                 TAG, "Animation done in " + this + ": exiting=" + mExiting
   6606                 + ", reportedVisible="
   6607                 + (mAppToken != null ? mAppToken.reportedVisible : false));
   6608 
   6609             mAnimating = false;
   6610             mLocalAnimating = false;
   6611             mAnimation = null;
   6612             mAnimLayer = mLayer;
   6613             if (mIsImWindow) {
   6614                 mAnimLayer += mInputMethodAnimLayerAdjustment;
   6615             } else if (mIsWallpaper) {
   6616                 mAnimLayer += mWallpaperAnimLayerAdjustment;
   6617             }
   6618             if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this
   6619                     + " anim layer: " + mAnimLayer);
   6620             mHasTransformation = false;
   6621             mHasLocalTransformation = false;
   6622             if (mPolicyVisibility != mPolicyVisibilityAfterAnim) {
   6623                 if (DEBUG_VISIBILITY) {
   6624                     Slog.v(TAG, "Policy visibility changing after anim in " + this + ": "
   6625                             + mPolicyVisibilityAfterAnim);
   6626                 }
   6627                 mPolicyVisibility = mPolicyVisibilityAfterAnim;
   6628                 if (!mPolicyVisibility) {
   6629                     if (mCurrentFocus == this) {
   6630                         mFocusMayChange = true;
   6631                     }
   6632                     // Window is no longer visible -- make sure if we were waiting
   6633                     // for it to be displayed before enabling the display, that
   6634                     // we allow the display to be enabled now.
   6635                     enableScreenIfNeededLocked();
   6636                 }
   6637             }
   6638             mTransformation.clear();
   6639             if (mHasDrawn
   6640                     && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
   6641                     && mAppToken != null
   6642                     && mAppToken.firstWindowDrawn
   6643                     && mAppToken.startingData != null) {
   6644                 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting "
   6645                         + mToken + ": first real window done animating");
   6646                 mFinishedStarting.add(mAppToken);
   6647                 mH.sendEmptyMessage(H.FINISHED_STARTING);
   6648             }
   6649 
   6650             finishExit();
   6651 
   6652             if (mAppToken != null) {
   6653                 mAppToken.updateReportedVisibilityLocked();
   6654             }
   6655 
   6656             return false;
   6657         }
   6658 
   6659         void finishExit() {
   6660             if (DEBUG_ANIM) Slog.v(
   6661                     TAG, "finishExit in " + this
   6662                     + ": exiting=" + mExiting
   6663                     + " remove=" + mRemoveOnExit
   6664                     + " windowAnimating=" + isWindowAnimating());
   6665 
   6666             final int N = mChildWindows.size();
   6667             for (int i=0; i<N; i++) {
   6668                 mChildWindows.get(i).finishExit();
   6669             }
   6670 
   6671             if (!mExiting) {
   6672                 return;
   6673             }
   6674 
   6675             if (isWindowAnimating()) {
   6676                 return;
   6677             }
   6678 
   6679             if (localLOGV) Slog.v(
   6680                     TAG, "Exit animation finished in " + this
   6681                     + ": remove=" + mRemoveOnExit);
   6682             if (mSurface != null) {
   6683                 mDestroySurface.add(this);
   6684                 mDestroying = true;
   6685                 if (SHOW_TRANSACTIONS) logSurface(this, "HIDE (finishExit)", null);
   6686                 mSurfaceShown = false;
   6687                 try {
   6688                     mSurface.hide();
   6689                 } catch (RuntimeException e) {
   6690                     Slog.w(TAG, "Error hiding surface in " + this, e);
   6691                 }
   6692                 mLastHidden = true;
   6693             }
   6694             mExiting = false;
   6695             if (mRemoveOnExit) {
   6696                 mPendingRemove.add(this);
   6697                 mRemoveOnExit = false;
   6698             }
   6699         }
   6700 
   6701         boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
   6702             if (dsdx < .99999f || dsdx > 1.00001f) return false;
   6703             if (dtdy < .99999f || dtdy > 1.00001f) return false;
   6704             if (dtdx < -.000001f || dtdx > .000001f) return false;
   6705             if (dsdy < -.000001f || dsdy > .000001f) return false;
   6706             return true;
   6707         }
   6708 
   6709         void computeShownFrameLocked() {
   6710             final boolean selfTransformation = mHasLocalTransformation;
   6711             Transformation attachedTransformation =
   6712                     (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
   6713                     ? mAttachedWindow.mTransformation : null;
   6714             Transformation appTransformation =
   6715                     (mAppToken != null && mAppToken.hasTransformation)
   6716                     ? mAppToken.transformation : null;
   6717 
   6718             // Wallpapers are animated based on the "real" window they
   6719             // are currently targeting.
   6720             if (mAttrs.type == TYPE_WALLPAPER && mLowerWallpaperTarget == null
   6721                     && mWallpaperTarget != null) {
   6722                 if (mWallpaperTarget.mHasLocalTransformation &&
   6723                         mWallpaperTarget.mAnimation != null &&
   6724                         !mWallpaperTarget.mAnimation.getDetachWallpaper()) {
   6725                     attachedTransformation = mWallpaperTarget.mTransformation;
   6726                     if (DEBUG_WALLPAPER && attachedTransformation != null) {
   6727                         Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
   6728                     }
   6729                 }
   6730                 if (mWallpaperTarget.mAppToken != null &&
   6731                         mWallpaperTarget.mAppToken.hasTransformation &&
   6732                         mWallpaperTarget.mAppToken.animation != null &&
   6733                         !mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) {
   6734                     appTransformation = mWallpaperTarget.mAppToken.transformation;
   6735                     if (DEBUG_WALLPAPER && appTransformation != null) {
   6736                         Slog.v(TAG, "WP target app xform: " + appTransformation);
   6737                     }
   6738                 }
   6739             }
   6740 
   6741             if (selfTransformation || attachedTransformation != null
   6742                     || appTransformation != null) {
   6743                 // cache often used attributes locally
   6744                 final Rect frame = mFrame;
   6745                 final float tmpFloats[] = mTmpFloats;
   6746                 final Matrix tmpMatrix = mTmpMatrix;
   6747 
   6748                 // Compute the desired transformation.
   6749                 tmpMatrix.setTranslate(0, 0);
   6750                 if (selfTransformation) {
   6751                     tmpMatrix.postConcat(mTransformation.getMatrix());
   6752                 }
   6753                 tmpMatrix.postTranslate(frame.left, frame.top);
   6754                 if (attachedTransformation != null) {
   6755                     tmpMatrix.postConcat(attachedTransformation.getMatrix());
   6756                 }
   6757                 if (appTransformation != null) {
   6758                     tmpMatrix.postConcat(appTransformation.getMatrix());
   6759                 }
   6760 
   6761                 // "convert" it into SurfaceFlinger's format
   6762                 // (a 2x2 matrix + an offset)
   6763                 // Here we must not transform the position of the surface
   6764                 // since it is already included in the transformation.
   6765                 //Slog.i(TAG, "Transform: " + matrix);
   6766 
   6767                 tmpMatrix.getValues(tmpFloats);
   6768                 mDsDx = tmpFloats[Matrix.MSCALE_X];
   6769                 mDtDx = tmpFloats[Matrix.MSKEW_X];
   6770                 mDsDy = tmpFloats[Matrix.MSKEW_Y];
   6771                 mDtDy = tmpFloats[Matrix.MSCALE_Y];
   6772                 int x = (int)tmpFloats[Matrix.MTRANS_X] + mXOffset;
   6773                 int y = (int)tmpFloats[Matrix.MTRANS_Y] + mYOffset;
   6774                 int w = frame.width();
   6775                 int h = frame.height();
   6776                 mShownFrame.set(x, y, x+w, y+h);
   6777 
   6778                 // Now set the alpha...  but because our current hardware
   6779                 // can't do alpha transformation on a non-opaque surface,
   6780                 // turn it off if we are running an animation that is also
   6781                 // transforming since it is more important to have that
   6782                 // animation be smooth.
   6783                 mShownAlpha = mAlpha;
   6784                 if (!mLimitedAlphaCompositing
   6785                         || (!PixelFormat.formatHasAlpha(mAttrs.format)
   6786                         || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
   6787                                 && x == frame.left && y == frame.top))) {
   6788                     //Slog.i(TAG, "Applying alpha transform");
   6789                     if (selfTransformation) {
   6790                         mShownAlpha *= mTransformation.getAlpha();
   6791                     }
   6792                     if (attachedTransformation != null) {
   6793                         mShownAlpha *= attachedTransformation.getAlpha();
   6794                     }
   6795                     if (appTransformation != null) {
   6796                         mShownAlpha *= appTransformation.getAlpha();
   6797                     }
   6798                 } else {
   6799                     //Slog.i(TAG, "Not applying alpha transform");
   6800                 }
   6801 
   6802                 if (localLOGV) Slog.v(
   6803                     TAG, "Continuing animation in " + this +
   6804                     ": " + mShownFrame +
   6805                     ", alpha=" + mTransformation.getAlpha());
   6806                 return;
   6807             }
   6808 
   6809             mShownFrame.set(mFrame);
   6810             if (mXOffset != 0 || mYOffset != 0) {
   6811                 mShownFrame.offset(mXOffset, mYOffset);
   6812             }
   6813             mShownAlpha = mAlpha;
   6814             mDsDx = 1;
   6815             mDtDx = 0;
   6816             mDsDy = 0;
   6817             mDtDy = 1;
   6818         }
   6819 
   6820         /**
   6821          * Is this window visible?  It is not visible if there is no
   6822          * surface, or we are in the process of running an exit animation
   6823          * that will remove the surface, or its app token has been hidden.
   6824          */
   6825         public boolean isVisibleLw() {
   6826             final AppWindowToken atoken = mAppToken;
   6827             return mSurface != null && mPolicyVisibility && !mAttachedHidden
   6828                     && (atoken == null || !atoken.hiddenRequested)
   6829                     && !mExiting && !mDestroying;
   6830         }
   6831 
   6832         /**
   6833          * Like {@link #isVisibleLw}, but also counts a window that is currently
   6834          * "hidden" behind the keyguard as visible.  This allows us to apply
   6835          * things like window flags that impact the keyguard.
   6836          * XXX I am starting to think we need to have ANOTHER visibility flag
   6837          * for this "hidden behind keyguard" state rather than overloading
   6838          * mPolicyVisibility.  Ungh.
   6839          */
   6840         public boolean isVisibleOrBehindKeyguardLw() {
   6841             final AppWindowToken atoken = mAppToken;
   6842             return mSurface != null && !mAttachedHidden
   6843                     && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
   6844                     && (mOrientationChanging || (!mDrawPending && !mCommitDrawPending))
   6845                     && !mExiting && !mDestroying;
   6846         }
   6847 
   6848         /**
   6849          * Is this window visible, ignoring its app token?  It is not visible
   6850          * if there is no surface, or we are in the process of running an exit animation
   6851          * that will remove the surface.
   6852          */
   6853         public boolean isWinVisibleLw() {
   6854             final AppWindowToken atoken = mAppToken;
   6855             return mSurface != null && mPolicyVisibility && !mAttachedHidden
   6856                     && (atoken == null || !atoken.hiddenRequested || atoken.animating)
   6857                     && !mExiting && !mDestroying;
   6858         }
   6859 
   6860         /**
   6861          * The same as isVisible(), but follows the current hidden state of
   6862          * the associated app token, not the pending requested hidden state.
   6863          */
   6864         boolean isVisibleNow() {
   6865             return mSurface != null && mPolicyVisibility && !mAttachedHidden
   6866                     && !mRootToken.hidden && !mExiting && !mDestroying;
   6867         }
   6868 
   6869         /**
   6870          * Same as isVisible(), but we also count it as visible between the
   6871          * call to IWindowSession.add() and the first relayout().
   6872          */
   6873         boolean isVisibleOrAdding() {
   6874             final AppWindowToken atoken = mAppToken;
   6875             return ((mSurface != null && !mReportDestroySurface)
   6876                             || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
   6877                     && mPolicyVisibility && !mAttachedHidden
   6878                     && (atoken == null || !atoken.hiddenRequested)
   6879                     && !mExiting && !mDestroying;
   6880         }
   6881 
   6882         /**
   6883          * Is this window currently on-screen?  It is on-screen either if it
   6884          * is visible or it is currently running an animation before no longer
   6885          * being visible.
   6886          */
   6887         boolean isOnScreen() {
   6888             final AppWindowToken atoken = mAppToken;
   6889             if (atoken != null) {
   6890                 return mSurface != null && mPolicyVisibility && !mDestroying
   6891                         && ((!mAttachedHidden && !atoken.hiddenRequested)
   6892                                 || mAnimation != null || atoken.animation != null);
   6893             } else {
   6894                 return mSurface != null && mPolicyVisibility && !mDestroying
   6895                         && (!mAttachedHidden || mAnimation != null);
   6896             }
   6897         }
   6898 
   6899         /**
   6900          * Like isOnScreen(), but we don't return true if the window is part
   6901          * of a transition that has not yet been started.
   6902          */
   6903         boolean isReadyForDisplay() {
   6904             if (mRootToken.waitingToShow &&
   6905                     mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
   6906                 return false;
   6907             }
   6908             final AppWindowToken atoken = mAppToken;
   6909             final boolean animating = atoken != null
   6910                     ? (atoken.animation != null) : false;
   6911             return mSurface != null && mPolicyVisibility && !mDestroying
   6912                     && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
   6913                                     && !mRootToken.hidden)
   6914                             || mAnimation != null || animating);
   6915         }
   6916 
   6917         /** Is the window or its container currently animating? */
   6918         boolean isAnimating() {
   6919             final WindowState attached = mAttachedWindow;
   6920             final AppWindowToken atoken = mAppToken;
   6921             return mAnimation != null
   6922                     || (attached != null && attached.mAnimation != null)
   6923                     || (atoken != null &&
   6924                             (atoken.animation != null
   6925                                     || atoken.inPendingTransaction));
   6926         }
   6927 
   6928         /** Is this window currently animating? */
   6929         boolean isWindowAnimating() {
   6930             return mAnimation != null;
   6931         }
   6932 
   6933         /**
   6934          * Like isOnScreen, but returns false if the surface hasn't yet
   6935          * been drawn.
   6936          */
   6937         public boolean isDisplayedLw() {
   6938             final AppWindowToken atoken = mAppToken;
   6939             return mSurface != null && mPolicyVisibility && !mDestroying
   6940                 && !mDrawPending && !mCommitDrawPending
   6941                 && ((!mAttachedHidden &&
   6942                         (atoken == null || !atoken.hiddenRequested))
   6943                         || mAnimating);
   6944         }
   6945 
   6946         /**
   6947          * Returns true if the window has a surface that it has drawn a
   6948          * complete UI in to.  Note that this returns true if the orientation
   6949          * is changing even if the window hasn't redrawn because we don't want
   6950          * to stop things from executing during that time.
   6951          */
   6952         public boolean isDrawnLw() {
   6953             final AppWindowToken atoken = mAppToken;
   6954             return mSurface != null && !mDestroying
   6955                 && (mOrientationChanging || (!mDrawPending && !mCommitDrawPending));
   6956         }
   6957 
   6958         /**
   6959          * Return true if the window is opaque and fully drawn.  This indicates
   6960          * it may obscure windows behind it.
   6961          */
   6962         boolean isOpaqueDrawn() {
   6963             return (mAttrs.format == PixelFormat.OPAQUE
   6964                             || mAttrs.type == TYPE_WALLPAPER)
   6965                     && mSurface != null && mAnimation == null
   6966                     && (mAppToken == null || mAppToken.animation == null)
   6967                     && !mDrawPending && !mCommitDrawPending;
   6968         }
   6969 
   6970         boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
   6971             return
   6972                  // only if the application is requesting compatible window
   6973                  (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 &&
   6974                  // only if it's visible
   6975                  mHasDrawn && mViewVisibility == View.VISIBLE &&
   6976                  // and only if the application fills the compatible screen
   6977                  mFrame.left <= mCompatibleScreenFrame.left &&
   6978                  mFrame.top <= mCompatibleScreenFrame.top &&
   6979                  mFrame.right >= mCompatibleScreenFrame.right &&
   6980                  mFrame.bottom >= mCompatibleScreenFrame.bottom &&
   6981                  // and starting window do not need background filler
   6982                  mAttrs.type != mAttrs.TYPE_APPLICATION_STARTING;
   6983         }
   6984 
   6985         boolean isFullscreen(int screenWidth, int screenHeight) {
   6986             return mFrame.left <= 0 && mFrame.top <= 0 &&
   6987                     mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
   6988         }
   6989 
   6990         void removeLocked() {
   6991             disposeInputChannel();
   6992 
   6993             if (mAttachedWindow != null) {
   6994                 mAttachedWindow.mChildWindows.remove(this);
   6995             }
   6996             destroySurfaceLocked();
   6997             mSession.windowRemovedLocked();
   6998             try {
   6999                 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
   7000             } catch (RuntimeException e) {
   7001                 // Ignore if it has already been removed (usually because
   7002                 // we are doing this as part of processing a death note.)
   7003             }
   7004         }
   7005 
   7006         void disposeInputChannel() {
   7007             if (mInputChannel != null) {
   7008                 mInputManager.unregisterInputChannel(mInputChannel);
   7009 
   7010                 mInputChannel.dispose();
   7011                 mInputChannel = null;
   7012             }
   7013         }
   7014 
   7015         private class DeathRecipient implements IBinder.DeathRecipient {
   7016             public void binderDied() {
   7017                 try {
   7018                     synchronized(mWindowMap) {
   7019                         WindowState win = windowForClientLocked(mSession, mClient, false);
   7020                         Slog.i(TAG, "WIN DEATH: " + win);
   7021                         if (win != null) {
   7022                             removeWindowLocked(mSession, win);
   7023                         }
   7024                     }
   7025                 } catch (IllegalArgumentException ex) {
   7026                     // This will happen if the window has already been
   7027                     // removed.
   7028                 }
   7029             }
   7030         }
   7031 
   7032         /** Returns true if this window desires key events. */
   7033         public final boolean canReceiveKeys() {
   7034             return     isVisibleOrAdding()
   7035                     && (mViewVisibility == View.VISIBLE)
   7036                     && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
   7037         }
   7038 
   7039         public boolean hasDrawnLw() {
   7040             return mHasDrawn;
   7041         }
   7042 
   7043         public boolean showLw(boolean doAnimation) {
   7044             return showLw(doAnimation, true);
   7045         }
   7046 
   7047         boolean showLw(boolean doAnimation, boolean requestAnim) {
   7048             if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
   7049                 return false;
   7050             }
   7051             if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
   7052             if (doAnimation) {
   7053                 if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
   7054                         + mPolicyVisibility + " mAnimation=" + mAnimation);
   7055                 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
   7056                     doAnimation = false;
   7057                 } else if (mPolicyVisibility && mAnimation == null) {
   7058                     // Check for the case where we are currently visible and
   7059                     // not animating; we do not want to do animation at such a
   7060                     // point to become visible when we already are.
   7061                     doAnimation = false;
   7062                 }
   7063             }
   7064             mPolicyVisibility = true;
   7065             mPolicyVisibilityAfterAnim = true;
   7066             if (doAnimation) {
   7067                 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
   7068             }
   7069             if (requestAnim) {
   7070                 requestAnimationLocked(0);
   7071             }
   7072             return true;
   7073         }
   7074 
   7075         public boolean hideLw(boolean doAnimation) {
   7076             return hideLw(doAnimation, true);
   7077         }
   7078 
   7079         boolean hideLw(boolean doAnimation, boolean requestAnim) {
   7080             if (doAnimation) {
   7081                 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
   7082                     doAnimation = false;
   7083                 }
   7084             }
   7085             boolean current = doAnimation ? mPolicyVisibilityAfterAnim
   7086                     : mPolicyVisibility;
   7087             if (!current) {
   7088                 return false;
   7089             }
   7090             if (doAnimation) {
   7091                 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
   7092                 if (mAnimation == null) {
   7093                     doAnimation = false;
   7094                 }
   7095             }
   7096             if (doAnimation) {
   7097                 mPolicyVisibilityAfterAnim = false;
   7098             } else {
   7099                 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
   7100                 mPolicyVisibilityAfterAnim = false;
   7101                 mPolicyVisibility = false;
   7102                 // Window is no longer visible -- make sure if we were waiting
   7103                 // for it to be displayed before enabling the display, that
   7104                 // we allow the display to be enabled now.
   7105                 enableScreenIfNeededLocked();
   7106                 if (mCurrentFocus == this) {
   7107                     mFocusMayChange = true;
   7108                 }
   7109             }
   7110             if (requestAnim) {
   7111                 requestAnimationLocked(0);
   7112             }
   7113             return true;
   7114         }
   7115 
   7116         void dump(PrintWriter pw, String prefix) {
   7117             pw.print(prefix); pw.print("mSession="); pw.print(mSession);
   7118                     pw.print(" mClient="); pw.println(mClient.asBinder());
   7119             pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
   7120             if (mAttachedWindow != null || mLayoutAttached) {
   7121                 pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
   7122                         pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
   7123             }
   7124             if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
   7125                 pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
   7126                         pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
   7127                         pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
   7128                         pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
   7129             }
   7130             pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
   7131                     pw.print(" mSubLayer="); pw.print(mSubLayer);
   7132                     pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
   7133                     pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
   7134                           : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
   7135                     pw.print("="); pw.print(mAnimLayer);
   7136                     pw.print(" mLastLayer="); pw.println(mLastLayer);
   7137             if (mSurface != null) {
   7138                 pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
   7139                 pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
   7140                         pw.print(" layer="); pw.print(mSurfaceLayer);
   7141                         pw.print(" alpha="); pw.print(mSurfaceAlpha);
   7142                         pw.print(" rect=("); pw.print(mSurfaceX);
   7143                         pw.print(","); pw.print(mSurfaceY);
   7144                         pw.print(") "); pw.print(mSurfaceW);
   7145                         pw.print(" x "); pw.println(mSurfaceH);
   7146             }
   7147             pw.print(prefix); pw.print("mToken="); pw.println(mToken);
   7148             pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
   7149             if (mAppToken != null) {
   7150                 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
   7151             }
   7152             if (mTargetAppToken != null) {
   7153                 pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
   7154             }
   7155             pw.print(prefix); pw.print("mViewVisibility=0x");
   7156                     pw.print(Integer.toHexString(mViewVisibility));
   7157                     pw.print(" mLastHidden="); pw.print(mLastHidden);
   7158                     pw.print(" mHaveFrame="); pw.print(mHaveFrame);
   7159                     pw.print(" mObscured="); pw.println(mObscured);
   7160             if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
   7161                 pw.print(prefix); pw.print("mPolicyVisibility=");
   7162                         pw.print(mPolicyVisibility);
   7163                         pw.print(" mPolicyVisibilityAfterAnim=");
   7164                         pw.print(mPolicyVisibilityAfterAnim);
   7165                         pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
   7166             }
   7167             if (!mRelayoutCalled) {
   7168                 pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled);
   7169             }
   7170             pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
   7171                     pw.print(" h="); pw.print(mRequestedHeight);
   7172                     pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
   7173             if (mXOffset != 0 || mYOffset != 0) {
   7174                 pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
   7175                         pw.print(" y="); pw.println(mYOffset);
   7176             }
   7177             pw.print(prefix); pw.print("mGivenContentInsets=");
   7178                     mGivenContentInsets.printShortString(pw);
   7179                     pw.print(" mGivenVisibleInsets=");
   7180                     mGivenVisibleInsets.printShortString(pw);
   7181                     pw.println();
   7182             if (mTouchableInsets != 0 || mGivenInsetsPending) {
   7183                 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
   7184                         pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
   7185             }
   7186             pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
   7187             pw.print(prefix); pw.print("mShownFrame=");
   7188                     mShownFrame.printShortString(pw);
   7189                     pw.print(" last="); mLastShownFrame.printShortString(pw);
   7190                     pw.println();
   7191             pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
   7192                     pw.print(" last="); mLastFrame.printShortString(pw);
   7193                     pw.println();
   7194             pw.print(prefix); pw.print("mContainingFrame=");
   7195                     mContainingFrame.printShortString(pw);
   7196                     pw.print(" mDisplayFrame=");
   7197                     mDisplayFrame.printShortString(pw);
   7198                     pw.println();
   7199             pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
   7200                     pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
   7201                     pw.println();
   7202             pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
   7203                     pw.print(" last="); mLastContentInsets.printShortString(pw);
   7204                     pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
   7205                     pw.print(" last="); mLastVisibleInsets.printShortString(pw);
   7206                     pw.println();
   7207             if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
   7208                 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
   7209                         pw.print(" mAlpha="); pw.print(mAlpha);
   7210                         pw.print(" mLastAlpha="); pw.println(mLastAlpha);
   7211             }
   7212             if (mAnimating || mLocalAnimating || mAnimationIsEntrance
   7213                     || mAnimation != null) {
   7214                 pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
   7215                         pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
   7216                         pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
   7217                         pw.print(" mAnimation="); pw.println(mAnimation);
   7218             }
   7219             if (mHasTransformation || mHasLocalTransformation) {
   7220                 pw.print(prefix); pw.print("XForm: has=");
   7221                         pw.print(mHasTransformation);
   7222                         pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
   7223                         pw.print(" "); mTransformation.printShortString(pw);
   7224                         pw.println();
   7225             }
   7226             pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
   7227                     pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
   7228                     pw.print(" mReadyToShow="); pw.print(mReadyToShow);
   7229                     pw.print(" mHasDrawn="); pw.println(mHasDrawn);
   7230             if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
   7231                 pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
   7232                         pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
   7233                         pw.print(" mDestroying="); pw.print(mDestroying);
   7234                         pw.print(" mRemoved="); pw.println(mRemoved);
   7235             }
   7236             if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
   7237                 pw.print(prefix); pw.print("mOrientationChanging=");
   7238                         pw.print(mOrientationChanging);
   7239                         pw.print(" mAppFreezing="); pw.print(mAppFreezing);
   7240                         pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
   7241             }
   7242             if (mHScale != 1 || mVScale != 1) {
   7243                 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
   7244                         pw.print(" mVScale="); pw.println(mVScale);
   7245             }
   7246             if (mWallpaperX != -1 || mWallpaperY != -1) {
   7247                 pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
   7248                         pw.print(" mWallpaperY="); pw.println(mWallpaperY);
   7249             }
   7250             if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
   7251                 pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
   7252                         pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
   7253             }
   7254         }
   7255 
   7256         String makeInputChannelName() {
   7257             return Integer.toHexString(System.identityHashCode(this))
   7258                 + " " + mAttrs.getTitle();
   7259         }
   7260 
   7261         @Override
   7262         public String toString() {
   7263             return "Window{"
   7264                 + Integer.toHexString(System.identityHashCode(this))
   7265                 + " " + mAttrs.getTitle() + " paused=" + mToken.paused + "}";
   7266         }
   7267     }
   7268 
   7269     // -------------------------------------------------------------
   7270     // Window Token State
   7271     // -------------------------------------------------------------
   7272 
   7273     class WindowToken {
   7274         // The actual token.
   7275         final IBinder token;
   7276 
   7277         // The type of window this token is for, as per WindowManager.LayoutParams.
   7278         final int windowType;
   7279 
   7280         // Set if this token was explicitly added by a client, so should
   7281         // not be removed when all windows are removed.
   7282         final boolean explicit;
   7283 
   7284         // For printing.
   7285         String stringName;
   7286 
   7287         // If this is an AppWindowToken, this is non-null.
   7288         AppWindowToken appWindowToken;
   7289 
   7290         // All of the windows associated with this token.
   7291         final ArrayList<WindowState> windows = new ArrayList<WindowState>();
   7292 
   7293         // Is key dispatching paused for this token?
   7294         boolean paused = false;
   7295 
   7296         // Should this token's windows be hidden?
   7297         boolean hidden;
   7298 
   7299         // Temporary for finding which tokens no longer have visible windows.
   7300         boolean hasVisible;
   7301 
   7302         // Set to true when this token is in a pending transaction where it
   7303         // will be shown.
   7304         boolean waitingToShow;
   7305 
   7306         // Set to true when this token is in a pending transaction where it
   7307         // will be hidden.
   7308         boolean waitingToHide;
   7309 
   7310         // Set to true when this token is in a pending transaction where its
   7311         // windows will be put to the bottom of the list.
   7312         boolean sendingToBottom;
   7313 
   7314         // Set to true when this token is in a pending transaction where its
   7315         // windows will be put to the top of the list.
   7316         boolean sendingToTop;
   7317 
   7318         WindowToken(IBinder _token, int type, boolean _explicit) {
   7319             token = _token;
   7320             windowType = type;
   7321             explicit = _explicit;
   7322         }
   7323 
   7324         void dump(PrintWriter pw, String prefix) {
   7325             pw.print(prefix); pw.print("token="); pw.println(token);
   7326             pw.print(prefix); pw.print("windows="); pw.println(windows);
   7327             pw.print(prefix); pw.print("windowType="); pw.print(windowType);
   7328                     pw.print(" hidden="); pw.print(hidden);
   7329                     pw.print(" hasVisible="); pw.println(hasVisible);
   7330             if (waitingToShow || waitingToHide || sendingToBottom || sendingToTop) {
   7331                 pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
   7332                         pw.print(" waitingToHide="); pw.print(waitingToHide);
   7333                         pw.print(" sendingToBottom="); pw.print(sendingToBottom);
   7334                         pw.print(" sendingToTop="); pw.println(sendingToTop);
   7335             }
   7336         }
   7337 
   7338         @Override
   7339         public String toString() {
   7340             if (stringName == null) {
   7341                 StringBuilder sb = new StringBuilder();
   7342                 sb.append("WindowToken{");
   7343                 sb.append(Integer.toHexString(System.identityHashCode(this)));
   7344                 sb.append(" token="); sb.append(token); sb.append('}');
   7345                 stringName = sb.toString();
   7346             }
   7347             return stringName;
   7348         }
   7349     };
   7350 
   7351     class AppWindowToken extends WindowToken {
   7352         // Non-null only for application tokens.
   7353         final IApplicationToken appToken;
   7354 
   7355         // All of the windows and child windows that are included in this
   7356         // application token.  Note this list is NOT sorted!
   7357         final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
   7358 
   7359         int groupId = -1;
   7360         boolean appFullscreen;
   7361         int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
   7362 
   7363         // The input dispatching timeout for this application token in nanoseconds.
   7364         long inputDispatchingTimeoutNanos;
   7365 
   7366         // These are used for determining when all windows associated with
   7367         // an activity have been drawn, so they can be made visible together
   7368         // at the same time.
   7369         int lastTransactionSequence = mTransactionSequence-1;
   7370         int numInterestingWindows;
   7371         int numDrawnWindows;
   7372         boolean inPendingTransaction;
   7373         boolean allDrawn;
   7374 
   7375         // Is this token going to be hidden in a little while?  If so, it
   7376         // won't be taken into account for setting the screen orientation.
   7377         boolean willBeHidden;
   7378 
   7379         // Is this window's surface needed?  This is almost like hidden, except
   7380         // it will sometimes be true a little earlier: when the token has
   7381         // been shown, but is still waiting for its app transition to execute
   7382         // before making its windows shown.
   7383         boolean hiddenRequested;
   7384 
   7385         // Have we told the window clients to hide themselves?
   7386         boolean clientHidden;
   7387 
   7388         // Last visibility state we reported to the app token.
   7389         boolean reportedVisible;
   7390 
   7391         // Set to true when the token has been removed from the window mgr.
   7392         boolean removed;
   7393 
   7394         // Have we been asked to have this token keep the screen frozen?
   7395         boolean freezingScreen;
   7396 
   7397         boolean animating;
   7398         Animation animation;
   7399         boolean hasTransformation;
   7400         final Transformation transformation = new Transformation();
   7401 
   7402         // Offset to the window of all layers in the token, for use by
   7403         // AppWindowToken animations.
   7404         int animLayerAdjustment;
   7405 
   7406         // Information about an application starting window if displayed.
   7407         StartingData startingData;
   7408         WindowState startingWindow;
   7409         View startingView;
   7410         boolean startingDisplayed;
   7411         boolean startingMoved;
   7412         boolean firstWindowDrawn;
   7413 
   7414         AppWindowToken(IApplicationToken _token) {
   7415             super(_token.asBinder(),
   7416                     WindowManager.LayoutParams.TYPE_APPLICATION, true);
   7417             appWindowToken = this;
   7418             appToken = _token;
   7419         }
   7420 
   7421         public void setAnimation(Animation anim) {
   7422             if (localLOGV) Slog.v(
   7423                 TAG, "Setting animation in " + this + ": " + anim);
   7424             animation = anim;
   7425             animating = false;
   7426             anim.restrictDuration(MAX_ANIMATION_DURATION);
   7427             anim.scaleCurrentDuration(mTransitionAnimationScale);
   7428             int zorder = anim.getZAdjustment();
   7429             int adj = 0;
   7430             if (zorder == Animation.ZORDER_TOP) {
   7431                 adj = TYPE_LAYER_OFFSET;
   7432             } else if (zorder == Animation.ZORDER_BOTTOM) {
   7433                 adj = -TYPE_LAYER_OFFSET;
   7434             }
   7435 
   7436             if (animLayerAdjustment != adj) {
   7437                 animLayerAdjustment = adj;
   7438                 updateLayers();
   7439             }
   7440         }
   7441 
   7442         public void setDummyAnimation() {
   7443             if (animation == null) {
   7444                 if (localLOGV) Slog.v(
   7445                     TAG, "Setting dummy animation in " + this);
   7446                 animation = sDummyAnimation;
   7447             }
   7448         }
   7449 
   7450         public void clearAnimation() {
   7451             if (animation != null) {
   7452                 animation = null;
   7453                 animating = true;
   7454             }
   7455         }
   7456 
   7457         void updateLayers() {
   7458             final int N = allAppWindows.size();
   7459             final int adj = animLayerAdjustment;
   7460             for (int i=0; i<N; i++) {
   7461                 WindowState w = allAppWindows.get(i);
   7462                 w.mAnimLayer = w.mLayer + adj;
   7463                 if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": "
   7464                         + w.mAnimLayer);
   7465                 if (w == mInputMethodTarget) {
   7466                     setInputMethodAnimLayerAdjustment(adj);
   7467                 }
   7468                 if (w == mWallpaperTarget && mLowerWallpaperTarget == null) {
   7469                     setWallpaperAnimLayerAdjustmentLocked(adj);
   7470                 }
   7471             }
   7472         }
   7473 
   7474         void sendAppVisibilityToClients() {
   7475             final int N = allAppWindows.size();
   7476             for (int i=0; i<N; i++) {
   7477                 WindowState win = allAppWindows.get(i);
   7478                 if (win == startingWindow && clientHidden) {
   7479                     // Don't hide the starting window.
   7480                     continue;
   7481                 }
   7482                 try {
   7483                     if (DEBUG_VISIBILITY) Slog.v(TAG,
   7484                             "Setting visibility of " + win + ": " + (!clientHidden));
   7485                     win.mClient.dispatchAppVisibility(!clientHidden);
   7486                 } catch (RemoteException e) {
   7487                 }
   7488             }
   7489         }
   7490 
   7491         void showAllWindowsLocked() {
   7492             final int NW = allAppWindows.size();
   7493             for (int i=0; i<NW; i++) {
   7494                 WindowState w = allAppWindows.get(i);
   7495                 if (DEBUG_VISIBILITY) Slog.v(TAG,
   7496                         "performing show on: " + w);
   7497                 w.performShowLocked();
   7498             }
   7499         }
   7500 
   7501         // This must be called while inside a transaction.
   7502         boolean stepAnimationLocked(long currentTime, int dw, int dh) {
   7503             if (!mDisplayFrozen && mPolicy.isScreenOn()) {
   7504                 // We will run animations as long as the display isn't frozen.
   7505 
   7506                 if (animation == sDummyAnimation) {
   7507                     // This guy is going to animate, but not yet.  For now count
   7508                     // it as not animating for purposes of scheduling transactions;
   7509                     // when it is really time to animate, this will be set to
   7510                     // a real animation and the next call will execute normally.
   7511                     return false;
   7512                 }
   7513 
   7514                 if ((allDrawn || animating || startingDisplayed) && animation != null) {
   7515                     if (!animating) {
   7516                         if (DEBUG_ANIM) Slog.v(
   7517                             TAG, "Starting animation in " + this +
   7518                             " @ " + currentTime + ": dw=" + dw + " dh=" + dh
   7519                             + " scale=" + mTransitionAnimationScale
   7520                             + " allDrawn=" + allDrawn + " animating=" + animating);
   7521                         animation.initialize(dw, dh, dw, dh);
   7522                         animation.setStartTime(currentTime);
   7523                         animating = true;
   7524                     }
   7525                     transformation.clear();
   7526                     final boolean more = animation.getTransformation(
   7527                         currentTime, transformation);
   7528                     if (DEBUG_ANIM) Slog.v(
   7529                         TAG, "Stepped animation in " + this +
   7530                         ": more=" + more + ", xform=" + transformation);
   7531                     if (more) {
   7532                         // we're done!
   7533                         hasTransformation = true;
   7534                         return true;
   7535                     }
   7536                     if (DEBUG_ANIM) Slog.v(
   7537                         TAG, "Finished animation in " + this +
   7538                         " @ " + currentTime);
   7539                     animation = null;
   7540                 }
   7541             } else if (animation != null) {
   7542                 // If the display is frozen, and there is a pending animation,
   7543                 // clear it and make sure we run the cleanup code.
   7544                 animating = true;
   7545                 animation = null;
   7546             }
   7547 
   7548             hasTransformation = false;
   7549 
   7550             if (!animating) {
   7551                 return false;
   7552             }
   7553 
   7554             clearAnimation();
   7555             animating = false;
   7556             if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == this) {
   7557                 moveInputMethodWindowsIfNeededLocked(true);
   7558             }
   7559 
   7560             if (DEBUG_ANIM) Slog.v(
   7561                     TAG, "Animation done in " + this
   7562                     + ": reportedVisible=" + reportedVisible);
   7563 
   7564             transformation.clear();
   7565             if (animLayerAdjustment != 0) {
   7566                 animLayerAdjustment = 0;
   7567                 updateLayers();
   7568             }
   7569 
   7570             final int N = windows.size();
   7571             for (int i=0; i<N; i++) {
   7572                 windows.get(i).finishExit();
   7573             }
   7574             updateReportedVisibilityLocked();
   7575 
   7576             return false;
   7577         }
   7578 
   7579         void updateReportedVisibilityLocked() {
   7580             if (appToken == null) {
   7581                 return;
   7582             }
   7583 
   7584             int numInteresting = 0;
   7585             int numVisible = 0;
   7586             boolean nowGone = true;
   7587 
   7588             if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
   7589             final int N = allAppWindows.size();
   7590             for (int i=0; i<N; i++) {
   7591                 WindowState win = allAppWindows.get(i);
   7592                 if (win == startingWindow || win.mAppFreezing
   7593                         || win.mViewVisibility != View.VISIBLE
   7594                         || win.mAttrs.type == TYPE_APPLICATION_STARTING) {
   7595                     continue;
   7596                 }
   7597                 if (DEBUG_VISIBILITY) {
   7598                     Slog.v(TAG, "Win " + win + ": isDrawn="
   7599                             + win.isDrawnLw()
   7600                             + ", isAnimating=" + win.isAnimating());
   7601                     if (!win.isDrawnLw()) {
   7602                         Slog.v(TAG, "Not displayed: s=" + win.mSurface
   7603                                 + " pv=" + win.mPolicyVisibility
   7604                                 + " dp=" + win.mDrawPending
   7605                                 + " cdp=" + win.mCommitDrawPending
   7606                                 + " ah=" + win.mAttachedHidden
   7607                                 + " th="
   7608                                 + (win.mAppToken != null
   7609                                         ? win.mAppToken.hiddenRequested : false)
   7610                                 + " a=" + win.mAnimating);
   7611                     }
   7612                 }
   7613                 numInteresting++;
   7614                 if (win.isDrawnLw()) {
   7615                     if (!win.isAnimating()) {
   7616                         numVisible++;
   7617                     }
   7618                     nowGone = false;
   7619                 } else if (win.isAnimating()) {
   7620                     nowGone = false;
   7621                 }
   7622             }
   7623 
   7624             boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
   7625             if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
   7626                     + numInteresting + " visible=" + numVisible);
   7627             if (nowVisible != reportedVisible) {
   7628                 if (DEBUG_VISIBILITY) Slog.v(
   7629                         TAG, "Visibility changed in " + this
   7630                         + ": vis=" + nowVisible);
   7631                 reportedVisible = nowVisible;
   7632                 Message m = mH.obtainMessage(
   7633                         H.REPORT_APPLICATION_TOKEN_WINDOWS,
   7634                         nowVisible ? 1 : 0,
   7635                         nowGone ? 1 : 0,
   7636                         this);
   7637                     mH.sendMessage(m);
   7638             }
   7639         }
   7640 
   7641         WindowState findMainWindow() {
   7642             int j = windows.size();
   7643             while (j > 0) {
   7644                 j--;
   7645                 WindowState win = windows.get(j);
   7646                 if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
   7647                         || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
   7648                     return win;
   7649                 }
   7650             }
   7651             return null;
   7652         }
   7653 
   7654         void dump(PrintWriter pw, String prefix) {
   7655             super.dump(pw, prefix);
   7656             if (appToken != null) {
   7657                 pw.print(prefix); pw.println("app=true");
   7658             }
   7659             if (allAppWindows.size() > 0) {
   7660                 pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
   7661             }
   7662             pw.print(prefix); pw.print("groupId="); pw.print(groupId);
   7663                     pw.print(" appFullscreen="); pw.print(appFullscreen);
   7664                     pw.print(" requestedOrientation="); pw.println(requestedOrientation);
   7665             pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
   7666                     pw.print(" clientHidden="); pw.print(clientHidden);
   7667                     pw.print(" willBeHidden="); pw.print(willBeHidden);
   7668                     pw.print(" reportedVisible="); pw.println(reportedVisible);
   7669             if (paused || freezingScreen) {
   7670                 pw.print(prefix); pw.print("paused="); pw.print(paused);
   7671                         pw.print(" freezingScreen="); pw.println(freezingScreen);
   7672             }
   7673             if (numInterestingWindows != 0 || numDrawnWindows != 0
   7674                     || inPendingTransaction || allDrawn) {
   7675                 pw.print(prefix); pw.print("numInterestingWindows=");
   7676                         pw.print(numInterestingWindows);
   7677                         pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
   7678                         pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
   7679                         pw.print(" allDrawn="); pw.println(allDrawn);
   7680             }
   7681             if (animating || animation != null) {
   7682                 pw.print(prefix); pw.print("animating="); pw.print(animating);
   7683                         pw.print(" animation="); pw.println(animation);
   7684             }
   7685             if (animLayerAdjustment != 0) {
   7686                 pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
   7687             }
   7688             if (hasTransformation) {
   7689                 pw.print(prefix); pw.print("hasTransformation="); pw.print(hasTransformation);
   7690                         pw.print(" transformation="); transformation.printShortString(pw);
   7691                         pw.println();
   7692             }
   7693             if (startingData != null || removed || firstWindowDrawn) {
   7694                 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
   7695                         pw.print(" removed="); pw.print(removed);
   7696                         pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
   7697             }
   7698             if (startingWindow != null || startingView != null
   7699                     || startingDisplayed || startingMoved) {
   7700                 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
   7701                         pw.print(" startingView="); pw.print(startingView);
   7702                         pw.print(" startingDisplayed="); pw.print(startingDisplayed);
   7703                         pw.print(" startingMoved"); pw.println(startingMoved);
   7704             }
   7705         }
   7706 
   7707         @Override
   7708         public String toString() {
   7709             if (stringName == null) {
   7710                 StringBuilder sb = new StringBuilder();
   7711                 sb.append("AppWindowToken{");
   7712                 sb.append(Integer.toHexString(System.identityHashCode(this)));
   7713                 sb.append(" token="); sb.append(token); sb.append('}');
   7714                 stringName = sb.toString();
   7715             }
   7716             return stringName;
   7717         }
   7718     }
   7719 
   7720     // -------------------------------------------------------------
   7721     // DummyAnimation
   7722     // -------------------------------------------------------------
   7723 
   7724     // This is an animation that does nothing: it just immediately finishes
   7725     // itself every time it is called.  It is used as a stub animation in cases
   7726     // where we want to synchronize multiple things that may be animating.
   7727     static final class DummyAnimation extends Animation {
   7728         public boolean getTransformation(long currentTime, Transformation outTransformation) {
   7729             return false;
   7730         }
   7731     }
   7732     static final Animation sDummyAnimation = new DummyAnimation();
   7733 
   7734     // -------------------------------------------------------------
   7735     // Async Handler
   7736     // -------------------------------------------------------------
   7737 
   7738     static final class StartingData {
   7739         final String pkg;
   7740         final int theme;
   7741         final CharSequence nonLocalizedLabel;
   7742         final int labelRes;
   7743         final int icon;
   7744 
   7745         StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel,
   7746                 int _labelRes, int _icon) {
   7747             pkg = _pkg;
   7748             theme = _theme;
   7749             nonLocalizedLabel = _nonLocalizedLabel;
   7750             labelRes = _labelRes;
   7751             icon = _icon;
   7752         }
   7753     }
   7754 
   7755     private final class H extends Handler {
   7756         public static final int REPORT_FOCUS_CHANGE = 2;
   7757         public static final int REPORT_LOSING_FOCUS = 3;
   7758         public static final int ANIMATE = 4;
   7759         public static final int ADD_STARTING = 5;
   7760         public static final int REMOVE_STARTING = 6;
   7761         public static final int FINISHED_STARTING = 7;
   7762         public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
   7763         public static final int WINDOW_FREEZE_TIMEOUT = 11;
   7764         public static final int HOLD_SCREEN_CHANGED = 12;
   7765         public static final int APP_TRANSITION_TIMEOUT = 13;
   7766         public static final int PERSIST_ANIMATION_SCALE = 14;
   7767         public static final int FORCE_GC = 15;
   7768         public static final int ENABLE_SCREEN = 16;
   7769         public static final int APP_FREEZE_TIMEOUT = 17;
   7770         public static final int SEND_NEW_CONFIGURATION = 18;
   7771         public static final int REPORT_WINDOWS_CHANGE = 19;
   7772 
   7773         private Session mLastReportedHold;
   7774 
   7775         public H() {
   7776         }
   7777 
   7778         @Override
   7779         public void handleMessage(Message msg) {
   7780             switch (msg.what) {
   7781                 case REPORT_FOCUS_CHANGE: {
   7782                     WindowState lastFocus;
   7783                     WindowState newFocus;
   7784 
   7785                     synchronized(mWindowMap) {
   7786                         lastFocus = mLastFocus;
   7787                         newFocus = mCurrentFocus;
   7788                         if (lastFocus == newFocus) {
   7789                             // Focus is not changing, so nothing to do.
   7790                             return;
   7791                         }
   7792                         mLastFocus = newFocus;
   7793                         //Slog.i(TAG, "Focus moving from " + lastFocus
   7794                         //        + " to " + newFocus);
   7795                         if (newFocus != null && lastFocus != null
   7796                                 && !newFocus.isDisplayedLw()) {
   7797                             //Slog.i(TAG, "Delaying loss of focus...");
   7798                             mLosingFocus.add(lastFocus);
   7799                             lastFocus = null;
   7800                         }
   7801                     }
   7802 
   7803                     if (lastFocus != newFocus) {
   7804                         //System.out.println("Changing focus from " + lastFocus
   7805                         //                   + " to " + newFocus);
   7806                         if (newFocus != null) {
   7807                             try {
   7808                                 //Slog.i(TAG, "Gaining focus: " + newFocus);
   7809                                 newFocus.mClient.windowFocusChanged(true, mInTouchMode);
   7810                             } catch (RemoteException e) {
   7811                                 // Ignore if process has died.
   7812                             }
   7813                             notifyFocusChanged();
   7814                         }
   7815 
   7816                         if (lastFocus != null) {
   7817                             try {
   7818                                 //Slog.i(TAG, "Losing focus: " + lastFocus);
   7819                                 lastFocus.mClient.windowFocusChanged(false, mInTouchMode);
   7820                             } catch (RemoteException e) {
   7821                                 // Ignore if process has died.
   7822                             }
   7823                         }
   7824                     }
   7825                 } break;
   7826 
   7827                 case REPORT_LOSING_FOCUS: {
   7828                     ArrayList<WindowState> losers;
   7829 
   7830                     synchronized(mWindowMap) {
   7831                         losers = mLosingFocus;
   7832                         mLosingFocus = new ArrayList<WindowState>();
   7833                     }
   7834 
   7835                     final int N = losers.size();
   7836                     for (int i=0; i<N; i++) {
   7837                         try {
   7838                             //Slog.i(TAG, "Losing delayed focus: " + losers.get(i));
   7839                             losers.get(i).mClient.windowFocusChanged(false, mInTouchMode);
   7840                         } catch (RemoteException e) {
   7841                              // Ignore if process has died.
   7842                         }
   7843                     }
   7844                 } break;
   7845 
   7846                 case ANIMATE: {
   7847                     synchronized(mWindowMap) {
   7848                         mAnimationPending = false;
   7849                         performLayoutAndPlaceSurfacesLocked();
   7850                     }
   7851                 } break;
   7852 
   7853                 case ADD_STARTING: {
   7854                     final AppWindowToken wtoken = (AppWindowToken)msg.obj;
   7855                     final StartingData sd = wtoken.startingData;
   7856 
   7857                     if (sd == null) {
   7858                         // Animation has been canceled... do nothing.
   7859                         return;
   7860                     }
   7861 
   7862                     if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
   7863                             + wtoken + ": pkg=" + sd.pkg);
   7864 
   7865                     View view = null;
   7866                     try {
   7867                         view = mPolicy.addStartingWindow(
   7868                             wtoken.token, sd.pkg,
   7869                             sd.theme, sd.nonLocalizedLabel, sd.labelRes,
   7870                             sd.icon);
   7871                     } catch (Exception e) {
   7872                         Slog.w(TAG, "Exception when adding starting window", e);
   7873                     }
   7874 
   7875                     if (view != null) {
   7876                         boolean abort = false;
   7877 
   7878                         synchronized(mWindowMap) {
   7879                             if (wtoken.removed || wtoken.startingData == null) {
   7880                                 // If the window was successfully added, then
   7881                                 // we need to remove it.
   7882                                 if (wtoken.startingWindow != null) {
   7883                                     if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
   7884                                             "Aborted starting " + wtoken
   7885                                             + ": removed=" + wtoken.removed
   7886                                             + " startingData=" + wtoken.startingData);
   7887                                     wtoken.startingWindow = null;
   7888                                     wtoken.startingData = null;
   7889                                     abort = true;
   7890                                 }
   7891                             } else {
   7892                                 wtoken.startingView = view;
   7893                             }
   7894                             if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
   7895                                     "Added starting " + wtoken
   7896                                     + ": startingWindow="
   7897                                     + wtoken.startingWindow + " startingView="
   7898                                     + wtoken.startingView);
   7899                         }
   7900 
   7901                         if (abort) {
   7902                             try {
   7903                                 mPolicy.removeStartingWindow(wtoken.token, view);
   7904                             } catch (Exception e) {
   7905                                 Slog.w(TAG, "Exception when removing starting window", e);
   7906                             }
   7907                         }
   7908                     }
   7909                 } break;
   7910 
   7911                 case REMOVE_STARTING: {
   7912                     final AppWindowToken wtoken = (AppWindowToken)msg.obj;
   7913                     IBinder token = null;
   7914                     View view = null;
   7915                     synchronized (mWindowMap) {
   7916                         if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
   7917                                 + wtoken + ": startingWindow="
   7918                                 + wtoken.startingWindow + " startingView="
   7919                                 + wtoken.startingView);
   7920                         if (wtoken.startingWindow != null) {
   7921                             view = wtoken.startingView;
   7922                             token = wtoken.token;
   7923                             wtoken.startingData = null;
   7924                             wtoken.startingView = null;
   7925                             wtoken.startingWindow = null;
   7926                         }
   7927                     }
   7928                     if (view != null) {
   7929                         try {
   7930                             mPolicy.removeStartingWindow(token, view);
   7931                         } catch (Exception e) {
   7932                             Slog.w(TAG, "Exception when removing starting window", e);
   7933                         }
   7934                     }
   7935                 } break;
   7936 
   7937                 case FINISHED_STARTING: {
   7938                     IBinder token = null;
   7939                     View view = null;
   7940                     while (true) {
   7941                         synchronized (mWindowMap) {
   7942                             final int N = mFinishedStarting.size();
   7943                             if (N <= 0) {
   7944                                 break;
   7945                             }
   7946                             AppWindowToken wtoken = mFinishedStarting.remove(N-1);
   7947 
   7948                             if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
   7949                                     "Finished starting " + wtoken
   7950                                     + ": startingWindow=" + wtoken.startingWindow
   7951                                     + " startingView=" + wtoken.startingView);
   7952 
   7953                             if (wtoken.startingWindow == null) {
   7954                                 continue;
   7955                             }
   7956 
   7957                             view = wtoken.startingView;
   7958                             token = wtoken.token;
   7959                             wtoken.startingData = null;
   7960                             wtoken.startingView = null;
   7961                             wtoken.startingWindow = null;
   7962                         }
   7963 
   7964                         try {
   7965                             mPolicy.removeStartingWindow(token, view);
   7966                         } catch (Exception e) {
   7967                             Slog.w(TAG, "Exception when removing starting window", e);
   7968                         }
   7969                     }
   7970                 } break;
   7971 
   7972                 case REPORT_APPLICATION_TOKEN_WINDOWS: {
   7973                     final AppWindowToken wtoken = (AppWindowToken)msg.obj;
   7974 
   7975                     boolean nowVisible = msg.arg1 != 0;
   7976                     boolean nowGone = msg.arg2 != 0;
   7977 
   7978                     try {
   7979                         if (DEBUG_VISIBILITY) Slog.v(
   7980                                 TAG, "Reporting visible in " + wtoken
   7981                                 + " visible=" + nowVisible
   7982                                 + " gone=" + nowGone);
   7983                         if (nowVisible) {
   7984                             wtoken.appToken.windowsVisible();
   7985                         } else {
   7986                             wtoken.appToken.windowsGone();
   7987                         }
   7988                     } catch (RemoteException ex) {
   7989                     }
   7990                 } break;
   7991 
   7992                 case WINDOW_FREEZE_TIMEOUT: {
   7993                     synchronized (mWindowMap) {
   7994                         Slog.w(TAG, "Window freeze timeout expired.");
   7995                         int i = mWindows.size();
   7996                         while (i > 0) {
   7997                             i--;
   7998                             WindowState w = mWindows.get(i);
   7999                             if (w.mOrientationChanging) {
   8000                                 w.mOrientationChanging = false;
   8001                                 Slog.w(TAG, "Force clearing orientation change: " + w);
   8002                             }
   8003                         }
   8004                         performLayoutAndPlaceSurfacesLocked();
   8005                     }
   8006                     break;
   8007                 }
   8008 
   8009                 case HOLD_SCREEN_CHANGED: {
   8010                     Session oldHold;
   8011                     Session newHold;
   8012                     synchronized (mWindowMap) {
   8013                         oldHold = mLastReportedHold;
   8014                         newHold = (Session)msg.obj;
   8015                         mLastReportedHold = newHold;
   8016                     }
   8017 
   8018                     if (oldHold != newHold) {
   8019                         try {
   8020                             if (oldHold != null) {
   8021                                 mBatteryStats.noteStopWakelock(oldHold.mUid, -1,
   8022                                         "window",
   8023                                         BatteryStats.WAKE_TYPE_WINDOW);
   8024                             }
   8025                             if (newHold != null) {
   8026                                 mBatteryStats.noteStartWakelock(newHold.mUid, -1,
   8027                                         "window",
   8028                                         BatteryStats.WAKE_TYPE_WINDOW);
   8029                             }
   8030                         } catch (RemoteException e) {
   8031                         }
   8032                     }
   8033                     break;
   8034                 }
   8035 
   8036                 case APP_TRANSITION_TIMEOUT: {
   8037                     synchronized (mWindowMap) {
   8038                         if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
   8039                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
   8040                                     "*** APP TRANSITION TIMEOUT");
   8041                             mAppTransitionReady = true;
   8042                             mAppTransitionTimeout = true;
   8043                             performLayoutAndPlaceSurfacesLocked();
   8044                         }
   8045                     }
   8046                     break;
   8047                 }
   8048 
   8049                 case PERSIST_ANIMATION_SCALE: {
   8050                     Settings.System.putFloat(mContext.getContentResolver(),
   8051                             Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
   8052                     Settings.System.putFloat(mContext.getContentResolver(),
   8053                             Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
   8054                     break;
   8055                 }
   8056 
   8057                 case FORCE_GC: {
   8058                     synchronized(mWindowMap) {
   8059                         if (mAnimationPending) {
   8060                             // If we are animating, don't do the gc now but
   8061                             // delay a bit so we don't interrupt the animation.
   8062                             mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
   8063                                     2000);
   8064                             return;
   8065                         }
   8066                         // If we are currently rotating the display, it will
   8067                         // schedule a new message when done.
   8068                         if (mDisplayFrozen) {
   8069                             return;
   8070                         }
   8071                         mFreezeGcPending = 0;
   8072                     }
   8073                     Runtime.getRuntime().gc();
   8074                     break;
   8075                 }
   8076 
   8077                 case ENABLE_SCREEN: {
   8078                     performEnableScreen();
   8079                     break;
   8080                 }
   8081 
   8082                 case APP_FREEZE_TIMEOUT: {
   8083                     synchronized (mWindowMap) {
   8084                         Slog.w(TAG, "App freeze timeout expired.");
   8085                         int i = mAppTokens.size();
   8086                         while (i > 0) {
   8087                             i--;
   8088                             AppWindowToken tok = mAppTokens.get(i);
   8089                             if (tok.freezingScreen) {
   8090                                 Slog.w(TAG, "Force clearing freeze: " + tok);
   8091                                 unsetAppFreezingScreenLocked(tok, true, true);
   8092                             }
   8093                         }
   8094                     }
   8095                     break;
   8096                 }
   8097 
   8098                 case SEND_NEW_CONFIGURATION: {
   8099                     removeMessages(SEND_NEW_CONFIGURATION);
   8100                     sendNewConfiguration();
   8101                     break;
   8102                 }
   8103 
   8104                 case REPORT_WINDOWS_CHANGE: {
   8105                     if (mWindowsChanged) {
   8106                         synchronized (mWindowMap) {
   8107                             mWindowsChanged = false;
   8108                         }
   8109                         notifyWindowsChanged();
   8110                     }
   8111                     break;
   8112                 }
   8113 
   8114             }
   8115         }
   8116     }
   8117 
   8118     // -------------------------------------------------------------
   8119     // IWindowManager API
   8120     // -------------------------------------------------------------
   8121 
   8122     public IWindowSession openSession(IInputMethodClient client,
   8123             IInputContext inputContext) {
   8124         if (client == null) throw new IllegalArgumentException("null client");
   8125         if (inputContext == null) throw new IllegalArgumentException("null inputContext");
   8126         Session session = new Session(client, inputContext);
   8127         return session;
   8128     }
   8129 
   8130     public boolean inputMethodClientHasFocus(IInputMethodClient client) {
   8131         synchronized (mWindowMap) {
   8132             // The focus for the client is the window immediately below
   8133             // where we would place the input method window.
   8134             int idx = findDesiredInputMethodWindowIndexLocked(false);
   8135             WindowState imFocus;
   8136             if (idx > 0) {
   8137                 imFocus = mWindows.get(idx-1);
   8138                 if (imFocus != null) {
   8139                     if (imFocus.mSession.mClient != null &&
   8140                             imFocus.mSession.mClient.asBinder() == client.asBinder()) {
   8141                         return true;
   8142                     }
   8143                 }
   8144             }
   8145         }
   8146         return false;
   8147     }
   8148 
   8149     // -------------------------------------------------------------
   8150     // Internals
   8151     // -------------------------------------------------------------
   8152 
   8153     final WindowState windowForClientLocked(Session session, IWindow client,
   8154             boolean throwOnError) {
   8155         return windowForClientLocked(session, client.asBinder(), throwOnError);
   8156     }
   8157 
   8158     final WindowState windowForClientLocked(Session session, IBinder client,
   8159             boolean throwOnError) {
   8160         WindowState win = mWindowMap.get(client);
   8161         if (localLOGV) Slog.v(
   8162             TAG, "Looking up client " + client + ": " + win);
   8163         if (win == null) {
   8164             RuntimeException ex = new IllegalArgumentException(
   8165                     "Requested window " + client + " does not exist");
   8166             if (throwOnError) {
   8167                 throw ex;
   8168             }
   8169             Slog.w(TAG, "Failed looking up window", ex);
   8170             return null;
   8171         }
   8172         if (session != null && win.mSession != session) {
   8173             RuntimeException ex = new IllegalArgumentException(
   8174                     "Requested window " + client + " is in session " +
   8175                     win.mSession + ", not " + session);
   8176             if (throwOnError) {
   8177                 throw ex;
   8178             }
   8179             Slog.w(TAG, "Failed looking up window", ex);
   8180             return null;
   8181         }
   8182 
   8183         return win;
   8184     }
   8185 
   8186     final void rebuildAppWindowListLocked() {
   8187         int NW = mWindows.size();
   8188         int i;
   8189         int lastWallpaper = -1;
   8190         int numRemoved = 0;
   8191 
   8192         // First remove all existing app windows.
   8193         i=0;
   8194         while (i < NW) {
   8195             WindowState w = mWindows.get(i);
   8196             if (w.mAppToken != null) {
   8197                 WindowState win = mWindows.remove(i);
   8198                 mWindowsChanged = true;
   8199                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
   8200                         "Rebuild removing window: " + win);
   8201                 NW--;
   8202                 numRemoved++;
   8203                 continue;
   8204             } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER
   8205                     && lastWallpaper == i-1) {
   8206                 lastWallpaper = i;
   8207             }
   8208             i++;
   8209         }
   8210 
   8211         // The wallpaper window(s) typically live at the bottom of the stack,
   8212         // so skip them before adding app tokens.
   8213         lastWallpaper++;
   8214         i = lastWallpaper;
   8215 
   8216         // First add all of the exiting app tokens...  these are no longer
   8217         // in the main app list, but still have windows shown.  We put them
   8218         // in the back because now that the animation is over we no longer
   8219         // will care about them.
   8220         int NT = mExitingAppTokens.size();
   8221         for (int j=0; j<NT; j++) {
   8222             i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j));
   8223         }
   8224 
   8225         // And add in the still active app tokens in Z order.
   8226         NT = mAppTokens.size();
   8227         for (int j=0; j<NT; j++) {
   8228             i = reAddAppWindowsLocked(i, mAppTokens.get(j));
   8229         }
   8230 
   8231         i -= lastWallpaper;
   8232         if (i != numRemoved) {
   8233             Slog.w(TAG, "Rebuild removed " + numRemoved
   8234                     + " windows but added " + i);
   8235         }
   8236     }
   8237 
   8238     private final void assignLayersLocked() {
   8239         int N = mWindows.size();
   8240         int curBaseLayer = 0;
   8241         int curLayer = 0;
   8242         int i;
   8243 
   8244         for (i=0; i<N; i++) {
   8245             WindowState w = mWindows.get(i);
   8246             if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
   8247                     || (i > 0 && w.mIsWallpaper)) {
   8248                 curLayer += WINDOW_LAYER_MULTIPLIER;
   8249                 w.mLayer = curLayer;
   8250             } else {
   8251                 curBaseLayer = curLayer = w.mBaseLayer;
   8252                 w.mLayer = curLayer;
   8253             }
   8254             if (w.mTargetAppToken != null) {
   8255                 w.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment;
   8256             } else if (w.mAppToken != null) {
   8257                 w.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment;
   8258             } else {
   8259                 w.mAnimLayer = w.mLayer;
   8260             }
   8261             if (w.mIsImWindow) {
   8262                 w.mAnimLayer += mInputMethodAnimLayerAdjustment;
   8263             } else if (w.mIsWallpaper) {
   8264                 w.mAnimLayer += mWallpaperAnimLayerAdjustment;
   8265             }
   8266             if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
   8267                     + w.mAnimLayer);
   8268             //System.out.println(
   8269             //    "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
   8270         }
   8271     }
   8272 
   8273     private boolean mInLayout = false;
   8274     private final void performLayoutAndPlaceSurfacesLocked() {
   8275         if (mInLayout) {
   8276             if (DEBUG) {
   8277                 throw new RuntimeException("Recursive call!");
   8278             }
   8279             Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout");
   8280             return;
   8281         }
   8282 
   8283         if (mWaitingForConfig) {
   8284             // Our configuration has changed (most likely rotation), but we
   8285             // don't yet have the complete configuration to report to
   8286             // applications.  Don't do any window layout until we have it.
   8287             return;
   8288         }
   8289 
   8290         if (mDisplay == null) {
   8291             // Not yet initialized, nothing to do.
   8292             return;
   8293         }
   8294 
   8295         boolean recoveringMemory = false;
   8296         if (mForceRemoves != null) {
   8297             recoveringMemory = true;
   8298             // Wait a little it for things to settle down, and off we go.
   8299             for (int i=0; i<mForceRemoves.size(); i++) {
   8300                 WindowState ws = mForceRemoves.get(i);
   8301                 Slog.i(TAG, "Force removing: " + ws);
   8302                 removeWindowInnerLocked(ws.mSession, ws);
   8303             }
   8304             mForceRemoves = null;
   8305             Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
   8306             Object tmp = new Object();
   8307             synchronized (tmp) {
   8308                 try {
   8309                     tmp.wait(250);
   8310                 } catch (InterruptedException e) {
   8311                 }
   8312             }
   8313         }
   8314 
   8315         mInLayout = true;
   8316         try {
   8317             performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
   8318 
   8319             int i = mPendingRemove.size()-1;
   8320             if (i >= 0) {
   8321                 while (i >= 0) {
   8322                     WindowState w = mPendingRemove.get(i);
   8323                     removeWindowInnerLocked(w.mSession, w);
   8324                     i--;
   8325                 }
   8326                 mPendingRemove.clear();
   8327 
   8328                 mInLayout = false;
   8329                 assignLayersLocked();
   8330                 mLayoutNeeded = true;
   8331                 performLayoutAndPlaceSurfacesLocked();
   8332 
   8333             } else {
   8334                 mInLayout = false;
   8335                 if (mLayoutNeeded) {
   8336                     requestAnimationLocked(0);
   8337                 }
   8338             }
   8339             if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
   8340                 mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
   8341                 mH.sendMessage(mH.obtainMessage(H.REPORT_WINDOWS_CHANGE));
   8342             }
   8343         } catch (RuntimeException e) {
   8344             mInLayout = false;
   8345             Slog.e(TAG, "Unhandled exception while layout out windows", e);
   8346         }
   8347     }
   8348 
   8349     private final int performLayoutLockedInner() {
   8350         if (!mLayoutNeeded) {
   8351             return 0;
   8352         }
   8353 
   8354         mLayoutNeeded = false;
   8355 
   8356         final int dw = mDisplay.getWidth();
   8357         final int dh = mDisplay.getHeight();
   8358 
   8359         final int N = mWindows.size();
   8360         int i;
   8361 
   8362         if (DEBUG_LAYOUT) Slog.v(TAG, "performLayout: needed="
   8363                 + mLayoutNeeded + " dw=" + dw + " dh=" + dh);
   8364 
   8365         mPolicy.beginLayoutLw(dw, dh);
   8366 
   8367         int seq = mLayoutSeq+1;
   8368         if (seq < 0) seq = 0;
   8369         mLayoutSeq = seq;
   8370 
   8371         // First perform layout of any root windows (not attached
   8372         // to another window).
   8373         int topAttached = -1;
   8374         for (i = N-1; i >= 0; i--) {
   8375             WindowState win = mWindows.get(i);
   8376 
   8377             // Don't do layout of a window if it is not visible, or
   8378             // soon won't be visible, to avoid wasting time and funky
   8379             // changes while a window is animating away.
   8380             final AppWindowToken atoken = win.mAppToken;
   8381             final boolean gone = win.mViewVisibility == View.GONE
   8382                     || !win.mRelayoutCalled
   8383                     || win.mRootToken.hidden
   8384                     || (atoken != null && atoken.hiddenRequested)
   8385                     || win.mAttachedHidden
   8386                     || win.mExiting || win.mDestroying;
   8387 
   8388             if (!win.mLayoutAttached) {
   8389                 if (DEBUG_LAYOUT) Slog.v(TAG, "First pass " + win
   8390                         + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
   8391                         + " mLayoutAttached=" + win.mLayoutAttached);
   8392                 if (DEBUG_LAYOUT && gone) Slog.v(TAG, "  (mViewVisibility="
   8393                         + win.mViewVisibility + " mRelayoutCalled="
   8394                         + win.mRelayoutCalled + " hidden="
   8395                         + win.mRootToken.hidden + " hiddenRequested="
   8396                         + (atoken != null && atoken.hiddenRequested)
   8397                         + " mAttachedHidden=" + win.mAttachedHidden);
   8398             }
   8399 
   8400             // If this view is GONE, then skip it -- keep the current
   8401             // frame, and let the caller know so they can ignore it
   8402             // if they want.  (We do the normal layout for INVISIBLE
   8403             // windows, since that means "perform layout as normal,
   8404             // just don't display").
   8405             if (!gone || !win.mHaveFrame) {
   8406                 if (!win.mLayoutAttached) {
   8407                     mPolicy.layoutWindowLw(win, win.mAttrs, null);
   8408                     win.mLayoutSeq = seq;
   8409                     if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
   8410                             + win.mFrame + " mContainingFrame="
   8411                             + win.mContainingFrame + " mDisplayFrame="
   8412                             + win.mDisplayFrame);
   8413                 } else {
   8414                     if (topAttached < 0) topAttached = i;
   8415                 }
   8416             }
   8417         }
   8418 
   8419         // Now perform layout of attached windows, which usually
   8420         // depend on the position of the window they are attached to.
   8421         // XXX does not deal with windows that are attached to windows
   8422         // that are themselves attached.
   8423         for (i = topAttached; i >= 0; i--) {
   8424             WindowState win = mWindows.get(i);
   8425 
   8426             // If this view is GONE, then skip it -- keep the current
   8427             // frame, and let the caller know so they can ignore it
   8428             // if they want.  (We do the normal layout for INVISIBLE
   8429             // windows, since that means "perform layout as normal,
   8430             // just don't display").
   8431             if (win.mLayoutAttached) {
   8432                 if (DEBUG_LAYOUT) Slog.v(TAG, "Second pass " + win
   8433                         + " mHaveFrame=" + win.mHaveFrame
   8434                         + " mViewVisibility=" + win.mViewVisibility
   8435                         + " mRelayoutCalled=" + win.mRelayoutCalled);
   8436                 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
   8437                         || !win.mHaveFrame) {
   8438                     mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
   8439                     win.mLayoutSeq = seq;
   8440                     if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
   8441                             + win.mFrame + " mContainingFrame="
   8442                             + win.mContainingFrame + " mDisplayFrame="
   8443                             + win.mDisplayFrame);
   8444                 }
   8445             }
   8446         }
   8447 
   8448         // Window frames may have changed.  Tell the input dispatcher about it.
   8449         mInputMonitor.updateInputWindowsLw();
   8450 
   8451         return mPolicy.finishLayoutLw();
   8452     }
   8453 
   8454     private final void performLayoutAndPlaceSurfacesLockedInner(
   8455             boolean recoveringMemory) {
   8456         final long currentTime = SystemClock.uptimeMillis();
   8457         final int dw = mDisplay.getWidth();
   8458         final int dh = mDisplay.getHeight();
   8459 
   8460         int i;
   8461 
   8462         if (mFocusMayChange) {
   8463             mFocusMayChange = false;
   8464             updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
   8465         }
   8466 
   8467         // Initialize state of exiting tokens.
   8468         for (i=mExitingTokens.size()-1; i>=0; i--) {
   8469             mExitingTokens.get(i).hasVisible = false;
   8470         }
   8471 
   8472         // Initialize state of exiting applications.
   8473         for (i=mExitingAppTokens.size()-1; i>=0; i--) {
   8474             mExitingAppTokens.get(i).hasVisible = false;
   8475         }
   8476 
   8477         boolean orientationChangeComplete = true;
   8478         Session holdScreen = null;
   8479         float screenBrightness = -1;
   8480         float buttonBrightness = -1;
   8481         boolean focusDisplayed = false;
   8482         boolean animating = false;
   8483         boolean createWatermark = false;
   8484 
   8485         if (mFxSession == null) {
   8486             mFxSession = new SurfaceSession();
   8487             createWatermark = true;
   8488         }
   8489 
   8490         if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
   8491 
   8492         Surface.openTransaction();
   8493 
   8494         if (createWatermark) {
   8495             createWatermark();
   8496         }
   8497         if (mWatermark != null) {
   8498             mWatermark.positionSurface(dw, dh);
   8499         }
   8500 
   8501         try {
   8502             boolean wallpaperForceHidingChanged = false;
   8503             int repeats = 0;
   8504             int changes = 0;
   8505 
   8506             do {
   8507                 repeats++;
   8508                 if (repeats > 6) {
   8509                     Slog.w(TAG, "Animation repeat aborted after too many iterations");
   8510                     mLayoutNeeded = false;
   8511                     break;
   8512                 }
   8513 
   8514                 if ((changes&(WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER
   8515                         | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG
   8516                         | WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT)) != 0) {
   8517                     if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
   8518                         if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
   8519                             assignLayersLocked();
   8520                             mLayoutNeeded = true;
   8521                         }
   8522                     }
   8523                     if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
   8524                         if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
   8525                         if (updateOrientationFromAppTokensLocked()) {
   8526                             mLayoutNeeded = true;
   8527                             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
   8528                         }
   8529                     }
   8530                     if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
   8531                         mLayoutNeeded = true;
   8532                     }
   8533                 }
   8534 
   8535                 // FIRST LOOP: Perform a layout, if needed.
   8536                 if (repeats < 4) {
   8537                     changes = performLayoutLockedInner();
   8538                     if (changes != 0) {
   8539                         continue;
   8540                     }
   8541                 } else {
   8542                     Slog.w(TAG, "Layout repeat skipped after too many iterations");
   8543                     changes = 0;
   8544                 }
   8545 
   8546                 final int transactionSequence = ++mTransactionSequence;
   8547 
   8548                 // Update animations of all applications, including those
   8549                 // associated with exiting/removed apps
   8550                 boolean tokensAnimating = false;
   8551                 final int NAT = mAppTokens.size();
   8552                 for (i=0; i<NAT; i++) {
   8553                     if (mAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
   8554                         tokensAnimating = true;
   8555                     }
   8556                 }
   8557                 final int NEAT = mExitingAppTokens.size();
   8558                 for (i=0; i<NEAT; i++) {
   8559                     if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
   8560                         tokensAnimating = true;
   8561                     }
   8562                 }
   8563 
   8564                 // SECOND LOOP: Execute animations and update visibility of windows.
   8565 
   8566                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq="
   8567                         + transactionSequence + " tokensAnimating="
   8568                         + tokensAnimating);
   8569 
   8570                 animating = tokensAnimating;
   8571 
   8572                 boolean tokenMayBeDrawn = false;
   8573                 boolean wallpaperMayChange = false;
   8574                 boolean forceHiding = false;
   8575 
   8576                 mPolicy.beginAnimationLw(dw, dh);
   8577 
   8578                 final int N = mWindows.size();
   8579 
   8580                 for (i=N-1; i>=0; i--) {
   8581                     WindowState w = mWindows.get(i);
   8582 
   8583                     final WindowManager.LayoutParams attrs = w.mAttrs;
   8584 
   8585                     if (w.mSurface != null) {
   8586                         // Execute animation.
   8587                         if (w.commitFinishDrawingLocked(currentTime)) {
   8588                             if ((w.mAttrs.flags
   8589                                     & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
   8590                                 if (DEBUG_WALLPAPER) Slog.v(TAG,
   8591                                         "First draw done in potential wallpaper target " + w);
   8592                                 wallpaperMayChange = true;
   8593                             }
   8594                         }
   8595 
   8596                         boolean wasAnimating = w.mAnimating;
   8597                         if (w.stepAnimationLocked(currentTime, dw, dh)) {
   8598                             animating = true;
   8599                             //w.dump("  ");
   8600                         }
   8601                         if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) {
   8602                             wallpaperMayChange = true;
   8603                         }
   8604 
   8605                         if (mPolicy.doesForceHide(w, attrs)) {
   8606                             if (!wasAnimating && animating) {
   8607                                 if (DEBUG_VISIBILITY) Slog.v(TAG,
   8608                                         "Animation done that could impact force hide: "
   8609                                         + w);
   8610                                 wallpaperForceHidingChanged = true;
   8611                                 mFocusMayChange = true;
   8612                             } else if (w.isReadyForDisplay() && w.mAnimation == null) {
   8613                                 forceHiding = true;
   8614                             }
   8615                         } else if (mPolicy.canBeForceHidden(w, attrs)) {
   8616                             boolean changed;
   8617                             if (forceHiding) {
   8618                                 changed = w.hideLw(false, false);
   8619                                 if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
   8620                                         "Now policy hidden: " + w);
   8621                             } else {
   8622                                 changed = w.showLw(false, false);
   8623                                 if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
   8624                                         "Now policy shown: " + w);
   8625                                 if (changed) {
   8626                                     if (wallpaperForceHidingChanged
   8627                                             && w.isVisibleNow() /*w.isReadyForDisplay()*/) {
   8628                                         // Assume we will need to animate.  If
   8629                                         // we don't (because the wallpaper will
   8630                                         // stay with the lock screen), then we will
   8631                                         // clean up later.
   8632                                         Animation a = mPolicy.createForceHideEnterAnimation();
   8633                                         if (a != null) {
   8634                                             w.setAnimation(a);
   8635                                         }
   8636                                     }
   8637                                     if (mCurrentFocus == null ||
   8638                                             mCurrentFocus.mLayer < w.mLayer) {
   8639                                         // We are showing on to of the current
   8640                                         // focus, so re-evaluate focus to make
   8641                                         // sure it is correct.
   8642                                         mFocusMayChange = true;
   8643                                     }
   8644                                 }
   8645                             }
   8646                             if (changed && (attrs.flags
   8647                                     & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
   8648                                 wallpaperMayChange = true;
   8649                             }
   8650                         }
   8651 
   8652                         mPolicy.animatingWindowLw(w, attrs);
   8653                     }
   8654 
   8655                     final AppWindowToken atoken = w.mAppToken;
   8656                     if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) {
   8657                         if (atoken.lastTransactionSequence != transactionSequence) {
   8658                             atoken.lastTransactionSequence = transactionSequence;
   8659                             atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
   8660                             atoken.startingDisplayed = false;
   8661                         }
   8662                         if ((w.isOnScreen() || w.mAttrs.type
   8663                                 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
   8664                                 && !w.mExiting && !w.mDestroying) {
   8665                             if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
   8666                                 Slog.v(TAG, "Eval win " + w + ": isDrawn="
   8667                                         + w.isDrawnLw()
   8668                                         + ", isAnimating=" + w.isAnimating());
   8669                                 if (!w.isDrawnLw()) {
   8670                                     Slog.v(TAG, "Not displayed: s=" + w.mSurface
   8671                                             + " pv=" + w.mPolicyVisibility
   8672                                             + " dp=" + w.mDrawPending
   8673                                             + " cdp=" + w.mCommitDrawPending
   8674                                             + " ah=" + w.mAttachedHidden
   8675                                             + " th=" + atoken.hiddenRequested
   8676                                             + " a=" + w.mAnimating);
   8677                                 }
   8678                             }
   8679                             if (w != atoken.startingWindow) {
   8680                                 if (!atoken.freezingScreen || !w.mAppFreezing) {
   8681                                     atoken.numInterestingWindows++;
   8682                                     if (w.isDrawnLw()) {
   8683                                         atoken.numDrawnWindows++;
   8684                                         if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
   8685                                                 "tokenMayBeDrawn: " + atoken
   8686                                                 + " freezingScreen=" + atoken.freezingScreen
   8687                                                 + " mAppFreezing=" + w.mAppFreezing);
   8688                                         tokenMayBeDrawn = true;
   8689                                     }
   8690                                 }
   8691                             } else if (w.isDrawnLw()) {
   8692                                 atoken.startingDisplayed = true;
   8693                             }
   8694                         }
   8695                     } else if (w.mReadyToShow) {
   8696                         w.performShowLocked();
   8697                     }
   8698                 }
   8699 
   8700                 changes |= mPolicy.finishAnimationLw();
   8701 
   8702                 if (tokenMayBeDrawn) {
   8703                     // See if any windows have been drawn, so they (and others
   8704                     // associated with them) can now be shown.
   8705                     final int NT = mTokenList.size();
   8706                     for (i=0; i<NT; i++) {
   8707                         AppWindowToken wtoken = mTokenList.get(i).appWindowToken;
   8708                         if (wtoken == null) {
   8709                             continue;
   8710                         }
   8711                         if (wtoken.freezingScreen) {
   8712                             int numInteresting = wtoken.numInterestingWindows;
   8713                             if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
   8714                                 if (DEBUG_VISIBILITY) Slog.v(TAG,
   8715                                         "allDrawn: " + wtoken
   8716                                         + " interesting=" + numInteresting
   8717                                         + " drawn=" + wtoken.numDrawnWindows);
   8718                                 wtoken.showAllWindowsLocked();
   8719                                 unsetAppFreezingScreenLocked(wtoken, false, true);
   8720                                 orientationChangeComplete = true;
   8721                             }
   8722                         } else if (!wtoken.allDrawn) {
   8723                             int numInteresting = wtoken.numInterestingWindows;
   8724                             if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
   8725                                 if (DEBUG_VISIBILITY) Slog.v(TAG,
   8726                                         "allDrawn: " + wtoken
   8727                                         + " interesting=" + numInteresting
   8728                                         + " drawn=" + wtoken.numDrawnWindows);
   8729                                 wtoken.allDrawn = true;
   8730                                 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
   8731 
   8732                                 // We can now show all of the drawn windows!
   8733                                 if (!mOpeningApps.contains(wtoken)) {
   8734                                     wtoken.showAllWindowsLocked();
   8735                                 }
   8736                             }
   8737                         }
   8738                     }
   8739                 }
   8740 
   8741                 // If we are ready to perform an app transition, check through
   8742                 // all of the app tokens to be shown and see if they are ready
   8743                 // to go.
   8744                 if (mAppTransitionReady) {
   8745                     int NN = mOpeningApps.size();
   8746                     boolean goodToGo = true;
   8747                     if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
   8748                             "Checking " + NN + " opening apps (frozen="
   8749                             + mDisplayFrozen + " timeout="
   8750                             + mAppTransitionTimeout + ")...");
   8751                     if (!mDisplayFrozen && !mAppTransitionTimeout) {
   8752                         // If the display isn't frozen, wait to do anything until
   8753                         // all of the apps are ready.  Otherwise just go because
   8754                         // we'll unfreeze the display when everyone is ready.
   8755                         for (i=0; i<NN && goodToGo; i++) {
   8756                             AppWindowToken wtoken = mOpeningApps.get(i);
   8757                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
   8758                                     "Check opening app" + wtoken + ": allDrawn="
   8759                                     + wtoken.allDrawn + " startingDisplayed="
   8760                                     + wtoken.startingDisplayed);
   8761                             if (!wtoken.allDrawn && !wtoken.startingDisplayed
   8762                                     && !wtoken.startingMoved) {
   8763                                 goodToGo = false;
   8764                             }
   8765                         }
   8766                     }
   8767                     if (goodToGo) {
   8768                         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
   8769                         int transit = mNextAppTransition;
   8770                         if (mSkipAppTransitionAnimation) {
   8771                             transit = WindowManagerPolicy.TRANSIT_UNSET;
   8772                         }
   8773                         mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
   8774                         mAppTransitionReady = false;
   8775                         mAppTransitionRunning = true;
   8776                         mAppTransitionTimeout = false;
   8777                         mStartingIconInTransition = false;
   8778                         mSkipAppTransitionAnimation = false;
   8779 
   8780                         mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
   8781 
   8782                         // If there are applications waiting to come to the
   8783                         // top of the stack, now is the time to move their windows.
   8784                         // (Note that we don't do apps going to the bottom
   8785                         // here -- we want to keep their windows in the old
   8786                         // Z-order until the animation completes.)
   8787                         if (mToTopApps.size() > 0) {
   8788                             NN = mAppTokens.size();
   8789                             for (i=0; i<NN; i++) {
   8790                                 AppWindowToken wtoken = mAppTokens.get(i);
   8791                                 if (wtoken.sendingToTop) {
   8792                                     wtoken.sendingToTop = false;
   8793                                     moveAppWindowsLocked(wtoken, NN, false);
   8794                                 }
   8795                             }
   8796                             mToTopApps.clear();
   8797                         }
   8798 
   8799                         WindowState oldWallpaper = mWallpaperTarget;
   8800 
   8801                         adjustWallpaperWindowsLocked();
   8802                         wallpaperMayChange = false;
   8803 
   8804                         // The top-most window will supply the layout params,
   8805                         // and we will determine it below.
   8806                         LayoutParams animLp = null;
   8807                         AppWindowToken animToken = null;
   8808                         int bestAnimLayer = -1;
   8809 
   8810                         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
   8811                                 "New wallpaper target=" + mWallpaperTarget
   8812                                 + ", lower target=" + mLowerWallpaperTarget
   8813                                 + ", upper target=" + mUpperWallpaperTarget);
   8814                         int foundWallpapers = 0;
   8815                         // Do a first pass through the tokens for two
   8816                         // things:
   8817                         // (1) Determine if both the closing and opening
   8818                         // app token sets are wallpaper targets, in which
   8819                         // case special animations are needed
   8820                         // (since the wallpaper needs to stay static
   8821                         // behind them).
   8822                         // (2) Find the layout params of the top-most
   8823                         // application window in the tokens, which is
   8824                         // what will control the animation theme.
   8825                         final int NC = mClosingApps.size();
   8826                         NN = NC + mOpeningApps.size();
   8827                         for (i=0; i<NN; i++) {
   8828                             AppWindowToken wtoken;
   8829                             int mode;
   8830                             if (i < NC) {
   8831                                 wtoken = mClosingApps.get(i);
   8832                                 mode = 1;
   8833                             } else {
   8834                                 wtoken = mOpeningApps.get(i-NC);
   8835                                 mode = 2;
   8836                             }
   8837                             if (mLowerWallpaperTarget != null) {
   8838                                 if (mLowerWallpaperTarget.mAppToken == wtoken
   8839                                         || mUpperWallpaperTarget.mAppToken == wtoken) {
   8840                                     foundWallpapers |= mode;
   8841                                 }
   8842                             }
   8843                             if (wtoken.appFullscreen) {
   8844                                 WindowState ws = wtoken.findMainWindow();
   8845                                 if (ws != null) {
   8846                                     // If this is a compatibility mode
   8847                                     // window, we will always use its anim.
   8848                                     if ((ws.mAttrs.flags&FLAG_COMPATIBLE_WINDOW) != 0) {
   8849                                         animLp = ws.mAttrs;
   8850                                         animToken = ws.mAppToken;
   8851                                         bestAnimLayer = Integer.MAX_VALUE;
   8852                                     } else if (ws.mLayer > bestAnimLayer) {
   8853                                         animLp = ws.mAttrs;
   8854                                         animToken = ws.mAppToken;
   8855                                         bestAnimLayer = ws.mLayer;
   8856                                     }
   8857                                 }
   8858                             }
   8859                         }
   8860 
   8861                         if (foundWallpapers == 3) {
   8862                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
   8863                                     "Wallpaper animation!");
   8864                             switch (transit) {
   8865                                 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
   8866                                 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
   8867                                 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
   8868                                     transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN;
   8869                                     break;
   8870                                 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
   8871                                 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
   8872                                 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
   8873                                     transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE;
   8874                                     break;
   8875                             }
   8876                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
   8877                                     "New transit: " + transit);
   8878                         } else if (oldWallpaper != null) {
   8879                             // We are transitioning from an activity with
   8880                             // a wallpaper to one without.
   8881                             transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE;
   8882                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
   8883                                     "New transit away from wallpaper: " + transit);
   8884                         } else if (mWallpaperTarget != null) {
   8885                             // We are transitioning from an activity without
   8886                             // a wallpaper to now showing the wallpaper
   8887                             transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN;
   8888                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
   8889                                     "New transit into wallpaper: " + transit);
   8890                         }
   8891 
   8892                         if ((transit&WindowManagerPolicy.TRANSIT_ENTER_MASK) != 0) {
   8893                             mLastEnterAnimToken = animToken;
   8894                             mLastEnterAnimParams = animLp;
   8895                         } else if (mLastEnterAnimParams != null) {
   8896                             animLp = mLastEnterAnimParams;
   8897                             mLastEnterAnimToken = null;
   8898                             mLastEnterAnimParams = null;
   8899                         }
   8900 
   8901                         // If all closing windows are obscured, then there is
   8902                         // no need to do an animation.  This is the case, for
   8903                         // example, when this transition is being done behind
   8904                         // the lock screen.
   8905                         if (!mPolicy.allowAppAnimationsLw()) {
   8906                             animLp = null;
   8907                         }
   8908 
   8909                         NN = mOpeningApps.size();
   8910                         for (i=0; i<NN; i++) {
   8911                             AppWindowToken wtoken = mOpeningApps.get(i);
   8912                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
   8913                                     "Now opening app" + wtoken);
   8914                             wtoken.reportedVisible = false;
   8915                             wtoken.inPendingTransaction = false;
   8916                             wtoken.animation = null;
   8917                             setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
   8918                             wtoken.updateReportedVisibilityLocked();
   8919                             wtoken.waitingToShow = false;
   8920                             wtoken.showAllWindowsLocked();
   8921                         }
   8922                         NN = mClosingApps.size();
   8923                         for (i=0; i<NN; i++) {
   8924                             AppWindowToken wtoken = mClosingApps.get(i);
   8925                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
   8926                                     "Now closing app" + wtoken);
   8927                             wtoken.inPendingTransaction = false;
   8928                             wtoken.animation = null;
   8929                             setTokenVisibilityLocked(wtoken, animLp, false, transit, false);
   8930                             wtoken.updateReportedVisibilityLocked();
   8931                             wtoken.waitingToHide = false;
   8932                             // Force the allDrawn flag, because we want to start
   8933                             // this guy's animations regardless of whether it's
   8934                             // gotten drawn.
   8935                             wtoken.allDrawn = true;
   8936                         }
   8937 
   8938                         mNextAppTransitionPackage = null;
   8939 
   8940                         mOpeningApps.clear();
   8941                         mClosingApps.clear();
   8942 
   8943                         // This has changed the visibility of windows, so perform
   8944                         // a new layout to get them all up-to-date.
   8945                         changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
   8946                         mLayoutNeeded = true;
   8947                         if (!moveInputMethodWindowsIfNeededLocked(true)) {
   8948                             assignLayersLocked();
   8949                         }
   8950                         updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES);
   8951                         mFocusMayChange = false;
   8952                     }
   8953                 }
   8954 
   8955                 int adjResult = 0;
   8956 
   8957                 if (!animating && mAppTransitionRunning) {
   8958                     // We have finished the animation of an app transition.  To do
   8959                     // this, we have delayed a lot of operations like showing and
   8960                     // hiding apps, moving apps in Z-order, etc.  The app token list
   8961                     // reflects the correct Z-order, but the window list may now
   8962                     // be out of sync with it.  So here we will just rebuild the
   8963                     // entire app window list.  Fun!
   8964                     mAppTransitionRunning = false;
   8965                     // Clear information about apps that were moving.
   8966                     mToBottomApps.clear();
   8967 
   8968                     rebuildAppWindowListLocked();
   8969                     changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
   8970                     adjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED;
   8971                     moveInputMethodWindowsIfNeededLocked(false);
   8972                     wallpaperMayChange = true;
   8973                     // Since the window list has been rebuilt, focus might
   8974                     // have to be recomputed since the actual order of windows
   8975                     // might have changed again.
   8976                     mFocusMayChange = true;
   8977                 }
   8978 
   8979                 if (wallpaperForceHidingChanged && changes == 0 && !mAppTransitionReady) {
   8980                     // At this point, there was a window with a wallpaper that
   8981                     // was force hiding other windows behind it, but now it
   8982                     // is going away.  This may be simple -- just animate
   8983                     // away the wallpaper and its window -- or it may be
   8984                     // hard -- the wallpaper now needs to be shown behind
   8985                     // something that was hidden.
   8986                     WindowState oldWallpaper = mWallpaperTarget;
   8987                     if (mLowerWallpaperTarget != null
   8988                             && mLowerWallpaperTarget.mAppToken != null) {
   8989                         if (DEBUG_WALLPAPER) Slog.v(TAG,
   8990                                 "wallpaperForceHiding changed with lower="
   8991                                 + mLowerWallpaperTarget);
   8992                         if (DEBUG_WALLPAPER) Slog.v(TAG,
   8993                                 "hidden=" + mLowerWallpaperTarget.mAppToken.hidden +
   8994                                 " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested);
   8995                         if (mLowerWallpaperTarget.mAppToken.hidden) {
   8996                             // The lower target has become hidden before we
   8997                             // actually started the animation...  let's completely
   8998                             // re-evaluate everything.
   8999                             mLowerWallpaperTarget = mUpperWallpaperTarget = null;
   9000                             changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
   9001                         }
   9002                     }
   9003                     adjResult |= adjustWallpaperWindowsLocked();
   9004                     wallpaperMayChange = false;
   9005                     wallpaperForceHidingChanged = false;
   9006                     if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper
   9007                             + " NEW: " + mWallpaperTarget
   9008                             + " LOWER: " + mLowerWallpaperTarget);
   9009                     if (mLowerWallpaperTarget == null) {
   9010                         // Whoops, we don't need a special wallpaper animation.
   9011                         // Clear them out.
   9012                         forceHiding = false;
   9013                         for (i=N-1; i>=0; i--) {
   9014                             WindowState w = mWindows.get(i);
   9015                             if (w.mSurface != null) {
   9016                                 final WindowManager.LayoutParams attrs = w.mAttrs;
   9017                                 if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) {
   9018                                     if (DEBUG_FOCUS) Slog.i(TAG, "win=" + w + " force hides other windows");
   9019                                     forceHiding = true;
   9020                                 } else if (mPolicy.canBeForceHidden(w, attrs)) {
   9021                                     if (!w.mAnimating) {
   9022                                         // We set the animation above so it
   9023                                         // is not yet running.
   9024                                         w.clearAnimation();
   9025                                     }
   9026                                 }
   9027                             }
   9028                         }
   9029                     }
   9030                 }
   9031 
   9032                 if (wallpaperMayChange) {
   9033                     if (DEBUG_WALLPAPER) Slog.v(TAG,
   9034                             "Wallpaper may change!  Adjusting");
   9035                     adjResult |= adjustWallpaperWindowsLocked();
   9036                 }
   9037 
   9038                 if ((adjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
   9039                     if (DEBUG_WALLPAPER) Slog.v(TAG,
   9040                             "Wallpaper layer changed: assigning layers + relayout");
   9041                     changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
   9042                     assignLayersLocked();
   9043                 } else if ((adjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) {
   9044                     if (DEBUG_WALLPAPER) Slog.v(TAG,
   9045                             "Wallpaper visibility changed: relayout");
   9046                     changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
   9047                 }
   9048 
   9049                 if (mFocusMayChange) {
   9050                     mFocusMayChange = false;
   9051                     if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES)) {
   9052                         changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
   9053                         adjResult = 0;
   9054                     }
   9055                 }
   9056 
   9057                 if (mLayoutNeeded) {
   9058                     changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
   9059                 }
   9060 
   9061                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x"
   9062                         + Integer.toHexString(changes));
   9063 
   9064                 mInputMonitor.updateInputWindowsLw();
   9065             } while (changes != 0);
   9066 
   9067             // THIRD LOOP: Update the surfaces of all windows.
   9068 
   9069             final boolean someoneLosingFocus = mLosingFocus.size() != 0;
   9070 
   9071             boolean obscured = false;
   9072             boolean blurring = false;
   9073             boolean dimming = false;
   9074             boolean covered = false;
   9075             boolean syswin = false;
   9076             boolean backgroundFillerShown = false;
   9077 
   9078             final int N = mWindows.size();
   9079 
   9080             for (i=N-1; i>=0; i--) {
   9081                 WindowState w = mWindows.get(i);
   9082 
   9083                 boolean displayed = false;
   9084                 final WindowManager.LayoutParams attrs = w.mAttrs;
   9085                 final int attrFlags = attrs.flags;
   9086 
   9087                 if (w.mSurface != null) {
   9088                     // XXX NOTE: The logic here could be improved.  We have
   9089                     // the decision about whether to resize a window separated
   9090                     // from whether to hide the surface.  This can cause us to
   9091                     // resize a surface even if we are going to hide it.  You
   9092                     // can see this by (1) holding device in landscape mode on
   9093                     // home screen; (2) tapping browser icon (device will rotate
   9094                     // to landscape; (3) tap home.  The wallpaper will be resized
   9095                     // in step 2 but then immediately hidden, causing us to
   9096                     // have to resize and then redraw it again in step 3.  It
   9097                     // would be nice to figure out how to avoid this, but it is
   9098                     // difficult because we do need to resize surfaces in some
   9099                     // cases while they are hidden such as when first showing a
   9100                     // window.
   9101 
   9102                     w.computeShownFrameLocked();
   9103                     if (localLOGV) Slog.v(
   9104                             TAG, "Placing surface #" + i + " " + w.mSurface
   9105                             + ": new=" + w.mShownFrame + ", old="
   9106                             + w.mLastShownFrame);
   9107 
   9108                     boolean resize;
   9109                     int width, height;
   9110                     if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
   9111                         resize = w.mLastRequestedWidth != w.mRequestedWidth ||
   9112                         w.mLastRequestedHeight != w.mRequestedHeight;
   9113                         // for a scaled surface, we just want to use
   9114                         // the requested size.
   9115                         width  = w.mRequestedWidth;
   9116                         height = w.mRequestedHeight;
   9117                         w.mLastRequestedWidth = width;
   9118                         w.mLastRequestedHeight = height;
   9119                         w.mLastShownFrame.set(w.mShownFrame);
   9120                         try {
   9121                             if (SHOW_TRANSACTIONS) logSurface(w,
   9122                                     "POS " + w.mShownFrame.left
   9123                                     + ", " + w.mShownFrame.top, null);
   9124                             w.mSurfaceX = w.mShownFrame.left;
   9125                             w.mSurfaceY = w.mShownFrame.top;
   9126                             w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top);
   9127                         } catch (RuntimeException e) {
   9128                             Slog.w(TAG, "Error positioning surface in " + w, e);
   9129                             if (!recoveringMemory) {
   9130                                 reclaimSomeSurfaceMemoryLocked(w, "position");
   9131                             }
   9132                         }
   9133                     } else {
   9134                         resize = !w.mLastShownFrame.equals(w.mShownFrame);
   9135                         width = w.mShownFrame.width();
   9136                         height = w.mShownFrame.height();
   9137                         w.mLastShownFrame.set(w.mShownFrame);
   9138                     }
   9139 
   9140                     if (resize) {
   9141                         if (width < 1) width = 1;
   9142                         if (height < 1) height = 1;
   9143                         if (w.mSurface != null) {
   9144                             try {
   9145                                 if (SHOW_TRANSACTIONS) logSurface(w,
   9146                                         "POS " + w.mShownFrame.left + ","
   9147                                         + w.mShownFrame.top + " SIZE "
   9148                                         + w.mShownFrame.width() + "x"
   9149                                         + w.mShownFrame.height(), null);
   9150                                 w.mSurfaceResized = true;
   9151                                 w.mSurfaceW = width;
   9152                                 w.mSurfaceH = height;
   9153                                 w.mSurface.setSize(width, height);
   9154                                 w.mSurfaceX = w.mShownFrame.left;
   9155                                 w.mSurfaceY = w.mShownFrame.top;
   9156                                 w.mSurface.setPosition(w.mShownFrame.left,
   9157                                         w.mShownFrame.top);
   9158                             } catch (RuntimeException e) {
   9159                                 // If something goes wrong with the surface (such
   9160                                 // as running out of memory), don't take down the
   9161                                 // entire system.
   9162                                 Slog.e(TAG, "Failure updating surface of " + w
   9163                                         + "size=(" + width + "x" + height
   9164                                         + "), pos=(" + w.mShownFrame.left
   9165                                         + "," + w.mShownFrame.top + ")", e);
   9166                                 if (!recoveringMemory) {
   9167                                     reclaimSomeSurfaceMemoryLocked(w, "size");
   9168                                 }
   9169                             }
   9170                         }
   9171                     }
   9172                     if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
   9173                         w.mContentInsetsChanged =
   9174                             !w.mLastContentInsets.equals(w.mContentInsets);
   9175                         w.mVisibleInsetsChanged =
   9176                             !w.mLastVisibleInsets.equals(w.mVisibleInsets);
   9177                         boolean configChanged =
   9178                             w.mConfiguration != mCurConfiguration
   9179                             && (w.mConfiguration == null
   9180                                     || mCurConfiguration.diff(w.mConfiguration) != 0);
   9181                         if (DEBUG_CONFIGURATION && configChanged) {
   9182                             Slog.v(TAG, "Win " + w + " config changed: "
   9183                                     + mCurConfiguration);
   9184                         }
   9185                         if (localLOGV) Slog.v(TAG, "Resizing " + w
   9186                                 + ": configChanged=" + configChanged
   9187                                 + " last=" + w.mLastFrame + " frame=" + w.mFrame);
   9188                         if (!w.mLastFrame.equals(w.mFrame)
   9189                                 || w.mContentInsetsChanged
   9190                                 || w.mVisibleInsetsChanged
   9191                                 || w.mSurfaceResized
   9192                                 || configChanged) {
   9193                             w.mLastFrame.set(w.mFrame);
   9194                             w.mLastContentInsets.set(w.mContentInsets);
   9195                             w.mLastVisibleInsets.set(w.mVisibleInsets);
   9196                             // If the screen is currently frozen, then keep
   9197                             // it frozen until this window draws at its new
   9198                             // orientation.
   9199                             if (mDisplayFrozen) {
   9200                                 if (DEBUG_ORIENTATION) Slog.v(TAG,
   9201                                         "Resizing while display frozen: " + w);
   9202                                 w.mOrientationChanging = true;
   9203                                 if (!mWindowsFreezingScreen) {
   9204                                     mWindowsFreezingScreen = true;
   9205                                     // XXX should probably keep timeout from
   9206                                     // when we first froze the display.
   9207                                     mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
   9208                                     mH.sendMessageDelayed(mH.obtainMessage(
   9209                                             H.WINDOW_FREEZE_TIMEOUT), 2000);
   9210                                 }
   9211                             }
   9212                             // If the orientation is changing, then we need to
   9213                             // hold off on unfreezing the display until this
   9214                             // window has been redrawn; to do that, we need
   9215                             // to go through the process of getting informed
   9216                             // by the application when it has finished drawing.
   9217                             if (w.mOrientationChanging) {
   9218                                 if (DEBUG_ORIENTATION) Slog.v(TAG,
   9219                                         "Orientation start waiting for draw in "
   9220                                         + w + ", surface " + w.mSurface);
   9221                                 w.mDrawPending = true;
   9222                                 w.mCommitDrawPending = false;
   9223                                 w.mReadyToShow = false;
   9224                                 if (w.mAppToken != null) {
   9225                                     w.mAppToken.allDrawn = false;
   9226                                 }
   9227                             }
   9228                             if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
   9229                                     "Resizing window " + w + " to " + w.mFrame);
   9230                             mResizingWindows.add(w);
   9231                         } else if (w.mOrientationChanging) {
   9232                             if (!w.mDrawPending && !w.mCommitDrawPending) {
   9233                                 if (DEBUG_ORIENTATION) Slog.v(TAG,
   9234                                         "Orientation not waiting for draw in "
   9235                                         + w + ", surface " + w.mSurface);
   9236                                 w.mOrientationChanging = false;
   9237                             }
   9238                         }
   9239                     }
   9240 
   9241                     if (w.mAttachedHidden || !w.isReadyForDisplay()) {
   9242                         if (!w.mLastHidden) {
   9243                             //dump();
   9244                             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Window hiding: waitingToShow="
   9245                                     + w.mRootToken.waitingToShow + " polvis="
   9246                                     + w.mPolicyVisibility + " atthid="
   9247                                     + w.mAttachedHidden + " tokhid="
   9248                                     + w.mRootToken.hidden + " vis="
   9249                                     + w.mViewVisibility);
   9250                             w.mLastHidden = true;
   9251                             if (SHOW_TRANSACTIONS) logSurface(w,
   9252                                     "HIDE (performLayout)", null);
   9253                             if (w.mSurface != null) {
   9254                                 w.mSurfaceShown = false;
   9255                                 try {
   9256                                     w.mSurface.hide();
   9257                                 } catch (RuntimeException e) {
   9258                                     Slog.w(TAG, "Exception hiding surface in " + w);
   9259                                 }
   9260                             }
   9261                         }
   9262                         // If we are waiting for this window to handle an
   9263                         // orientation change, well, it is hidden, so
   9264                         // doesn't really matter.  Note that this does
   9265                         // introduce a potential glitch if the window
   9266                         // becomes unhidden before it has drawn for the
   9267                         // new orientation.
   9268                         if (w.mOrientationChanging) {
   9269                             w.mOrientationChanging = false;
   9270                             if (DEBUG_ORIENTATION) Slog.v(TAG,
   9271                                     "Orientation change skips hidden " + w);
   9272                         }
   9273                     } else if (w.mLastLayer != w.mAnimLayer
   9274                             || w.mLastAlpha != w.mShownAlpha
   9275                             || w.mLastDsDx != w.mDsDx
   9276                             || w.mLastDtDx != w.mDtDx
   9277                             || w.mLastDsDy != w.mDsDy
   9278                             || w.mLastDtDy != w.mDtDy
   9279                             || w.mLastHScale != w.mHScale
   9280                             || w.mLastVScale != w.mVScale
   9281                             || w.mLastHidden) {
   9282                         displayed = true;
   9283                         w.mLastAlpha = w.mShownAlpha;
   9284                         w.mLastLayer = w.mAnimLayer;
   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                         if (SHOW_TRANSACTIONS) logSurface(w,
   9292                                 "alpha=" + w.mShownAlpha + " layer=" + w.mAnimLayer
   9293                                 + " matrix=[" + (w.mDsDx*w.mHScale)
   9294                                 + "," + (w.mDtDx*w.mVScale)
   9295                                 + "][" + (w.mDsDy*w.mHScale)
   9296                                 + "," + (w.mDtDy*w.mVScale) + "]", null);
   9297                         if (w.mSurface != null) {
   9298                             try {
   9299                                 w.mSurfaceAlpha = w.mShownAlpha;
   9300                                 w.mSurface.setAlpha(w.mShownAlpha);
   9301                                 w.mSurfaceLayer = w.mAnimLayer;
   9302                                 w.mSurface.setLayer(w.mAnimLayer);
   9303                                 w.mSurface.setMatrix(
   9304                                         w.mDsDx*w.mHScale, w.mDtDx*w.mVScale,
   9305                                         w.mDsDy*w.mHScale, w.mDtDy*w.mVScale);
   9306                             } catch (RuntimeException e) {
   9307                                 Slog.w(TAG, "Error updating surface in " + w, e);
   9308                                 if (!recoveringMemory) {
   9309                                     reclaimSomeSurfaceMemoryLocked(w, "update");
   9310                                 }
   9311                             }
   9312                         }
   9313 
   9314                         if (w.mLastHidden && !w.mDrawPending
   9315                                 && !w.mCommitDrawPending
   9316                                 && !w.mReadyToShow) {
   9317                             if (SHOW_TRANSACTIONS) logSurface(w,
   9318                                     "SHOW (performLayout)", null);
   9319                             if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w
   9320                                     + " during relayout");
   9321                             if (showSurfaceRobustlyLocked(w)) {
   9322                                 w.mHasDrawn = true;
   9323                                 w.mLastHidden = false;
   9324                             } else {
   9325                                 w.mOrientationChanging = false;
   9326                             }
   9327                         }
   9328                         if (w.mSurface != null) {
   9329                             w.mToken.hasVisible = true;
   9330                         }
   9331                     } else {
   9332                         displayed = true;
   9333                     }
   9334 
   9335                     if (displayed) {
   9336                         if (!covered) {
   9337                             if (attrs.width == LayoutParams.MATCH_PARENT
   9338                                     && attrs.height == LayoutParams.MATCH_PARENT) {
   9339                                 covered = true;
   9340                             }
   9341                         }
   9342                         if (w.mOrientationChanging) {
   9343                             if (w.mDrawPending || w.mCommitDrawPending) {
   9344                                 orientationChangeComplete = false;
   9345                                 if (DEBUG_ORIENTATION) Slog.v(TAG,
   9346                                         "Orientation continue waiting for draw in " + w);
   9347                             } else {
   9348                                 w.mOrientationChanging = false;
   9349                                 if (DEBUG_ORIENTATION) Slog.v(TAG,
   9350                                         "Orientation change complete in " + w);
   9351                             }
   9352                         }
   9353                         w.mToken.hasVisible = true;
   9354                     }
   9355                 } else if (w.mOrientationChanging) {
   9356                     if (DEBUG_ORIENTATION) Slog.v(TAG,
   9357                             "Orientation change skips hidden " + w);
   9358                     w.mOrientationChanging = false;
   9359                 }
   9360 
   9361                 final boolean canBeSeen = w.isDisplayedLw();
   9362 
   9363                 if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) {
   9364                     focusDisplayed = true;
   9365                 }
   9366 
   9367                 final boolean obscuredChanged = w.mObscured != obscured;
   9368 
   9369                 // Update effect.
   9370                 if (!(w.mObscured=obscured)) {
   9371                     if (w.mSurface != null) {
   9372                         if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
   9373                             holdScreen = w.mSession;
   9374                         }
   9375                         if (!syswin && w.mAttrs.screenBrightness >= 0
   9376                                 && screenBrightness < 0) {
   9377                             screenBrightness = w.mAttrs.screenBrightness;
   9378                         }
   9379                         if (!syswin && w.mAttrs.buttonBrightness >= 0
   9380                                 && buttonBrightness < 0) {
   9381                             buttonBrightness = w.mAttrs.buttonBrightness;
   9382                         }
   9383                         if (canBeSeen
   9384                                 && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
   9385                                  || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD
   9386                                  || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) {
   9387                             syswin = true;
   9388                         }
   9389                     }
   9390 
   9391                     boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
   9392                     if (opaqueDrawn && w.isFullscreen(dw, dh)) {
   9393                         // This window completely covers everything behind it,
   9394                         // so we want to leave all of them as unblurred (for
   9395                         // performance reasons).
   9396                         obscured = true;
   9397                     } else if (opaqueDrawn && w.needsBackgroundFiller(dw, dh)) {
   9398                         if (SHOW_TRANSACTIONS) Slog.d(TAG, "showing background filler");
   9399                         // This window is in compatibility mode, and needs background filler.
   9400                         obscured = true;
   9401                         if (mBackgroundFillerSurface == null) {
   9402                             try {
   9403                                 mBackgroundFillerSurface = new Surface(mFxSession, 0,
   9404                                         "BackGroundFiller",
   9405                                         0, dw, dh,
   9406                                         PixelFormat.OPAQUE,
   9407                                         Surface.FX_SURFACE_NORMAL);
   9408                             } catch (Exception e) {
   9409                                 Slog.e(TAG, "Exception creating filler surface", e);
   9410                             }
   9411                         }
   9412                         try {
   9413                             mBackgroundFillerSurface.setPosition(0, 0);
   9414                             mBackgroundFillerSurface.setSize(dw, dh);
   9415                             // Using the same layer as Dim because they will never be shown at the
   9416                             // same time.
   9417                             mBackgroundFillerSurface.setLayer(w.mAnimLayer - 1);
   9418                             mBackgroundFillerSurface.show();
   9419                         } catch (RuntimeException e) {
   9420                             Slog.e(TAG, "Exception showing filler surface");
   9421                         }
   9422                         backgroundFillerShown = true;
   9423                         mBackgroundFillerShown = true;
   9424                     } else if (canBeSeen && !obscured &&
   9425                             (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
   9426                         if (localLOGV) Slog.v(TAG, "Win " + w
   9427                                 + ": blurring=" + blurring
   9428                                 + " obscured=" + obscured
   9429                                 + " displayed=" + displayed);
   9430                         if ((attrFlags&FLAG_DIM_BEHIND) != 0) {
   9431                             if (!dimming) {
   9432                                 //Slog.i(TAG, "DIM BEHIND: " + w);
   9433                                 dimming = true;
   9434                                 if (mDimAnimator == null) {
   9435                                     mDimAnimator = new DimAnimator(mFxSession);
   9436                                 }
   9437                                 mDimAnimator.show(dw, dh);
   9438                                 mDimAnimator.updateParameters(w, currentTime);
   9439                             }
   9440                         }
   9441                         if ((attrFlags&FLAG_BLUR_BEHIND) != 0) {
   9442                             if (!blurring) {
   9443                                 //Slog.i(TAG, "BLUR BEHIND: " + w);
   9444                                 blurring = true;
   9445                                 if (mBlurSurface == null) {
   9446                                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  BLUR "
   9447                                             + mBlurSurface + ": CREATE");
   9448                                     try {
   9449                                         mBlurSurface = new Surface(mFxSession, 0,
   9450                                                 "BlurSurface",
   9451                                                 -1, 16, 16,
   9452                                                 PixelFormat.OPAQUE,
   9453                                                 Surface.FX_SURFACE_BLUR);
   9454                                     } catch (Exception e) {
   9455                                         Slog.e(TAG, "Exception creating Blur surface", e);
   9456                                     }
   9457                                 }
   9458                                 if (mBlurSurface != null) {
   9459                                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  BLUR "
   9460                                             + mBlurSurface + ": pos=(0,0) (" +
   9461                                             dw + "x" + dh + "), layer=" + (w.mAnimLayer-1));
   9462                                     mBlurSurface.setPosition(0, 0);
   9463                                     mBlurSurface.setSize(dw, dh);
   9464                                     mBlurSurface.setLayer(w.mAnimLayer-2);
   9465                                     if (!mBlurShown) {
   9466                                         try {
   9467                                             if (SHOW_TRANSACTIONS) Slog.i(TAG, "  BLUR "
   9468                                                     + mBlurSurface + ": SHOW");
   9469                                             mBlurSurface.show();
   9470                                         } catch (RuntimeException e) {
   9471                                             Slog.w(TAG, "Failure showing blur surface", e);
   9472                                         }
   9473                                         mBlurShown = true;
   9474                                     }
   9475                                 }
   9476                             }
   9477                         }
   9478                     }
   9479                 }
   9480 
   9481                 if (obscuredChanged && mWallpaperTarget == w) {
   9482                     // This is the wallpaper target and its obscured state
   9483                     // changed... make sure the current wallaper's visibility
   9484                     // has been updated accordingly.
   9485                     updateWallpaperVisibilityLocked();
   9486                 }
   9487             }
   9488 
   9489             if (backgroundFillerShown == false && mBackgroundFillerShown) {
   9490                 mBackgroundFillerShown = false;
   9491                 if (SHOW_TRANSACTIONS) Slog.d(TAG, "hiding background filler");
   9492                 try {
   9493                     mBackgroundFillerSurface.hide();
   9494                 } catch (RuntimeException e) {
   9495                     Slog.e(TAG, "Exception hiding filler surface", e);
   9496                 }
   9497             }
   9498 
   9499             if (mDimAnimator != null && mDimAnimator.mDimShown) {
   9500                 animating |= mDimAnimator.updateSurface(dimming, currentTime,
   9501                         mDisplayFrozen || !mPolicy.isScreenOn());
   9502             }
   9503 
   9504             if (!blurring && mBlurShown) {
   9505                 if (SHOW_TRANSACTIONS) Slog.i(TAG, "  BLUR " + mBlurSurface
   9506                         + ": HIDE");
   9507                 try {
   9508                     mBlurSurface.hide();
   9509                 } catch (IllegalArgumentException e) {
   9510                     Slog.w(TAG, "Illegal argument exception hiding blur surface");
   9511                 }
   9512                 mBlurShown = false;
   9513             }
   9514 
   9515             if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
   9516         } catch (RuntimeException e) {
   9517             Slog.e(TAG, "Unhandled exception in Window Manager", e);
   9518         }
   9519 
   9520         mInputMonitor.updateInputWindowsLw();
   9521 
   9522         Surface.closeTransaction();
   9523 
   9524         if (mWatermark != null) {
   9525             mWatermark.drawIfNeeded();
   9526         }
   9527 
   9528         if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
   9529                 "With display frozen, orientationChangeComplete="
   9530                 + orientationChangeComplete);
   9531         if (orientationChangeComplete) {
   9532             if (mWindowsFreezingScreen) {
   9533                 mWindowsFreezingScreen = false;
   9534                 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
   9535             }
   9536             stopFreezingDisplayLocked();
   9537         }
   9538 
   9539         i = mResizingWindows.size();
   9540         if (i > 0) {
   9541             do {
   9542                 i--;
   9543                 WindowState win = mResizingWindows.get(i);
   9544                 try {
   9545                     if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
   9546                             "Reporting new frame to " + win + ": " + win.mFrame);
   9547                     int diff = 0;
   9548                     boolean configChanged =
   9549                         win.mConfiguration != mCurConfiguration
   9550                         && (win.mConfiguration == null
   9551                                 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0);
   9552                     if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
   9553                             && configChanged) {
   9554                         Slog.i(TAG, "Sending new config to window " + win + ": "
   9555                                 + win.mFrame.width() + "x" + win.mFrame.height()
   9556                                 + " / " + mCurConfiguration + " / 0x"
   9557                                 + Integer.toHexString(diff));
   9558                     }
   9559                     win.mConfiguration = mCurConfiguration;
   9560                     win.mClient.resized(win.mFrame.width(),
   9561                             win.mFrame.height(), win.mLastContentInsets,
   9562                             win.mLastVisibleInsets, win.mDrawPending,
   9563                             configChanged ? win.mConfiguration : null);
   9564                     win.mContentInsetsChanged = false;
   9565                     win.mVisibleInsetsChanged = false;
   9566                     win.mSurfaceResized = false;
   9567                 } catch (RemoteException e) {
   9568                     win.mOrientationChanging = false;
   9569                 }
   9570             } while (i > 0);
   9571             mResizingWindows.clear();
   9572         }
   9573 
   9574         // Destroy the surface of any windows that are no longer visible.
   9575         boolean wallpaperDestroyed = false;
   9576         i = mDestroySurface.size();
   9577         if (i > 0) {
   9578             do {
   9579                 i--;
   9580                 WindowState win = mDestroySurface.get(i);
   9581                 win.mDestroying = false;
   9582                 if (mInputMethodWindow == win) {
   9583                     mInputMethodWindow = null;
   9584                 }
   9585                 if (win == mWallpaperTarget) {
   9586                     wallpaperDestroyed = true;
   9587                 }
   9588                 win.destroySurfaceLocked();
   9589             } while (i > 0);
   9590             mDestroySurface.clear();
   9591         }
   9592 
   9593         // Time to remove any exiting tokens?
   9594         for (i=mExitingTokens.size()-1; i>=0; i--) {
   9595             WindowToken token = mExitingTokens.get(i);
   9596             if (!token.hasVisible) {
   9597                 mExitingTokens.remove(i);
   9598                 if (token.windowType == TYPE_WALLPAPER) {
   9599                     mWallpaperTokens.remove(token);
   9600                 }
   9601             }
   9602         }
   9603 
   9604         // Time to remove any exiting applications?
   9605         for (i=mExitingAppTokens.size()-1; i>=0; i--) {
   9606             AppWindowToken token = mExitingAppTokens.get(i);
   9607             if (!token.hasVisible && !mClosingApps.contains(token)) {
   9608                 // Make sure there is no animation running on this token,
   9609                 // so any windows associated with it will be removed as
   9610                 // soon as their animations are complete
   9611                 token.animation = null;
   9612                 token.animating = false;
   9613                 mAppTokens.remove(token);
   9614                 mExitingAppTokens.remove(i);
   9615                 if (mLastEnterAnimToken == token) {
   9616                     mLastEnterAnimToken = null;
   9617                     mLastEnterAnimParams = null;
   9618                 }
   9619             }
   9620         }
   9621 
   9622         boolean needRelayout = false;
   9623 
   9624         if (!animating && mAppTransitionRunning) {
   9625             // We have finished the animation of an app transition.  To do
   9626             // this, we have delayed a lot of operations like showing and
   9627             // hiding apps, moving apps in Z-order, etc.  The app token list
   9628             // reflects the correct Z-order, but the window list may now
   9629             // be out of sync with it.  So here we will just rebuild the
   9630             // entire app window list.  Fun!
   9631             mAppTransitionRunning = false;
   9632             needRelayout = true;
   9633             rebuildAppWindowListLocked();
   9634             assignLayersLocked();
   9635             // Clear information about apps that were moving.
   9636             mToBottomApps.clear();
   9637         }
   9638 
   9639         if (focusDisplayed) {
   9640             mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
   9641         }
   9642         if (wallpaperDestroyed) {
   9643             needRelayout = adjustWallpaperWindowsLocked() != 0;
   9644         }
   9645         if (needRelayout) {
   9646             requestAnimationLocked(0);
   9647         } else if (animating) {
   9648             requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis());
   9649         }
   9650 
   9651         mInputMonitor.updateInputWindowsLw();
   9652 
   9653         if (DEBUG_FREEZE) Slog.v(TAG, "Layout: mDisplayFrozen=" + mDisplayFrozen
   9654                 + " holdScreen=" + holdScreen);
   9655         if (!mDisplayFrozen) {
   9656             setHoldScreenLocked(holdScreen != null);
   9657             if (screenBrightness < 0 || screenBrightness > 1.0f) {
   9658                 mPowerManager.setScreenBrightnessOverride(-1);
   9659             } else {
   9660                 mPowerManager.setScreenBrightnessOverride((int)
   9661                         (screenBrightness * Power.BRIGHTNESS_ON));
   9662             }
   9663             if (buttonBrightness < 0 || buttonBrightness > 1.0f) {
   9664                 mPowerManager.setButtonBrightnessOverride(-1);
   9665             } else {
   9666                 mPowerManager.setButtonBrightnessOverride((int)
   9667                         (buttonBrightness * Power.BRIGHTNESS_ON));
   9668             }
   9669             if (holdScreen != mHoldingScreenOn) {
   9670                 mHoldingScreenOn = holdScreen;
   9671                 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen);
   9672                 mH.sendMessage(m);
   9673             }
   9674         }
   9675 
   9676         if (mTurnOnScreen) {
   9677             if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
   9678             mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
   9679                     LocalPowerManager.BUTTON_EVENT, true);
   9680             mTurnOnScreen = false;
   9681         }
   9682 
   9683         // Check to see if we are now in a state where the screen should
   9684         // be enabled, because the window obscured flags have changed.
   9685         enableScreenIfNeededLocked();
   9686     }
   9687 
   9688     /**
   9689      * Must be called with the main window manager lock held.
   9690      */
   9691     void setHoldScreenLocked(boolean holding) {
   9692         boolean state = mHoldingScreenWakeLock.isHeld();
   9693         if (holding != state) {
   9694             if (holding) {
   9695                 mHoldingScreenWakeLock.acquire();
   9696             } else {
   9697                 mPolicy.screenOnStoppedLw();
   9698                 mHoldingScreenWakeLock.release();
   9699             }
   9700         }
   9701     }
   9702 
   9703     void requestAnimationLocked(long delay) {
   9704         if (!mAnimationPending) {
   9705             mAnimationPending = true;
   9706             mH.sendMessageDelayed(mH.obtainMessage(H.ANIMATE), delay);
   9707         }
   9708     }
   9709 
   9710     /**
   9711      * Have the surface flinger show a surface, robustly dealing with
   9712      * error conditions.  In particular, if there is not enough memory
   9713      * to show the surface, then we will try to get rid of other surfaces
   9714      * in order to succeed.
   9715      *
   9716      * @return Returns true if the surface was successfully shown.
   9717      */
   9718     boolean showSurfaceRobustlyLocked(WindowState win) {
   9719         try {
   9720             if (win.mSurface != null) {
   9721                 win.mSurfaceShown = true;
   9722                 win.mSurface.show();
   9723                 if (win.mTurnOnScreen) {
   9724                     if (DEBUG_VISIBILITY) Slog.v(TAG,
   9725                             "Show surface turning screen on: " + win);
   9726                     win.mTurnOnScreen = false;
   9727                     mTurnOnScreen = true;
   9728                 }
   9729             }
   9730             return true;
   9731         } catch (RuntimeException e) {
   9732             Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win);
   9733         }
   9734 
   9735         reclaimSomeSurfaceMemoryLocked(win, "show");
   9736 
   9737         return false;
   9738     }
   9739 
   9740     void reclaimSomeSurfaceMemoryLocked(WindowState win, String operation) {
   9741         final Surface surface = win.mSurface;
   9742 
   9743         EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, win.toString(),
   9744                 win.mSession.mPid, operation);
   9745 
   9746         if (mForceRemoves == null) {
   9747             mForceRemoves = new ArrayList<WindowState>();
   9748         }
   9749 
   9750         long callingIdentity = Binder.clearCallingIdentity();
   9751         try {
   9752             // There was some problem...   first, do a sanity check of the
   9753             // window list to make sure we haven't left any dangling surfaces
   9754             // around.
   9755             int N = mWindows.size();
   9756             boolean leakedSurface = false;
   9757             Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
   9758             for (int i=0; i<N; i++) {
   9759                 WindowState ws = mWindows.get(i);
   9760                 if (ws.mSurface != null) {
   9761                     if (!mSessions.contains(ws.mSession)) {
   9762                         Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
   9763                                 + ws + " surface=" + ws.mSurface
   9764                                 + " token=" + win.mToken
   9765                                 + " pid=" + ws.mSession.mPid
   9766                                 + " uid=" + ws.mSession.mUid);
   9767                         ws.mSurface.destroy();
   9768                         ws.mSurfaceShown = false;
   9769                         ws.mSurface = null;
   9770                         mForceRemoves.add(ws);
   9771                         i--;
   9772                         N--;
   9773                         leakedSurface = true;
   9774                     } else if (win.mAppToken != null && win.mAppToken.clientHidden) {
   9775                         Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
   9776                                 + ws + " surface=" + ws.mSurface
   9777                                 + " token=" + win.mAppToken);
   9778                         ws.mSurface.destroy();
   9779                         ws.mSurfaceShown = false;
   9780                         ws.mSurface = null;
   9781                         leakedSurface = true;
   9782                     }
   9783                 }
   9784             }
   9785 
   9786             boolean killedApps = false;
   9787             if (!leakedSurface) {
   9788                 Slog.w(TAG, "No leaked surfaces; killing applicatons!");
   9789                 SparseIntArray pidCandidates = new SparseIntArray();
   9790                 for (int i=0; i<N; i++) {
   9791                     WindowState ws = mWindows.get(i);
   9792                     if (ws.mSurface != null) {
   9793                         pidCandidates.append(ws.mSession.mPid, ws.mSession.mPid);
   9794                     }
   9795                 }
   9796                 if (pidCandidates.size() > 0) {
   9797                     int[] pids = new int[pidCandidates.size()];
   9798                     for (int i=0; i<pids.length; i++) {
   9799                         pids[i] = pidCandidates.keyAt(i);
   9800                     }
   9801                     try {
   9802                         if (mActivityManager.killPids(pids, "Free memory")) {
   9803                             killedApps = true;
   9804                         }
   9805                     } catch (RemoteException e) {
   9806                     }
   9807                 }
   9808             }
   9809 
   9810             if (leakedSurface || killedApps) {
   9811                 // We managed to reclaim some memory, so get rid of the trouble
   9812                 // surface and ask the app to request another one.
   9813                 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
   9814                 if (surface != null) {
   9815                     surface.destroy();
   9816                     win.mSurfaceShown = false;
   9817                     win.mSurface = null;
   9818                 }
   9819 
   9820                 try {
   9821                     win.mClient.dispatchGetNewSurface();
   9822                 } catch (RemoteException e) {
   9823                 }
   9824             }
   9825         } finally {
   9826             Binder.restoreCallingIdentity(callingIdentity);
   9827         }
   9828     }
   9829 
   9830     private boolean updateFocusedWindowLocked(int mode) {
   9831         WindowState newFocus = computeFocusedWindowLocked();
   9832         if (mCurrentFocus != newFocus) {
   9833             // This check makes sure that we don't already have the focus
   9834             // change message pending.
   9835             mH.removeMessages(H.REPORT_FOCUS_CHANGE);
   9836             mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
   9837             if (localLOGV) Slog.v(
   9838                 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
   9839             final WindowState oldFocus = mCurrentFocus;
   9840             mCurrentFocus = newFocus;
   9841             mLosingFocus.remove(newFocus);
   9842 
   9843             final WindowState imWindow = mInputMethodWindow;
   9844             if (newFocus != imWindow && oldFocus != imWindow) {
   9845                 if (moveInputMethodWindowsIfNeededLocked(
   9846                         mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS &&
   9847                         mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
   9848                     mLayoutNeeded = true;
   9849                 }
   9850                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
   9851                     performLayoutLockedInner();
   9852                 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
   9853                     // Client will do the layout, but we need to assign layers
   9854                     // for handleNewWindowLocked() below.
   9855                     assignLayersLocked();
   9856                 }
   9857             }
   9858 
   9859             if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
   9860                 // If we defer assigning layers, then the caller is responsible for
   9861                 // doing this part.
   9862                 finishUpdateFocusedWindowAfterAssignLayersLocked();
   9863             }
   9864             return true;
   9865         }
   9866         return false;
   9867     }
   9868 
   9869     private void finishUpdateFocusedWindowAfterAssignLayersLocked() {
   9870         mInputMonitor.setInputFocusLw(mCurrentFocus);
   9871     }
   9872 
   9873     private WindowState computeFocusedWindowLocked() {
   9874         WindowState result = null;
   9875         WindowState win;
   9876 
   9877         int i = mWindows.size() - 1;
   9878         int nextAppIndex = mAppTokens.size()-1;
   9879         WindowToken nextApp = nextAppIndex >= 0
   9880             ? mAppTokens.get(nextAppIndex) : null;
   9881 
   9882         while (i >= 0) {
   9883             win = mWindows.get(i);
   9884 
   9885             if (localLOGV || DEBUG_FOCUS) Slog.v(
   9886                 TAG, "Looking for focus: " + i
   9887                 + " = " + win
   9888                 + ", flags=" + win.mAttrs.flags
   9889                 + ", canReceive=" + win.canReceiveKeys());
   9890 
   9891             AppWindowToken thisApp = win.mAppToken;
   9892 
   9893             // If this window's application has been removed, just skip it.
   9894             if (thisApp != null && thisApp.removed) {
   9895                 i--;
   9896                 continue;
   9897             }
   9898 
   9899             // If there is a focused app, don't allow focus to go to any
   9900             // windows below it.  If this is an application window, step
   9901             // through the app tokens until we find its app.
   9902             if (thisApp != null && nextApp != null && thisApp != nextApp
   9903                     && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
   9904                 int origAppIndex = nextAppIndex;
   9905                 while (nextAppIndex > 0) {
   9906                     if (nextApp == mFocusedApp) {
   9907                         // Whoops, we are below the focused app...  no focus
   9908                         // for you!
   9909                         if (localLOGV || DEBUG_FOCUS) Slog.v(
   9910                             TAG, "Reached focused app: " + mFocusedApp);
   9911                         return null;
   9912                     }
   9913                     nextAppIndex--;
   9914                     nextApp = mAppTokens.get(nextAppIndex);
   9915                     if (nextApp == thisApp) {
   9916                         break;
   9917                     }
   9918                 }
   9919                 if (thisApp != nextApp) {
   9920                     // Uh oh, the app token doesn't exist!  This shouldn't
   9921                     // happen, but if it does we can get totally hosed...
   9922                     // so restart at the original app.
   9923                     nextAppIndex = origAppIndex;
   9924                     nextApp = mAppTokens.get(nextAppIndex);
   9925                 }
   9926             }
   9927 
   9928             // Dispatch to this window if it is wants key events.
   9929             if (win.canReceiveKeys()) {
   9930                 if (DEBUG_FOCUS) Slog.v(
   9931                         TAG, "Found focus @ " + i + " = " + win);
   9932                 result = win;
   9933                 break;
   9934             }
   9935 
   9936             i--;
   9937         }
   9938 
   9939         return result;
   9940     }
   9941 
   9942     private void startFreezingDisplayLocked() {
   9943         if (mDisplayFrozen) {
   9944             return;
   9945         }
   9946 
   9947         mScreenFrozenLock.acquire();
   9948 
   9949         long now = SystemClock.uptimeMillis();
   9950         //Slog.i(TAG, "Freezing, gc pending: " + mFreezeGcPending + ", now " + now);
   9951         if (mFreezeGcPending != 0) {
   9952             if (now > (mFreezeGcPending+1000)) {
   9953                 //Slog.i(TAG, "Gc!  " + now + " > " + (mFreezeGcPending+1000));
   9954                 mH.removeMessages(H.FORCE_GC);
   9955                 Runtime.getRuntime().gc();
   9956                 mFreezeGcPending = now;
   9957             }
   9958         } else {
   9959             mFreezeGcPending = now;
   9960         }
   9961 
   9962         if (DEBUG_FREEZE) Slog.v(TAG, "*** FREEZING DISPLAY", new RuntimeException());
   9963 
   9964         mDisplayFrozen = true;
   9965 
   9966         mInputMonitor.freezeInputDispatchingLw();
   9967 
   9968         if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
   9969             mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
   9970             mNextAppTransitionPackage = null;
   9971             mAppTransitionReady = true;
   9972         }
   9973 
   9974         if (PROFILE_ORIENTATION) {
   9975             File file = new File("/data/system/frozen");
   9976             Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
   9977         }
   9978         Surface.freezeDisplay(0);
   9979     }
   9980 
   9981     private void stopFreezingDisplayLocked() {
   9982         if (!mDisplayFrozen) {
   9983             return;
   9984         }
   9985 
   9986         if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) {
   9987             return;
   9988         }
   9989 
   9990         if (DEBUG_FREEZE) Slog.v(TAG, "*** UNFREEZING DISPLAY", new RuntimeException());
   9991 
   9992         mDisplayFrozen = false;
   9993         mH.removeMessages(H.APP_FREEZE_TIMEOUT);
   9994         if (PROFILE_ORIENTATION) {
   9995             Debug.stopMethodTracing();
   9996         }
   9997         Surface.unfreezeDisplay(0);
   9998 
   9999         mInputMonitor.thawInputDispatchingLw();
   10000 
   10001         // While the display is frozen we don't re-compute the orientation
   10002         // to avoid inconsistent states.  However, something interesting
   10003         // could have actually changed during that time so re-evaluate it
   10004         // now to catch that.
   10005         if (updateOrientationFromAppTokensLocked()) {
   10006             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
   10007         }
   10008 
   10009         // A little kludge: a lot could have happened while the
   10010         // display was frozen, so now that we are coming back we
   10011         // do a gc so that any remote references the system
   10012         // processes holds on others can be released if they are
   10013         // no longer needed.
   10014         mH.removeMessages(H.FORCE_GC);
   10015         mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
   10016                 2000);
   10017 
   10018         mScreenFrozenLock.release();
   10019     }
   10020 
   10021     static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
   10022             DisplayMetrics dm) {
   10023         if (index < tokens.length) {
   10024             String str = tokens[index];
   10025             if (str != null && str.length() > 0) {
   10026                 try {
   10027                     int val = Integer.parseInt(str);
   10028                     return val;
   10029                 } catch (Exception e) {
   10030                 }
   10031             }
   10032         }
   10033         if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
   10034             return defDps;
   10035         }
   10036         int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
   10037         return val;
   10038     }
   10039 
   10040     class Watermark {
   10041         final String[] mTokens;
   10042         final String mText;
   10043         final Paint mTextPaint;
   10044         final int mTextWidth;
   10045         final int mTextHeight;
   10046         final int mTextAscent;
   10047         final int mTextDescent;
   10048         final int mDeltaX;
   10049         final int mDeltaY;
   10050 
   10051         Surface mSurface;
   10052         int mLastDW;
   10053         int mLastDH;
   10054         boolean mDrawNeeded;
   10055 
   10056         Watermark(SurfaceSession session, String[] tokens) {
   10057             final DisplayMetrics dm = new DisplayMetrics();
   10058             mDisplay.getMetrics(dm);
   10059 
   10060             if (false) {
   10061                 Log.i(TAG, "*********************** WATERMARK");
   10062                 for (int i=0; i<tokens.length; i++) {
   10063                     Log.i(TAG, "  TOKEN #" + i + ": " + tokens[i]);
   10064                 }
   10065             }
   10066 
   10067             mTokens = tokens;
   10068 
   10069             StringBuilder builder = new StringBuilder(32);
   10070             int len = mTokens[0].length();
   10071             len = len & ~1;
   10072             for (int i=0; i<len; i+=2) {
   10073                 int c1 = mTokens[0].charAt(i);
   10074                 int c2 = mTokens[0].charAt(i+1);
   10075                 if (c1 >= 'a' && c1 <= 'f') c1 = c1 - 'a' + 10;
   10076                 else if (c1 >= 'A' && c1 <= 'F') c1 = c1 - 'A' + 10;
   10077                 else c1 -= '0';
   10078                 if (c2 >= 'a' && c2 <= 'f') c2 = c2 - 'a' + 10;
   10079                 else if (c2 >= 'A' && c2 <= 'F') c2 = c2 - 'A' + 10;
   10080                 else c2 -= '0';
   10081                 builder.append((char)(255-((c1*16)+c2)));
   10082             }
   10083             mText = builder.toString();
   10084             if (false) {
   10085                 Log.i(TAG, "Final text: " + mText);
   10086             }
   10087 
   10088             int fontSize = getPropertyInt(tokens, 1,
   10089                     TypedValue.COMPLEX_UNIT_DIP, 20, dm);
   10090 
   10091             mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
   10092             mTextPaint.setTextSize(fontSize);
   10093             mTextPaint.setTypeface(Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD));
   10094 
   10095             FontMetricsInt fm = mTextPaint.getFontMetricsInt();
   10096             mTextWidth = (int)mTextPaint.measureText(mText);
   10097             mTextAscent = fm.ascent;
   10098             mTextDescent = fm.descent;
   10099             mTextHeight = fm.descent - fm.ascent;
   10100 
   10101             mDeltaX = getPropertyInt(tokens, 2,
   10102                     TypedValue.COMPLEX_UNIT_PX, mTextWidth*2, dm);
   10103             mDeltaY = getPropertyInt(tokens, 3,
   10104                     TypedValue.COMPLEX_UNIT_PX, mTextHeight*3, dm);
   10105             int shadowColor = getPropertyInt(tokens, 4,
   10106                     TypedValue.COMPLEX_UNIT_PX, 0xb0000000, dm);
   10107             int color = getPropertyInt(tokens, 5,
   10108                     TypedValue.COMPLEX_UNIT_PX, 0x60ffffff, dm);
   10109             int shadowRadius = getPropertyInt(tokens, 6,
   10110                     TypedValue.COMPLEX_UNIT_PX, 7, dm);
   10111             int shadowDx = getPropertyInt(tokens, 8,
   10112                     TypedValue.COMPLEX_UNIT_PX, 0, dm);
   10113             int shadowDy = getPropertyInt(tokens, 9,
   10114                     TypedValue.COMPLEX_UNIT_PX, 0, dm);
   10115 
   10116             mTextPaint.setColor(color);
   10117             mTextPaint.setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor);
   10118 
   10119             try {
   10120                 mSurface = new Surface(session, 0,
   10121                         "WatermarkSurface", -1, 1, 1, PixelFormat.TRANSLUCENT, 0);
   10122                 mSurface.setLayer(TYPE_LAYER_MULTIPLIER*100);
   10123                 mSurface.setPosition(0, 0);
   10124                 mSurface.show();
   10125             } catch (OutOfResourcesException e) {
   10126             }
   10127         }
   10128 
   10129         void positionSurface(int dw, int dh) {
   10130             if (mLastDW != dw || mLastDH != dh) {
   10131                 mLastDW = dw;
   10132                 mLastDH = dh;
   10133                 mSurface.setSize(dw, dh);
   10134                 mDrawNeeded = true;
   10135             }
   10136         }
   10137 
   10138         void drawIfNeeded() {
   10139             if (mDrawNeeded) {
   10140                 final int dw = mLastDW;
   10141                 final int dh = mLastDH;
   10142 
   10143                 mDrawNeeded = false;
   10144                 Rect dirty = new Rect(0, 0, dw, dh);
   10145                 Canvas c = null;
   10146                 try {
   10147                     c = mSurface.lockCanvas(dirty);
   10148                 } catch (IllegalArgumentException e) {
   10149                 } catch (OutOfResourcesException e) {
   10150                 }
   10151                 if (c != null) {
   10152                     int deltaX = mDeltaX;
   10153                     int deltaY = mDeltaY;
   10154 
   10155                     // deltaX shouldn't be close to a round fraction of our
   10156                     // x step, or else things will line up too much.
   10157                     int div = (dw+mTextWidth)/deltaX;
   10158                     int rem = (dw+mTextWidth) - (div*deltaX);
   10159                     int qdelta = deltaX/4;
   10160                     if (rem < qdelta || rem > (deltaX-qdelta)) {
   10161                         deltaX += deltaX/3;
   10162                     }
   10163 
   10164                     int y = -mTextHeight;
   10165                     int x = -mTextWidth;
   10166                     while (y < (dh+mTextHeight)) {
   10167                         c.drawText(mText, x, y, mTextPaint);
   10168                         x += deltaX;
   10169                         if (x >= dw) {
   10170                             x -= (dw+mTextWidth);
   10171                             y += deltaY;
   10172                         }
   10173                     }
   10174                     mSurface.unlockCanvasAndPost(c);
   10175                 }
   10176             }
   10177         }
   10178     }
   10179 
   10180     void createWatermark() {
   10181         if (mWatermark != null) {
   10182             return;
   10183         }
   10184 
   10185         File file = new File("/system/etc/setup.conf");
   10186         FileInputStream in = null;
   10187         try {
   10188             in = new FileInputStream(file);
   10189             DataInputStream ind = new DataInputStream(in);
   10190             String line = ind.readLine();
   10191             if (line != null) {
   10192                 String[] toks = line.split("%");
   10193                 if (toks != null && toks.length > 0) {
   10194                     mWatermark = new Watermark(mFxSession, toks);
   10195                 }
   10196             }
   10197         } catch (FileNotFoundException e) {
   10198         } catch (IOException e) {
   10199         } finally {
   10200             if (in != null) {
   10201                 try {
   10202                     in.close();
   10203                 } catch (IOException e) {
   10204                 }
   10205             }
   10206         }
   10207     }
   10208 
   10209     @Override
   10210     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   10211         if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
   10212                 != PackageManager.PERMISSION_GRANTED) {
   10213             pw.println("Permission Denial: can't dump WindowManager from from pid="
   10214                     + Binder.getCallingPid()
   10215                     + ", uid=" + Binder.getCallingUid());
   10216             return;
   10217         }
   10218 
   10219         mInputManager.dump(pw);
   10220         pw.println(" ");
   10221 
   10222         synchronized(mWindowMap) {
   10223             pw.println("Current Window Manager state:");
   10224             for (int i=mWindows.size()-1; i>=0; i--) {
   10225                 WindowState w = mWindows.get(i);
   10226                 pw.print("  Window #"); pw.print(i); pw.print(' ');
   10227                         pw.print(w); pw.println(":");
   10228                 w.dump(pw, "    ");
   10229             }
   10230             if (mInputMethodDialogs.size() > 0) {
   10231                 pw.println(" ");
   10232                 pw.println("  Input method dialogs:");
   10233                 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
   10234                     WindowState w = mInputMethodDialogs.get(i);
   10235                     pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
   10236                 }
   10237             }
   10238             if (mPendingRemove.size() > 0) {
   10239                 pw.println(" ");
   10240                 pw.println("  Remove pending for:");
   10241                 for (int i=mPendingRemove.size()-1; i>=0; i--) {
   10242                     WindowState w = mPendingRemove.get(i);
   10243                     pw.print("  Remove #"); pw.print(i); pw.print(' ');
   10244                             pw.print(w); pw.println(":");
   10245                     w.dump(pw, "    ");
   10246                 }
   10247             }
   10248             if (mForceRemoves != null && mForceRemoves.size() > 0) {
   10249                 pw.println(" ");
   10250                 pw.println("  Windows force removing:");
   10251                 for (int i=mForceRemoves.size()-1; i>=0; i--) {
   10252                     WindowState w = mForceRemoves.get(i);
   10253                     pw.print("  Removing #"); pw.print(i); pw.print(' ');
   10254                             pw.print(w); pw.println(":");
   10255                     w.dump(pw, "    ");
   10256                 }
   10257             }
   10258             if (mDestroySurface.size() > 0) {
   10259                 pw.println(" ");
   10260                 pw.println("  Windows waiting to destroy their surface:");
   10261                 for (int i=mDestroySurface.size()-1; i>=0; i--) {
   10262                     WindowState w = mDestroySurface.get(i);
   10263                     pw.print("  Destroy #"); pw.print(i); pw.print(' ');
   10264                             pw.print(w); pw.println(":");
   10265                     w.dump(pw, "    ");
   10266                 }
   10267             }
   10268             if (mLosingFocus.size() > 0) {
   10269                 pw.println(" ");
   10270                 pw.println("  Windows losing focus:");
   10271                 for (int i=mLosingFocus.size()-1; i>=0; i--) {
   10272                     WindowState w = mLosingFocus.get(i);
   10273                     pw.print("  Losing #"); pw.print(i); pw.print(' ');
   10274                             pw.print(w); pw.println(":");
   10275                     w.dump(pw, "    ");
   10276                 }
   10277             }
   10278             if (mResizingWindows.size() > 0) {
   10279                 pw.println(" ");
   10280                 pw.println("  Windows waiting to resize:");
   10281                 for (int i=mResizingWindows.size()-1; i>=0; i--) {
   10282                     WindowState w = mResizingWindows.get(i);
   10283                     pw.print("  Resizing #"); pw.print(i); pw.print(' ');
   10284                             pw.print(w); pw.println(":");
   10285                     w.dump(pw, "    ");
   10286                 }
   10287             }
   10288             if (mSessions.size() > 0) {
   10289                 pw.println(" ");
   10290                 pw.println("  All active sessions:");
   10291                 Iterator<Session> it = mSessions.iterator();
   10292                 while (it.hasNext()) {
   10293                     Session s = it.next();
   10294                     pw.print("  Session "); pw.print(s); pw.println(':');
   10295                     s.dump(pw, "    ");
   10296                 }
   10297             }
   10298             if (mTokenMap.size() > 0) {
   10299                 pw.println(" ");
   10300                 pw.println("  All tokens:");
   10301                 Iterator<WindowToken> it = mTokenMap.values().iterator();
   10302                 while (it.hasNext()) {
   10303                     WindowToken token = it.next();
   10304                     pw.print("  Token "); pw.print(token.token); pw.println(':');
   10305                     token.dump(pw, "    ");
   10306                 }
   10307             }
   10308             if (mTokenList.size() > 0) {
   10309                 pw.println(" ");
   10310                 pw.println("  Window token list:");
   10311                 for (int i=0; i<mTokenList.size(); i++) {
   10312                     pw.print("  #"); pw.print(i); pw.print(": ");
   10313                             pw.println(mTokenList.get(i));
   10314                 }
   10315             }
   10316             if (mWallpaperTokens.size() > 0) {
   10317                 pw.println(" ");
   10318                 pw.println("  Wallpaper tokens:");
   10319                 for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
   10320                     WindowToken token = mWallpaperTokens.get(i);
   10321                     pw.print("  Wallpaper #"); pw.print(i);
   10322                             pw.print(' '); pw.print(token); pw.println(':');
   10323                     token.dump(pw, "    ");
   10324                 }
   10325             }
   10326             if (mAppTokens.size() > 0) {
   10327                 pw.println(" ");
   10328                 pw.println("  Application tokens in Z order:");
   10329                 for (int i=mAppTokens.size()-1; i>=0; i--) {
   10330                     pw.print("  App #"); pw.print(i); pw.print(": ");
   10331                             pw.println(mAppTokens.get(i));
   10332                 }
   10333             }
   10334             if (mFinishedStarting.size() > 0) {
   10335                 pw.println(" ");
   10336                 pw.println("  Finishing start of application tokens:");
   10337                 for (int i=mFinishedStarting.size()-1; i>=0; i--) {
   10338                     WindowToken token = mFinishedStarting.get(i);
   10339                     pw.print("  Finished Starting #"); pw.print(i);
   10340                             pw.print(' '); pw.print(token); pw.println(':');
   10341                     token.dump(pw, "    ");
   10342                 }
   10343             }
   10344             if (mExitingTokens.size() > 0) {
   10345                 pw.println(" ");
   10346                 pw.println("  Exiting tokens:");
   10347                 for (int i=mExitingTokens.size()-1; i>=0; i--) {
   10348                     WindowToken token = mExitingTokens.get(i);
   10349                     pw.print("  Exiting #"); pw.print(i);
   10350                             pw.print(' '); pw.print(token); pw.println(':');
   10351                     token.dump(pw, "    ");
   10352                 }
   10353             }
   10354             if (mExitingAppTokens.size() > 0) {
   10355                 pw.println(" ");
   10356                 pw.println("  Exiting application tokens:");
   10357                 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
   10358                     WindowToken token = mExitingAppTokens.get(i);
   10359                     pw.print("  Exiting App #"); pw.print(i);
   10360                             pw.print(' '); pw.print(token); pw.println(':');
   10361                     token.dump(pw, "    ");
   10362                 }
   10363             }
   10364             pw.println(" ");
   10365             pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
   10366             pw.print("  mLastFocus="); pw.println(mLastFocus);
   10367             pw.print("  mFocusedApp="); pw.println(mFocusedApp);
   10368             pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
   10369             pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
   10370             pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
   10371             if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) {
   10372                 pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
   10373                 pw.print("  mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
   10374             }
   10375             pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
   10376             pw.print("  mInTouchMode="); pw.print(mInTouchMode);
   10377                     pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
   10378             pw.print("  mSystemBooted="); pw.print(mSystemBooted);
   10379                     pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
   10380             pw.print("  mLayoutNeeded="); pw.print(mLayoutNeeded);
   10381                     pw.print(" mBlurShown="); pw.println(mBlurShown);
   10382             if (mDimAnimator != null) {
   10383                 mDimAnimator.printTo(pw);
   10384             } else {
   10385                 pw.println( "  no DimAnimator ");
   10386             }
   10387             pw.print("  mInputMethodAnimLayerAdjustment=");
   10388                     pw.print(mInputMethodAnimLayerAdjustment);
   10389                     pw.print("  mWallpaperAnimLayerAdjustment=");
   10390                     pw.println(mWallpaperAnimLayerAdjustment);
   10391             pw.print("  mLastWallpaperX="); pw.print(mLastWallpaperX);
   10392                     pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
   10393             pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
   10394                     pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
   10395                     pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen);
   10396                     pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig);
   10397             pw.print("  mRotation="); pw.print(mRotation);
   10398                     pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation);
   10399                     pw.print(", mRequestedRotation="); pw.println(mRequestedRotation);
   10400             pw.print("  mAnimationPending="); pw.print(mAnimationPending);
   10401                     pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
   10402                     pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale);
   10403             pw.print("  mNextAppTransition=0x");
   10404                     pw.print(Integer.toHexString(mNextAppTransition));
   10405                     pw.print(", mAppTransitionReady="); pw.print(mAppTransitionReady);
   10406                     pw.print(", mAppTransitionRunning="); pw.print(mAppTransitionRunning);
   10407                     pw.print(", mAppTransitionTimeout="); pw.println( mAppTransitionTimeout);
   10408             if (mNextAppTransitionPackage != null) {
   10409                 pw.print("  mNextAppTransitionPackage=");
   10410                     pw.print(mNextAppTransitionPackage);
   10411                     pw.print(", mNextAppTransitionEnter=0x");
   10412                     pw.print(Integer.toHexString(mNextAppTransitionEnter));
   10413                     pw.print(", mNextAppTransitionExit=0x");
   10414                     pw.print(Integer.toHexString(mNextAppTransitionExit));
   10415             }
   10416             pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
   10417                     pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
   10418             if (mLastEnterAnimToken != null || mLastEnterAnimToken != null) {
   10419                 pw.print("  mLastEnterAnimToken="); pw.print(mLastEnterAnimToken);
   10420                         pw.print(", mLastEnterAnimParams="); pw.println(mLastEnterAnimParams);
   10421             }
   10422             if (mOpeningApps.size() > 0) {
   10423                 pw.print("  mOpeningApps="); pw.println(mOpeningApps);
   10424             }
   10425             if (mClosingApps.size() > 0) {
   10426                 pw.print("  mClosingApps="); pw.println(mClosingApps);
   10427             }
   10428             if (mToTopApps.size() > 0) {
   10429                 pw.print("  mToTopApps="); pw.println(mToTopApps);
   10430             }
   10431             if (mToBottomApps.size() > 0) {
   10432                 pw.print("  mToBottomApps="); pw.println(mToBottomApps);
   10433             }
   10434             pw.print("  DisplayWidth="); pw.print(mDisplay.getWidth());
   10435                     pw.print(" DisplayHeight="); pw.println(mDisplay.getHeight());
   10436         }
   10437     }
   10438 
   10439     // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
   10440     public void monitor() {
   10441         synchronized (mWindowMap) { }
   10442         synchronized (mKeyguardTokenWatcher) { }
   10443     }
   10444 
   10445     /**
   10446      * DimAnimator class that controls the dim animation. This holds the surface and
   10447      * all state used for dim animation.
   10448      */
   10449     private static class DimAnimator {
   10450         Surface mDimSurface;
   10451         boolean mDimShown = false;
   10452         float mDimCurrentAlpha;
   10453         float mDimTargetAlpha;
   10454         float mDimDeltaPerMs;
   10455         long mLastDimAnimTime;
   10456 
   10457         int mLastDimWidth, mLastDimHeight;
   10458 
   10459         DimAnimator (SurfaceSession session) {
   10460             if (mDimSurface == null) {
   10461                 if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM "
   10462                         + mDimSurface + ": CREATE");
   10463                 try {
   10464                     mDimSurface = new Surface(session, 0,
   10465                             "DimSurface",
   10466                             -1, 16, 16, PixelFormat.OPAQUE,
   10467                             Surface.FX_SURFACE_DIM);
   10468                     mDimSurface.setAlpha(0.0f);
   10469                 } catch (Exception e) {
   10470                     Slog.e(TAG, "Exception creating Dim surface", e);
   10471                 }
   10472             }
   10473         }
   10474 
   10475         /**
   10476          * Show the dim surface.
   10477          */
   10478         void show(int dw, int dh) {
   10479             if (!mDimShown) {
   10480                 if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
   10481                         dw + "x" + dh + ")");
   10482                 mDimShown = true;
   10483                 try {
   10484                     mLastDimWidth = dw;
   10485                     mLastDimHeight = dh;
   10486                     mDimSurface.setPosition(0, 0);
   10487                     mDimSurface.setSize(dw, dh);
   10488                     mDimSurface.show();
   10489                 } catch (RuntimeException e) {
   10490                     Slog.w(TAG, "Failure showing dim surface", e);
   10491                 }
   10492             } else if (mLastDimWidth != dw || mLastDimHeight != dh) {
   10493                 mLastDimWidth = dw;
   10494                 mLastDimHeight = dh;
   10495                 mDimSurface.setSize(dw, dh);
   10496             }
   10497         }
   10498 
   10499         /**
   10500          * Set's the dim surface's layer and update dim parameters that will be used in
   10501          * {@link updateSurface} after all windows are examined.
   10502          */
   10503         void updateParameters(WindowState w, long currentTime) {
   10504             mDimSurface.setLayer(w.mAnimLayer-1);
   10505 
   10506             final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
   10507             if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM " + mDimSurface
   10508                     + ": layer=" + (w.mAnimLayer-1) + " target=" + target);
   10509             if (mDimTargetAlpha != target) {
   10510                 // If the desired dim level has changed, then
   10511                 // start an animation to it.
   10512                 mLastDimAnimTime = currentTime;
   10513                 long duration = (w.mAnimating && w.mAnimation != null)
   10514                         ? w.mAnimation.computeDurationHint()
   10515                         : DEFAULT_DIM_DURATION;
   10516                 if (target > mDimTargetAlpha) {
   10517                     // This is happening behind the activity UI,
   10518                     // so we can make it run a little longer to
   10519                     // give a stronger impression without disrupting
   10520                     // the user.
   10521                     duration *= DIM_DURATION_MULTIPLIER;
   10522                 }
   10523                 if (duration < 1) {
   10524                     // Don't divide by zero
   10525                     duration = 1;
   10526                 }
   10527                 mDimTargetAlpha = target;
   10528                 mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration;
   10529             }
   10530         }
   10531 
   10532         /**
   10533          * Updating the surface's alpha. Returns true if the animation continues, or returns
   10534          * false when the animation is finished and the dim surface is hidden.
   10535          */
   10536         boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
   10537             if (!dimming) {
   10538                 if (mDimTargetAlpha != 0) {
   10539                     mLastDimAnimTime = currentTime;
   10540                     mDimTargetAlpha = 0;
   10541                     mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION;
   10542                 }
   10543             }
   10544 
   10545             boolean animating = false;
   10546             if (mLastDimAnimTime != 0) {
   10547                 mDimCurrentAlpha += mDimDeltaPerMs
   10548                         * (currentTime-mLastDimAnimTime);
   10549                 boolean more = true;
   10550                 if (displayFrozen) {
   10551                     // If the display is frozen, there is no reason to animate.
   10552                     more = false;
   10553                 } else if (mDimDeltaPerMs > 0) {
   10554                     if (mDimCurrentAlpha > mDimTargetAlpha) {
   10555                         more = false;
   10556                     }
   10557                 } else if (mDimDeltaPerMs < 0) {
   10558                     if (mDimCurrentAlpha < mDimTargetAlpha) {
   10559                         more = false;
   10560                     }
   10561                 } else {
   10562                     more = false;
   10563                 }
   10564 
   10565                 // Do we need to continue animating?
   10566                 if (more) {
   10567                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM "
   10568                             + mDimSurface + ": alpha=" + mDimCurrentAlpha);
   10569                     mLastDimAnimTime = currentTime;
   10570                     mDimSurface.setAlpha(mDimCurrentAlpha);
   10571                     animating = true;
   10572                 } else {
   10573                     mDimCurrentAlpha = mDimTargetAlpha;
   10574                     mLastDimAnimTime = 0;
   10575                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM "
   10576                             + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
   10577                     mDimSurface.setAlpha(mDimCurrentAlpha);
   10578                     if (!dimming) {
   10579                         if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM " + mDimSurface
   10580                                 + ": HIDE");
   10581                         try {
   10582                             mDimSurface.hide();
   10583                         } catch (RuntimeException e) {
   10584                             Slog.w(TAG, "Illegal argument exception hiding dim surface");
   10585                         }
   10586                         mDimShown = false;
   10587                     }
   10588                 }
   10589             }
   10590             return animating;
   10591         }
   10592 
   10593         public void printTo(PrintWriter pw) {
   10594             pw.print("  mDimShown="); pw.print(mDimShown);
   10595             pw.print(" current="); pw.print(mDimCurrentAlpha);
   10596             pw.print(" target="); pw.print(mDimTargetAlpha);
   10597             pw.print(" delta="); pw.print(mDimDeltaPerMs);
   10598             pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
   10599         }
   10600     }
   10601 
   10602     /**
   10603      * Animation that fade in after 0.5 interpolate time, or fade out in reverse order.
   10604      * This is used for opening/closing transition for apps in compatible mode.
   10605      */
   10606     private static class FadeInOutAnimation extends Animation {
   10607         int mWidth;
   10608         boolean mFadeIn;
   10609 
   10610         public FadeInOutAnimation(boolean fadeIn) {
   10611             setInterpolator(new AccelerateInterpolator());
   10612             setDuration(DEFAULT_FADE_IN_OUT_DURATION);
   10613             mFadeIn = fadeIn;
   10614         }
   10615 
   10616         @Override
   10617         protected void applyTransformation(float interpolatedTime, Transformation t) {
   10618             float x = interpolatedTime;
   10619             if (!mFadeIn) {
   10620                 x = 1.0f - x; // reverse the interpolation for fade out
   10621             }
   10622             if (x < 0.5) {
   10623                 // move the window out of the screen.
   10624                 t.getMatrix().setTranslate(mWidth, 0);
   10625             } else {
   10626                 t.getMatrix().setTranslate(0, 0);// show
   10627                 t.setAlpha((x - 0.5f) * 2);
   10628             }
   10629         }
   10630 
   10631         @Override
   10632         public void initialize(int width, int height, int parentWidth, int parentHeight) {
   10633             // width is the screen width {@see AppWindowToken#stepAnimatinoLocked}
   10634             mWidth = width;
   10635         }
   10636 
   10637         @Override
   10638         public int getZAdjustment() {
   10639             return Animation.ZORDER_TOP;
   10640         }
   10641     }
   10642 }
   10643