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