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