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