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