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