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