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