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