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