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