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