WindowManagerService.java revision 22af5b842869abff5418263e6fb0b4b925077629
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    private 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            } else {
3550                newTask.mAppTokens.add(atoken);
3551            }
3552        }
3553    }
3554
3555    public int getOrientationFromWindowsLocked() {
3556        if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
3557            // If the display is frozen, some activities may be in the middle
3558            // of restarting, and thus have removed their old window.  If the
3559            // window has the flag to hide the lock screen, then the lock screen
3560            // can re-appear and inflict its own orientation on us.  Keep the
3561            // orientation stable until this all settles down.
3562            return mLastWindowForcedOrientation;
3563        }
3564
3565        // TODO(multidisplay): Change to the correct display.
3566        final WindowList windows = getDefaultWindowListLocked();
3567        int pos = windows.size() - 1;
3568        while (pos >= 0) {
3569            WindowState win = windows.get(pos);
3570            pos--;
3571            if (win.mAppToken != null) {
3572                // We hit an application window. so the orientation will be determined by the
3573                // app window. No point in continuing further.
3574                return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3575            }
3576            if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
3577                continue;
3578            }
3579            int req = win.mAttrs.screenOrientation;
3580            if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
3581                    (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
3582                continue;
3583            }
3584
3585            if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req);
3586            return (mLastWindowForcedOrientation=req);
3587        }
3588        return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3589    }
3590
3591    public int getOrientationFromAppTokensLocked() {
3592        int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3593        boolean findingBehind = false;
3594        boolean lastFullscreen = false;
3595        // TODO: Multi window.
3596        DisplayContent displayContent = getDefaultDisplayContentLocked();
3597        final ArrayList<Task> tasks = displayContent.getTasks();
3598        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
3599            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
3600            final int firstToken = tokens.size() - 1;
3601            for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) {
3602                final AppWindowToken atoken = tokens.get(tokenNdx);
3603
3604                if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken);
3605
3606                // if we're about to tear down this window and not seek for
3607                // the behind activity, don't use it for orientation
3608                if (!findingBehind
3609                        && (!atoken.hidden && atoken.hiddenRequested)) {
3610                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
3611                            + " -- going to hide");
3612                    continue;
3613                }
3614
3615                if (tokenNdx == firstToken) {
3616                    // If we have hit a new Task, and the bottom
3617                    // of the previous group didn't explicitly say to use
3618                    // the orientation behind it, and the last app was
3619                    // full screen, then we'll stick with the
3620                    // user's orientation.
3621                    if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
3622                            && lastFullscreen) {
3623                        if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3624                                + " -- end of group, return " + lastOrientation);
3625                        return lastOrientation;
3626                    }
3627                }
3628
3629                // We ignore any hidden applications on the top.
3630                if (atoken.hiddenRequested || atoken.willBeHidden) {
3631                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
3632                            + " -- hidden on top");
3633                    continue;
3634                }
3635
3636                if (tokenNdx == 0) {
3637                    // Last token in this task.
3638                    lastOrientation = atoken.requestedOrientation;
3639                }
3640
3641                int or = atoken.requestedOrientation;
3642                // If this application is fullscreen, and didn't explicitly say
3643                // to use the orientation behind it, then just take whatever
3644                // orientation it has and ignores whatever is under it.
3645                lastFullscreen = atoken.appFullscreen;
3646                if (lastFullscreen
3647                        && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3648                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3649                            + " -- full screen, return " + or);
3650                    return or;
3651                }
3652                // If this application has requested an explicit orientation,
3653                // then use it.
3654                if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
3655                        && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3656                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3657                            + " -- explicitly set, return " + or);
3658                    return or;
3659                }
3660                findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
3661            }
3662        }
3663        if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation");
3664        return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3665    }
3666
3667    @Override
3668    public Configuration updateOrientationFromAppTokens(
3669            Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3670        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3671                "updateOrientationFromAppTokens()")) {
3672            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3673        }
3674
3675        Configuration config = null;
3676        long ident = Binder.clearCallingIdentity();
3677
3678        synchronized(mWindowMap) {
3679            config = updateOrientationFromAppTokensLocked(currentConfig,
3680                    freezeThisOneIfNeeded);
3681        }
3682
3683        Binder.restoreCallingIdentity(ident);
3684        return config;
3685    }
3686
3687    private Configuration updateOrientationFromAppTokensLocked(
3688            Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3689        Configuration config = null;
3690
3691        if (updateOrientationFromAppTokensLocked(false)) {
3692            if (freezeThisOneIfNeeded != null) {
3693                AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);
3694                if (atoken != null) {
3695                    startAppFreezingScreenLocked(atoken);
3696                }
3697            }
3698            config = computeNewConfigurationLocked();
3699
3700        } else if (currentConfig != null) {
3701            // No obvious action we need to take, but if our current
3702            // state mismatches the activity manager's, update it,
3703            // disregarding font scale, which should remain set to
3704            // the value of the previous configuration.
3705            mTempConfiguration.setToDefaults();
3706            mTempConfiguration.fontScale = currentConfig.fontScale;
3707            if (computeScreenConfigurationLocked(mTempConfiguration)) {
3708                if (currentConfig.diff(mTempConfiguration) != 0) {
3709                    mWaitingForConfig = true;
3710                    final DisplayContent displayContent = getDefaultDisplayContentLocked();
3711                    displayContent.layoutNeeded = true;
3712                    int anim[] = new int[2];
3713                    if (displayContent.isDimming()) {
3714                        anim[0] = anim[1] = 0;
3715                    } else {
3716                        mPolicy.selectRotationAnimationLw(anim);
3717                    }
3718                    startFreezingDisplayLocked(false, anim[0], anim[1]);
3719                    config = new Configuration(mTempConfiguration);
3720                }
3721            }
3722        }
3723
3724        return config;
3725    }
3726
3727    /*
3728     * Determine the new desired orientation of the display, returning
3729     * a non-null new Configuration if it has changed from the current
3730     * orientation.  IF TRUE IS RETURNED SOMEONE MUST CALL
3731     * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
3732     * SCREEN.  This will typically be done for you if you call
3733     * sendNewConfiguration().
3734     *
3735     * The orientation is computed from non-application windows first. If none of
3736     * the non-application windows specify orientation, the orientation is computed from
3737     * application tokens.
3738     * @see android.view.IWindowManager#updateOrientationFromAppTokens(
3739     * android.os.IBinder)
3740     */
3741    boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
3742        long ident = Binder.clearCallingIdentity();
3743        try {
3744            int req = getOrientationFromWindowsLocked();
3745            if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
3746                req = getOrientationFromAppTokensLocked();
3747            }
3748
3749            if (req != mForcedAppOrientation) {
3750                mForcedAppOrientation = req;
3751                //send a message to Policy indicating orientation change to take
3752                //action like disabling/enabling sensors etc.,
3753                mPolicy.setCurrentOrientationLw(req);
3754                if (updateRotationUncheckedLocked(inTransaction)) {
3755                    // changed
3756                    return true;
3757                }
3758            }
3759
3760            return false;
3761        } finally {
3762            Binder.restoreCallingIdentity(ident);
3763        }
3764    }
3765
3766    @Override
3767    public void setNewConfiguration(Configuration config) {
3768        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3769                "setNewConfiguration()")) {
3770            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3771        }
3772
3773        synchronized(mWindowMap) {
3774            mCurConfiguration = new Configuration(config);
3775            if (mWaitingForConfig) {
3776                mWaitingForConfig = false;
3777                mLastFinishedFreezeSource = "new-config";
3778            }
3779            performLayoutAndPlaceSurfacesLocked();
3780        }
3781    }
3782
3783    @Override
3784    public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
3785        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3786                "setAppOrientation()")) {
3787            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3788        }
3789
3790        synchronized(mWindowMap) {
3791            AppWindowToken atoken = findAppWindowToken(token.asBinder());
3792            if (atoken == null) {
3793                Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
3794                return;
3795            }
3796
3797            atoken.requestedOrientation = requestedOrientation;
3798        }
3799    }
3800
3801    @Override
3802    public int getAppOrientation(IApplicationToken token) {
3803        synchronized(mWindowMap) {
3804            AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3805            if (wtoken == null) {
3806                return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3807            }
3808
3809            return wtoken.requestedOrientation;
3810        }
3811    }
3812
3813    /** Call while in a Surface transaction. */
3814    void setFocusedStackLayer() {
3815        mFocusedStackLayer = 0;
3816        if (mFocusedApp != null) {
3817            final WindowList windows = mFocusedApp.allAppWindows;
3818            for (int i = windows.size() - 1; i >= 0; --i) {
3819                final WindowState win = windows.get(i);
3820                final int animLayer = win.mWinAnimator.mAnimLayer;
3821                if (win.mAttachedWindow == null && win.isVisibleLw() &&
3822                        animLayer > mFocusedStackLayer) {
3823                    mFocusedStackLayer = animLayer + LAYER_OFFSET_FOCUSED_STACK;
3824                }
3825            }
3826        }
3827        if (DEBUG_LAYERS) Slog.v(TAG, "Setting FocusedStackFrame to layer=" +
3828                mFocusedStackLayer);
3829        mFocusedStackFrame.setLayer(mFocusedStackLayer);
3830    }
3831
3832    void setFocusedStackFrame() {
3833        final TaskStack stack;
3834        if (mFocusedApp != null) {
3835            Task task = mTaskIdToTask.get(mFocusedApp.groupId);
3836            stack = task.mStack;
3837            final DisplayContent displayContent = task.getDisplayContent();
3838            if (displayContent != null) {
3839                displayContent.setTouchExcludeRegion(stack);
3840            }
3841        } else {
3842            stack = null;
3843        }
3844        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame");
3845        SurfaceControl.openTransaction();
3846        try {
3847            if (stack == null) {
3848                mFocusedStackFrame.setVisibility(false);
3849            } else {
3850                mFocusedStackFrame.setBounds(stack);
3851                final boolean multipleStacks = !stack.isFullscreen();
3852                mFocusedStackFrame.setVisibility(multipleStacks);
3853            }
3854        } finally {
3855            SurfaceControl.closeTransaction();
3856            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame");
3857        }
3858    }
3859
3860    @Override
3861    public void setFocusedApp(IBinder token, boolean moveFocusNow) {
3862        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3863                "setFocusedApp()")) {
3864            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3865        }
3866
3867        synchronized(mWindowMap) {
3868            final AppWindowToken newFocus;
3869            if (token == null) {
3870                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);
3871                newFocus = null;
3872            } else {
3873                newFocus = findAppWindowToken(token);
3874                if (newFocus == null) {
3875                    Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
3876                }
3877                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus
3878                        + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow);
3879            }
3880
3881            final boolean changed = mFocusedApp != newFocus;
3882            if (changed) {
3883                mFocusedApp = newFocus;
3884                mInputMonitor.setFocusedAppLw(null);
3885            }
3886
3887            if (moveFocusNow && changed) {
3888                final long origId = Binder.clearCallingIdentity();
3889                updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
3890                Binder.restoreCallingIdentity(origId);
3891            }
3892        }
3893    }
3894
3895    @Override
3896    public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
3897        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3898                "prepareAppTransition()")) {
3899            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3900        }
3901
3902        synchronized(mWindowMap) {
3903            if (DEBUG_APP_TRANSITIONS) Slog.v(
3904                    TAG, "Prepare app transition: transit=" + transit
3905                    + " " + mAppTransition
3906                    + " alwaysKeepCurrent=" + alwaysKeepCurrent
3907                    + " Callers=" + Debug.getCallers(3));
3908            if (okToDisplay()) {
3909                if (!mAppTransition.isTransitionSet() || mAppTransition.isTransitionNone()) {
3910                    mAppTransition.setAppTransition(transit);
3911                } else if (!alwaysKeepCurrent) {
3912                    if (transit == AppTransition.TRANSIT_TASK_OPEN
3913                            && mAppTransition.isTransitionEqual(
3914                                    AppTransition.TRANSIT_TASK_CLOSE)) {
3915                        // Opening a new task always supersedes a close for the anim.
3916                        mAppTransition.setAppTransition(transit);
3917                    } else if (transit == AppTransition.TRANSIT_ACTIVITY_OPEN
3918                            && mAppTransition.isTransitionEqual(
3919                                AppTransition.TRANSIT_ACTIVITY_CLOSE)) {
3920                        // Opening a new activity always supersedes a close for the anim.
3921                        mAppTransition.setAppTransition(transit);
3922                    }
3923                }
3924                mAppTransition.prepare();
3925                mStartingIconInTransition = false;
3926                mSkipAppTransitionAnimation = false;
3927                mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
3928                mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000);
3929            }
3930        }
3931    }
3932
3933    @Override
3934    public int getPendingAppTransition() {
3935        return mAppTransition.getAppTransition();
3936    }
3937
3938    @Override
3939    public void overridePendingAppTransition(String packageName,
3940            int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
3941        synchronized(mWindowMap) {
3942            mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim,
3943                    startedCallback);
3944        }
3945    }
3946
3947    @Override
3948    public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
3949            int startHeight) {
3950        synchronized(mWindowMap) {
3951            mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth,
3952                    startHeight);
3953        }
3954    }
3955
3956    @Override
3957    public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
3958            int startY, IRemoteCallback startedCallback, boolean scaleUp) {
3959        synchronized(mWindowMap) {
3960            mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY,
3961                    startedCallback, scaleUp);
3962        }
3963    }
3964
3965    @Override
3966    public void executeAppTransition() {
3967        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3968                "executeAppTransition()")) {
3969            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3970        }
3971
3972        synchronized(mWindowMap) {
3973            if (DEBUG_APP_TRANSITIONS) {
3974                RuntimeException e = new RuntimeException("here");
3975                e.fillInStackTrace();
3976                Slog.w(TAG, "Execute app transition: " + mAppTransition, e);
3977            }
3978            if (mAppTransition.isTransitionSet()) {
3979                mAppTransition.setReady();
3980                final long origId = Binder.clearCallingIdentity();
3981                performLayoutAndPlaceSurfacesLocked();
3982                Binder.restoreCallingIdentity(origId);
3983            }
3984        }
3985    }
3986
3987    @Override
3988    public void setAppStartingWindow(IBinder token, String pkg,
3989            int theme, CompatibilityInfo compatInfo,
3990            CharSequence nonLocalizedLabel, int labelRes, int icon, int logo,
3991            int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
3992        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3993                "setAppStartingWindow()")) {
3994            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3995        }
3996
3997        synchronized(mWindowMap) {
3998            if (DEBUG_STARTING_WINDOW) Slog.v(
3999                    TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg
4000                    + " transferFrom=" + transferFrom);
4001
4002            AppWindowToken wtoken = findAppWindowToken(token);
4003            if (wtoken == null) {
4004                Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token);
4005                return;
4006            }
4007
4008            // If the display is frozen, we won't do anything until the
4009            // actual window is displayed so there is no reason to put in
4010            // the starting window.
4011            if (!okToDisplay()) {
4012                return;
4013            }
4014
4015            if (wtoken.startingData != null) {
4016                return;
4017            }
4018
4019            if (transferFrom != null) {
4020                AppWindowToken ttoken = findAppWindowToken(transferFrom);
4021                if (ttoken != null) {
4022                    WindowState startingWindow = ttoken.startingWindow;
4023                    if (startingWindow != null) {
4024                        if (mStartingIconInTransition) {
4025                            // In this case, the starting icon has already
4026                            // been displayed, so start letting windows get
4027                            // shown immediately without any more transitions.
4028                            mSkipAppTransitionAnimation = true;
4029                        }
4030                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
4031                                "Moving existing starting " + startingWindow + " from " + ttoken
4032                                + " to " + wtoken);
4033                        final long origId = Binder.clearCallingIdentity();
4034
4035                        // Transfer the starting window over to the new
4036                        // token.
4037                        wtoken.startingData = ttoken.startingData;
4038                        wtoken.startingView = ttoken.startingView;
4039                        wtoken.startingDisplayed = ttoken.startingDisplayed;
4040                        ttoken.startingDisplayed = false;
4041                        wtoken.startingWindow = startingWindow;
4042                        wtoken.reportedVisible = ttoken.reportedVisible;
4043                        ttoken.startingData = null;
4044                        ttoken.startingView = null;
4045                        ttoken.startingWindow = null;
4046                        ttoken.startingMoved = true;
4047                        startingWindow.mToken = wtoken;
4048                        startingWindow.mRootToken = wtoken;
4049                        startingWindow.mAppToken = wtoken;
4050                        startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator;
4051
4052                        if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) {
4053                            Slog.v(TAG, "Removing starting window: " + startingWindow);
4054                        }
4055                        removeStartingWindowTimeout(ttoken);
4056                        startingWindow.getWindowList().remove(startingWindow);
4057                        mWindowsChanged = true;
4058                        if (DEBUG_ADD_REMOVE) Slog.v(TAG,
4059                                "Removing starting " + startingWindow + " from " + ttoken);
4060                        ttoken.windows.remove(startingWindow);
4061                        ttoken.allAppWindows.remove(startingWindow);
4062                        addWindowToListInOrderLocked(startingWindow, true);
4063
4064                        // Propagate other interesting state between the
4065                        // tokens.  If the old token is displayed, we should
4066                        // immediately force the new one to be displayed.  If
4067                        // it is animating, we need to move that animation to
4068                        // the new one.
4069                        if (ttoken.allDrawn) {
4070                            wtoken.allDrawn = true;
4071                            wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn;
4072                        }
4073                        if (ttoken.firstWindowDrawn) {
4074                            wtoken.firstWindowDrawn = true;
4075                        }
4076                        if (!ttoken.hidden) {
4077                            wtoken.hidden = false;
4078                            wtoken.hiddenRequested = false;
4079                            wtoken.willBeHidden = false;
4080                        }
4081                        if (wtoken.clientHidden != ttoken.clientHidden) {
4082                            wtoken.clientHidden = ttoken.clientHidden;
4083                            wtoken.sendAppVisibilityToClients();
4084                        }
4085                        final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
4086                        final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
4087                        if (tAppAnimator.animation != null) {
4088                            wAppAnimator.animation = tAppAnimator.animation;
4089                            wAppAnimator.animating = tAppAnimator.animating;
4090                            wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment;
4091                            tAppAnimator.animation = null;
4092                            tAppAnimator.animLayerAdjustment = 0;
4093                            wAppAnimator.updateLayers();
4094                            tAppAnimator.updateLayers();
4095                        }
4096
4097                        updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4098                                true /*updateInputWindows*/);
4099                        getDefaultDisplayContentLocked().layoutNeeded = true;
4100                        performLayoutAndPlaceSurfacesLocked();
4101                        Binder.restoreCallingIdentity(origId);
4102                        return;
4103                    } else if (ttoken.startingData != null) {
4104                        // The previous app was getting ready to show a
4105                        // starting window, but hasn't yet done so.  Steal it!
4106                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
4107                                "Moving pending starting from " + ttoken
4108                                + " to " + wtoken);
4109                        wtoken.startingData = ttoken.startingData;
4110                        ttoken.startingData = null;
4111                        ttoken.startingMoved = true;
4112                        Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4113                        // Note: we really want to do sendMessageAtFrontOfQueue() because we
4114                        // want to process the message ASAP, before any other queued
4115                        // messages.
4116                        mH.sendMessageAtFrontOfQueue(m);
4117                        return;
4118                    }
4119                    final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
4120                    final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
4121                    if (tAppAnimator.thumbnail != null) {
4122                        // The old token is animating with a thumbnail, transfer
4123                        // that to the new token.
4124                        if (wAppAnimator.thumbnail != null) {
4125                            wAppAnimator.thumbnail.destroy();
4126                        }
4127                        wAppAnimator.thumbnail = tAppAnimator.thumbnail;
4128                        wAppAnimator.thumbnailX = tAppAnimator.thumbnailX;
4129                        wAppAnimator.thumbnailY = tAppAnimator.thumbnailY;
4130                        wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer;
4131                        wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
4132                        tAppAnimator.thumbnail = null;
4133                    }
4134                }
4135            }
4136
4137            // There is no existing starting window, and the caller doesn't
4138            // want us to create one, so that's it!
4139            if (!createIfNeeded) {
4140                return;
4141            }
4142
4143            // If this is a translucent window, then don't
4144            // show a starting window -- the current effect (a full-screen
4145            // opaque starting window that fades away to the real contents
4146            // when it is ready) does not work for this.
4147            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x"
4148                    + Integer.toHexString(theme));
4149            if (theme != 0) {
4150                AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
4151                        com.android.internal.R.styleable.Window, mCurrentUserId);
4152                if (ent == null) {
4153                    // Whoops!  App doesn't exist.  Um.  Okay.  We'll just
4154                    // pretend like we didn't see that.
4155                    return;
4156                }
4157                if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent="
4158                        + ent.array.getBoolean(
4159                                com.android.internal.R.styleable.Window_windowIsTranslucent, false)
4160                        + " Floating="
4161                        + ent.array.getBoolean(
4162                                com.android.internal.R.styleable.Window_windowIsFloating, false)
4163                        + " ShowWallpaper="
4164                        + ent.array.getBoolean(
4165                                com.android.internal.R.styleable.Window_windowShowWallpaper, false));
4166                if (ent.array.getBoolean(
4167                        com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
4168                    return;
4169                }
4170                if (ent.array.getBoolean(
4171                        com.android.internal.R.styleable.Window_windowIsFloating, false)) {
4172                    return;
4173                }
4174                if (ent.array.getBoolean(
4175                        com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
4176                    if (mWallpaperTarget == null) {
4177                        // If this theme is requesting a wallpaper, and the wallpaper
4178                        // is not curently visible, then this effectively serves as
4179                        // an opaque window and our starting window transition animation
4180                        // can still work.  We just need to make sure the starting window
4181                        // is also showing the wallpaper.
4182                        windowFlags |= FLAG_SHOW_WALLPAPER;
4183                    } else {
4184                        return;
4185                    }
4186                }
4187            }
4188
4189            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData");
4190            mStartingIconInTransition = true;
4191            wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
4192                    labelRes, icon, logo, windowFlags);
4193            Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4194            // Note: we really want to do sendMessageAtFrontOfQueue() because we
4195            // want to process the message ASAP, before any other queued
4196            // messages.
4197            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
4198            mH.sendMessageAtFrontOfQueue(m);
4199        }
4200    }
4201
4202    @Override
4203    public void setAppWillBeHidden(IBinder token) {
4204        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4205                "setAppWillBeHidden()")) {
4206            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4207        }
4208
4209        AppWindowToken wtoken;
4210
4211        synchronized(mWindowMap) {
4212            wtoken = findAppWindowToken(token);
4213            if (wtoken == null) {
4214                Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
4215                return;
4216            }
4217            wtoken.willBeHidden = true;
4218        }
4219    }
4220
4221    public void setAppFullscreen(IBinder token, boolean toOpaque) {
4222        AppWindowToken atoken = findAppWindowToken(token);
4223        if (atoken != null) {
4224            atoken.appFullscreen = toOpaque;
4225            // When making translucent, wait until windows below have been drawn.
4226            if (toOpaque) {
4227                // Making opaque so do it now.
4228                setWindowOpaque(token, true);
4229            }
4230            requestTraversal();
4231        }
4232    }
4233
4234    public void setWindowOpaque(IBinder token, boolean isOpaque) {
4235        AppWindowToken wtoken = findAppWindowToken(token);
4236        if (wtoken != null) {
4237            WindowState win = wtoken.findMainWindow();
4238            if (win != null) {
4239                win.mWinAnimator.setOpaque(isOpaque);
4240            }
4241        }
4242    }
4243
4244    boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
4245            boolean visible, int transit, boolean performLayout) {
4246        boolean delayed = false;
4247
4248        if (wtoken.clientHidden == visible) {
4249            wtoken.clientHidden = !visible;
4250            wtoken.sendAppVisibilityToClients();
4251        }
4252
4253        wtoken.willBeHidden = false;
4254        if (wtoken.hidden == visible) {
4255            boolean changed = false;
4256            if (DEBUG_APP_TRANSITIONS) Slog.v(
4257                TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
4258                + " performLayout=" + performLayout);
4259
4260            boolean runningAppAnimation = false;
4261
4262            if (transit != AppTransition.TRANSIT_UNSET) {
4263                if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
4264                    wtoken.mAppAnimator.animation = null;
4265                }
4266                if (applyAnimationLocked(wtoken, lp, transit, visible)) {
4267                    delayed = runningAppAnimation = true;
4268                }
4269                WindowState window = wtoken.findMainWindow();
4270                //TODO (multidisplay): Magnification is supported only for the default display.
4271                if (window != null && mDisplayMagnifier != null
4272                        && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
4273                    mDisplayMagnifier.onAppWindowTransitionLocked(window, transit);
4274                }
4275                changed = true;
4276            }
4277
4278            final int N = wtoken.allAppWindows.size();
4279            for (int i=0; i<N; i++) {
4280                WindowState win = wtoken.allAppWindows.get(i);
4281                if (win == wtoken.startingWindow) {
4282                    continue;
4283                }
4284
4285                //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible());
4286                //win.dump("  ");
4287                if (visible) {
4288                    if (!win.isVisibleNow()) {
4289                        if (!runningAppAnimation) {
4290                            win.mWinAnimator.applyAnimationLocked(
4291                                    WindowManagerPolicy.TRANSIT_ENTER, true);
4292                            //TODO (multidisplay): Magnification is supported only for the default
4293                            if (mDisplayMagnifier != null
4294                                    && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4295                                mDisplayMagnifier.onWindowTransitionLocked(win,
4296                                        WindowManagerPolicy.TRANSIT_ENTER);
4297                            }
4298                        }
4299                        changed = true;
4300                        final DisplayContent displayContent = win.getDisplayContent();
4301                        if (displayContent != null) {
4302                            displayContent.layoutNeeded = true;
4303                        }
4304                    }
4305                } else if (win.isVisibleNow()) {
4306                    if (!runningAppAnimation) {
4307                        win.mWinAnimator.applyAnimationLocked(
4308                                WindowManagerPolicy.TRANSIT_EXIT, false);
4309                        //TODO (multidisplay): Magnification is supported only for the default
4310                        if (mDisplayMagnifier != null
4311                                && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4312                            mDisplayMagnifier.onWindowTransitionLocked(win,
4313                                    WindowManagerPolicy.TRANSIT_EXIT);
4314                        }
4315                    }
4316                    changed = true;
4317                    final DisplayContent displayContent = win.getDisplayContent();
4318                    if (displayContent != null) {
4319                        displayContent.layoutNeeded = true;
4320                    }
4321                }
4322            }
4323
4324            wtoken.hidden = wtoken.hiddenRequested = !visible;
4325            if (!visible) {
4326                unsetAppFreezingScreenLocked(wtoken, true, true);
4327            } else {
4328                // If we are being set visible, and the starting window is
4329                // not yet displayed, then make sure it doesn't get displayed.
4330                WindowState swin = wtoken.startingWindow;
4331                if (swin != null && !swin.isDrawnLw()) {
4332                    swin.mPolicyVisibility = false;
4333                    swin.mPolicyVisibilityAfterAnim = false;
4334                 }
4335            }
4336
4337            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken
4338                      + ": hidden=" + wtoken.hidden + " hiddenRequested="
4339                      + wtoken.hiddenRequested);
4340
4341            if (changed) {
4342                mInputMonitor.setUpdateInputWindowsNeededLw();
4343                if (performLayout) {
4344                    updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4345                            false /*updateInputWindows*/);
4346                    performLayoutAndPlaceSurfacesLocked();
4347                }
4348                mInputMonitor.updateInputWindowsLw(false /*force*/);
4349            }
4350        }
4351
4352        if (wtoken.mAppAnimator.animation != null) {
4353            delayed = true;
4354        }
4355
4356        for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) {
4357            if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) {
4358                delayed = true;
4359            }
4360        }
4361
4362        return delayed;
4363    }
4364
4365    @Override
4366    public void setAppVisibility(IBinder token, boolean visible) {
4367        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4368                "setAppVisibility()")) {
4369            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4370        }
4371
4372        AppWindowToken wtoken;
4373
4374        synchronized(mWindowMap) {
4375            wtoken = findAppWindowToken(token);
4376            if (wtoken == null) {
4377                Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
4378                return;
4379            }
4380
4381            if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
4382                RuntimeException e = null;
4383                if (!HIDE_STACK_CRAWLS) {
4384                    e = new RuntimeException();
4385                    e.fillInStackTrace();
4386                }
4387                Slog.v(TAG, "setAppVisibility(" + token + ", visible=" + visible
4388                        + "): " + mAppTransition
4389                        + " hidden=" + wtoken.hidden
4390                        + " hiddenRequested=" + wtoken.hiddenRequested, e);
4391            }
4392
4393            // If we are preparing an app transition, then delay changing
4394            // the visibility of this token until we execute that transition.
4395            if (okToDisplay() && mAppTransition.isTransitionSet()) {
4396                wtoken.hiddenRequested = !visible;
4397
4398                if (!wtoken.startingDisplayed) {
4399                    if (DEBUG_APP_TRANSITIONS) Slog.v(
4400                            TAG, "Setting dummy animation on: " + wtoken);
4401                    wtoken.mAppAnimator.setDummyAnimation();
4402                }
4403                mOpeningApps.remove(wtoken);
4404                mClosingApps.remove(wtoken);
4405                wtoken.waitingToShow = wtoken.waitingToHide = false;
4406                wtoken.inPendingTransaction = true;
4407                if (visible) {
4408                    mOpeningApps.add(wtoken);
4409                    wtoken.startingMoved = false;
4410
4411                    // If the token is currently hidden (should be the
4412                    // common case), then we need to set up to wait for
4413                    // its windows to be ready.
4414                    if (wtoken.hidden) {
4415                        wtoken.allDrawn = false;
4416                        wtoken.deferClearAllDrawn = false;
4417                        wtoken.waitingToShow = true;
4418
4419                        if (wtoken.clientHidden) {
4420                            // In the case where we are making an app visible
4421                            // but holding off for a transition, we still need
4422                            // to tell the client to make its windows visible so
4423                            // they get drawn.  Otherwise, we will wait on
4424                            // performing the transition until all windows have
4425                            // been drawn, they never will be, and we are sad.
4426                            wtoken.clientHidden = false;
4427                            wtoken.sendAppVisibilityToClients();
4428                        }
4429                    }
4430                } else {
4431                    mClosingApps.add(wtoken);
4432
4433                    // If the token is currently visible (should be the
4434                    // common case), then set up to wait for it to be hidden.
4435                    if (!wtoken.hidden) {
4436                        wtoken.waitingToHide = true;
4437                    }
4438                }
4439                return;
4440            }
4441
4442            final long origId = Binder.clearCallingIdentity();
4443            setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET,
4444                    true);
4445            wtoken.updateReportedVisibilityLocked();
4446            Binder.restoreCallingIdentity(origId);
4447        }
4448    }
4449
4450    void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
4451            boolean unfreezeSurfaceNow, boolean force) {
4452        if (wtoken.mAppAnimator.freezingScreen) {
4453            if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
4454                    + " force=" + force);
4455            final int N = wtoken.allAppWindows.size();
4456            boolean unfrozeWindows = false;
4457            for (int i=0; i<N; i++) {
4458                WindowState w = wtoken.allAppWindows.get(i);
4459                if (w.mAppFreezing) {
4460                    w.mAppFreezing = false;
4461                    if (w.mHasSurface && !w.mOrientationChanging) {
4462                        if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w);
4463                        w.mOrientationChanging = true;
4464                        mInnerFields.mOrientationChangeComplete = false;
4465                    }
4466                    w.mLastFreezeDuration = 0;
4467                    unfrozeWindows = true;
4468                    final DisplayContent displayContent = w.getDisplayContent();
4469                    if (displayContent != null) {
4470                        displayContent.layoutNeeded = true;
4471                    }
4472                }
4473            }
4474            if (force || unfrozeWindows) {
4475                if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
4476                wtoken.mAppAnimator.freezingScreen = false;
4477                wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime()
4478                        - mDisplayFreezeTime);
4479                mAppsFreezingScreen--;
4480                mLastFinishedFreezeSource = wtoken;
4481            }
4482            if (unfreezeSurfaceNow) {
4483                if (unfrozeWindows) {
4484                    performLayoutAndPlaceSurfacesLocked();
4485                }
4486                stopFreezingDisplayLocked();
4487            }
4488        }
4489    }
4490
4491    private void startAppFreezingScreenLocked(AppWindowToken wtoken) {
4492        if (DEBUG_ORIENTATION) {
4493            RuntimeException e = null;
4494            if (!HIDE_STACK_CRAWLS) {
4495                e = new RuntimeException();
4496                e.fillInStackTrace();
4497            }
4498            Slog.i(TAG, "Set freezing of " + wtoken.appToken
4499                    + ": hidden=" + wtoken.hidden + " freezing="
4500                    + wtoken.mAppAnimator.freezingScreen, e);
4501        }
4502        if (!wtoken.hiddenRequested) {
4503            if (!wtoken.mAppAnimator.freezingScreen) {
4504                wtoken.mAppAnimator.freezingScreen = true;
4505                wtoken.mAppAnimator.lastFreezeDuration = 0;
4506                mAppsFreezingScreen++;
4507                if (mAppsFreezingScreen == 1) {
4508                    startFreezingDisplayLocked(false, 0, 0);
4509                    mH.removeMessages(H.APP_FREEZE_TIMEOUT);
4510                    mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000);
4511                }
4512            }
4513            final int N = wtoken.allAppWindows.size();
4514            for (int i=0; i<N; i++) {
4515                WindowState w = wtoken.allAppWindows.get(i);
4516                w.mAppFreezing = true;
4517            }
4518        }
4519    }
4520
4521    @Override
4522    public void startAppFreezingScreen(IBinder token, int configChanges) {
4523        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4524                "setAppFreezingScreen()")) {
4525            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4526        }
4527
4528        synchronized(mWindowMap) {
4529            if (configChanges == 0 && okToDisplay()) {
4530                if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
4531                return;
4532            }
4533
4534            AppWindowToken wtoken = findAppWindowToken(token);
4535            if (wtoken == null || wtoken.appToken == null) {
4536                Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
4537                return;
4538            }
4539            final long origId = Binder.clearCallingIdentity();
4540            startAppFreezingScreenLocked(wtoken);
4541            Binder.restoreCallingIdentity(origId);
4542        }
4543    }
4544
4545    @Override
4546    public void stopAppFreezingScreen(IBinder token, boolean force) {
4547        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4548                "setAppFreezingScreen()")) {
4549            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4550        }
4551
4552        synchronized(mWindowMap) {
4553            AppWindowToken wtoken = findAppWindowToken(token);
4554            if (wtoken == null || wtoken.appToken == null) {
4555                return;
4556            }
4557            final long origId = Binder.clearCallingIdentity();
4558            if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
4559                    + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
4560            unsetAppFreezingScreenLocked(wtoken, true, force);
4561            Binder.restoreCallingIdentity(origId);
4562        }
4563    }
4564
4565    void removeAppFromTaskLocked(AppWindowToken wtoken) {
4566        final Task task = mTaskIdToTask.get(wtoken.groupId);
4567        if (task != null) {
4568            if (!task.removeAppToken(wtoken)) {
4569                Slog.e(TAG, "removeAppFromTaskLocked: token=" + wtoken + " not found.");
4570            }
4571        }
4572    }
4573
4574    @Override
4575    public void removeAppToken(IBinder token) {
4576        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4577                "removeAppToken()")) {
4578            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4579        }
4580
4581        AppWindowToken wtoken = null;
4582        AppWindowToken startingToken = null;
4583        boolean delayed = false;
4584
4585        final long origId = Binder.clearCallingIdentity();
4586        synchronized(mWindowMap) {
4587            WindowToken basewtoken = mTokenMap.remove(token);
4588            if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
4589                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
4590                delayed = setTokenVisibilityLocked(wtoken, null, false,
4591                        AppTransition.TRANSIT_UNSET, true);
4592                wtoken.inPendingTransaction = false;
4593                mOpeningApps.remove(wtoken);
4594                wtoken.waitingToShow = false;
4595                if (mClosingApps.contains(wtoken)) {
4596                    delayed = true;
4597                } else if (mAppTransition.isTransitionSet()) {
4598                    mClosingApps.add(wtoken);
4599                    wtoken.waitingToHide = true;
4600                    delayed = true;
4601                }
4602                if (DEBUG_APP_TRANSITIONS) Slog.v(
4603                        TAG, "Removing app " + wtoken + " delayed=" + delayed
4604                        + " animation=" + wtoken.mAppAnimator.animation
4605                        + " animating=" + wtoken.mAppAnimator.animating);
4606                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: "
4607                        + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
4608                final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack;
4609                if (delayed) {
4610                    // set the token aside because it has an active animation to be finished
4611                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
4612                            "removeAppToken make exiting: " + wtoken);
4613                    stack.mExitingAppTokens.add(wtoken);
4614                    wtoken.mDeferRemoval = true;
4615                } else {
4616                    // Make sure there is no animation running on this token,
4617                    // so any windows associated with it will be removed as
4618                    // soon as their animations are complete
4619                    wtoken.mAppAnimator.clearAnimation();
4620                    wtoken.mAppAnimator.animating = false;
4621                    removeAppFromTaskLocked(wtoken);
4622                }
4623
4624                wtoken.removed = true;
4625                if (wtoken.startingData != null) {
4626                    startingToken = wtoken;
4627                }
4628                unsetAppFreezingScreenLocked(wtoken, true, true);
4629                if (mFocusedApp == wtoken) {
4630                    if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Removing focused app token:" + wtoken);
4631                    mFocusedApp = null;
4632                    updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
4633                    mInputMonitor.setFocusedAppLw(null);
4634                }
4635            } else {
4636                Slog.w(TAG, "Attempted to remove non-existing app token: " + token);
4637            }
4638
4639            if (!delayed && wtoken != null) {
4640                wtoken.updateReportedVisibilityLocked();
4641            }
4642        }
4643        Binder.restoreCallingIdentity(origId);
4644
4645        // Will only remove if startingToken non null.
4646        scheduleRemoveStartingWindow(startingToken);
4647    }
4648
4649    void removeStartingWindowTimeout(AppWindowToken wtoken) {
4650        if (wtoken != null) {
4651            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) +
4652                    ": Remove starting window timeout " + wtoken + (wtoken != null ?
4653                    " startingWindow=" + wtoken.startingWindow : ""));
4654            mH.removeMessages(H.REMOVE_STARTING_TIMEOUT, wtoken);
4655        }
4656    }
4657
4658    void scheduleRemoveStartingWindow(AppWindowToken wtoken) {
4659        if (wtoken != null && wtoken.startingWindow != null) {
4660            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) +
4661                    ": Schedule remove starting " + wtoken + (wtoken != null ?
4662                    " startingWindow=" + wtoken.startingWindow : ""));
4663            removeStartingWindowTimeout(wtoken);
4664            Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken);
4665            mH.sendMessage(m);
4666        }
4667    }
4668
4669    private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
4670        WindowList windows = token.windows;
4671        final int NW = windows.size();
4672        if (NW > 0) {
4673            mWindowsChanged = true;
4674        }
4675        for (int i = 0; i < NW; i++) {
4676            WindowState win = windows.get(i);
4677            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
4678            win.getWindowList().remove(win);
4679            int j = win.mChildWindows.size();
4680            while (j > 0) {
4681                j--;
4682                WindowState cwin = win.mChildWindows.get(j);
4683                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
4684                        "Tmp removing child window " + cwin);
4685                cwin.getWindowList().remove(cwin);
4686            }
4687        }
4688        return NW > 0;
4689    }
4690
4691    void dumpAppTokensLocked() {
4692        final int numStacks = mStackIdToStack.size();
4693        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
4694            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
4695            Slog.v(TAG, "  Stack #" + stack.mStackId + " tasks from bottom to top:");
4696            final ArrayList<Task> tasks = stack.getTasks();
4697            final int numTasks = tasks.size();
4698            for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4699                final Task task = tasks.get(taskNdx);
4700                Slog.v(TAG, "    Task #" + task.taskId + " activities from bottom to top:");
4701                AppTokenList tokens = task.mAppTokens;
4702                final int numTokens = tokens.size();
4703                for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
4704                    Slog.v(TAG, "      activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token);
4705                }
4706            }
4707        }
4708    }
4709
4710    void dumpWindowsLocked() {
4711        final int numDisplays = mDisplayContents.size();
4712        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4713            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
4714            Slog.v(TAG, " Display #" + displayContent.getDisplayId());
4715            final WindowList windows = displayContent.getWindowList();
4716            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
4717                Slog.v(TAG, "  #" + winNdx + ": " + windows.get(winNdx));
4718            }
4719        }
4720    }
4721
4722    private int findAppWindowInsertionPointLocked(AppWindowToken target) {
4723        final int taskId = target.groupId;
4724        Task targetTask = mTaskIdToTask.get(taskId);
4725        if (targetTask == null) {
4726            Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId="
4727                    + taskId);
4728            return 0;
4729        }
4730        DisplayContent displayContent = targetTask.getDisplayContent();
4731        if (displayContent == null) {
4732            Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target);
4733            return 0;
4734        }
4735        final WindowList windows = displayContent.getWindowList();
4736        final int NW = windows.size();
4737
4738        boolean found = false;
4739        final ArrayList<Task> tasks = displayContent.getTasks();
4740        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
4741            final Task task = tasks.get(taskNdx);
4742            if (!found && task.taskId != taskId) {
4743                continue;
4744            }
4745            AppTokenList tokens = task.mAppTokens;
4746            for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
4747                final AppWindowToken wtoken = tokens.get(tokenNdx);
4748                if (!found && wtoken == target) {
4749                    found = true;
4750                }
4751                if (found) {
4752                    // Find the first app token below the new position that has
4753                    // a window displayed.
4754                    if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token);
4755                    if (wtoken.sendingToBottom) {
4756                        if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom");
4757                        continue;
4758                    }
4759                    for (int i = wtoken.windows.size() - 1; i >= 0; --i) {
4760                        WindowState win = wtoken.windows.get(i);
4761                        for (int j = win.mChildWindows.size() - 1; j >= 0; --j) {
4762                            WindowState cwin = win.mChildWindows.get(j);
4763                            if (cwin.mSubLayer >= 0) {
4764                                for (int pos = NW - 1; pos >= 0; pos--) {
4765                                    if (windows.get(pos) == cwin) {
4766                                        if (DEBUG_REORDER) Slog.v(TAG,
4767                                                "Found child win @" + (pos + 1));
4768                                        return pos + 1;
4769                                    }
4770                                }
4771                            }
4772                        }
4773                        for (int pos = NW - 1; pos >= 0; pos--) {
4774                            if (windows.get(pos) == win) {
4775                                if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1));
4776                                return pos + 1;
4777                            }
4778                        }
4779                    }
4780                }
4781            }
4782        }
4783        // Never put an app window underneath wallpaper.
4784        for (int pos = NW - 1; pos >= 0; pos--) {
4785            if (windows.get(pos).mIsWallpaper) {
4786                if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos);
4787                return pos + 1;
4788            }
4789        }
4790        return 0;
4791    }
4792
4793    private final int reAddWindowLocked(int index, WindowState win) {
4794        final WindowList windows = win.getWindowList();
4795        final int NCW = win.mChildWindows.size();
4796        boolean added = false;
4797        for (int j=0; j<NCW; j++) {
4798            WindowState cwin = win.mChildWindows.get(j);
4799            if (!added && cwin.mSubLayer >= 0) {
4800                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
4801                        + index + ": " + cwin);
4802                win.mRebuilding = false;
4803                windows.add(index, win);
4804                index++;
4805                added = true;
4806            }
4807            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4808                    + index + ": " + cwin);
4809            cwin.mRebuilding = false;
4810            windows.add(index, cwin);
4811            index++;
4812        }
4813        if (!added) {
4814            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4815                    + index + ": " + win);
4816            win.mRebuilding = false;
4817            windows.add(index, win);
4818            index++;
4819        }
4820        mWindowsChanged = true;
4821        return index;
4822    }
4823
4824    private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index,
4825                                            WindowToken token) {
4826        final int NW = token.windows.size();
4827        for (int i=0; i<NW; i++) {
4828            final WindowState win = token.windows.get(i);
4829            final DisplayContent winDisplayContent = win.getDisplayContent();
4830            if (winDisplayContent == displayContent || winDisplayContent == null) {
4831                win.mDisplayContent = displayContent;
4832                index = reAddWindowLocked(index, win);
4833            }
4834        }
4835        return index;
4836    }
4837
4838    void tmpRemoveTaskWindowsLocked(Task task) {
4839        AppTokenList tokens = task.mAppTokens;
4840        for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
4841            tmpRemoveAppWindowsLocked(tokens.get(tokenNdx));
4842        }
4843    }
4844
4845    void moveStackWindowsLocked(DisplayContent displayContent) {
4846        // First remove all of the windows from the list.
4847        final ArrayList<Task> tasks = displayContent.getTasks();
4848        final int numTasks = tasks.size();
4849        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4850            tmpRemoveTaskWindowsLocked(tasks.get(taskNdx));
4851        }
4852
4853        // And now add them back at the correct place.
4854        // Where to start adding?
4855        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4856            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
4857            int pos = findAppWindowInsertionPointLocked(tokens.get(0));
4858            final int numTokens = tokens.size();
4859            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
4860                final AppWindowToken wtoken = tokens.get(tokenNdx);
4861                if (wtoken != null) {
4862                    final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
4863                    if (newPos != pos) {
4864                        displayContent.layoutNeeded = true;
4865                    }
4866                    pos = newPos;
4867                }
4868            }
4869        }
4870
4871        if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4872                false /*updateInputWindows*/)) {
4873            assignLayersLocked(displayContent.getWindowList());
4874        }
4875
4876        mInputMonitor.setUpdateInputWindowsNeededLw();
4877        performLayoutAndPlaceSurfacesLocked();
4878        mInputMonitor.updateInputWindowsLw(false /*force*/);
4879
4880        //dump();
4881    }
4882
4883    public void moveTaskToTop(int taskId) {
4884        final long origId = Binder.clearCallingIdentity();
4885        try {
4886            synchronized(mWindowMap) {
4887                Task task = mTaskIdToTask.get(taskId);
4888                if (task == null) {
4889                    // Normal behavior, addAppToken will be called next and task will be created.
4890                    return;
4891                }
4892                final TaskStack stack = task.mStack;
4893                final DisplayContent displayContent = task.getDisplayContent();
4894                displayContent.moveStack(stack, true);
4895                if (displayContent.isDefaultDisplay) {
4896                    final TaskStack homeStack = displayContent.getHomeStack();
4897                    if (homeStack != stack) {
4898                        // When a non-home stack moves to the top, the home stack moves to the
4899                        // bottom.
4900                        displayContent.moveStack(homeStack, false);
4901                    }
4902                }
4903                stack.moveTaskToTop(task);
4904            }
4905        } finally {
4906            Binder.restoreCallingIdentity(origId);
4907        }
4908    }
4909
4910    public void moveTaskToBottom(int taskId) {
4911        final long origId = Binder.clearCallingIdentity();
4912        try {
4913            synchronized(mWindowMap) {
4914                Task task = mTaskIdToTask.get(taskId);
4915                if (task == null) {
4916                    Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId
4917                            + " not found in mTaskIdToTask");
4918                    return;
4919                }
4920                final TaskStack stack = task.mStack;
4921                stack.moveTaskToBottom(task);
4922                moveStackWindowsLocked(stack.getDisplayContent());
4923            }
4924        } finally {
4925            Binder.restoreCallingIdentity(origId);
4926        }
4927    }
4928
4929    /**
4930     * Create a new TaskStack and place it on a DisplayContent.
4931     * @param stackId The unique identifier of the new stack.
4932     * @param displayId The unique identifier of the DisplayContent.
4933     */
4934    public void attachStack(int stackId, int displayId) {
4935        final long origId = Binder.clearCallingIdentity();
4936        try {
4937            synchronized (mWindowMap) {
4938                final DisplayContent displayContent = mDisplayContents.get(displayId);
4939                if (displayContent != null) {
4940                    TaskStack stack = mStackIdToStack.get(stackId);
4941                    if (stack == null) {
4942                        if (DEBUG_STACK) Slog.d(TAG, "attachStack: stackId=" + stackId);
4943                        stack = new TaskStack(this, stackId);
4944                        mStackIdToStack.put(stackId, stack);
4945                    }
4946                    stack.attachDisplayContent(displayContent);
4947                    displayContent.attachStack(stack);
4948                    moveStackWindowsLocked(displayContent);
4949                    final WindowList windows = displayContent.getWindowList();
4950                    for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
4951                        windows.get(winNdx).reportResized();
4952                    }
4953                }
4954            }
4955        } finally {
4956            Binder.restoreCallingIdentity(origId);
4957        }
4958    }
4959
4960    void detachStackLocked(DisplayContent displayContent, TaskStack stack) {
4961        displayContent.detachStack(stack);
4962        stack.detachDisplay();
4963    }
4964
4965    public void detachStack(int stackId) {
4966        synchronized (mWindowMap) {
4967            TaskStack stack = mStackIdToStack.get(stackId);
4968            if (stack != null) {
4969                final DisplayContent displayContent = stack.getDisplayContent();
4970                if (displayContent != null) {
4971                    if (stack.isAnimating()) {
4972                        stack.mDeferDetach = true;
4973                        return;
4974                    }
4975                    detachStackLocked(displayContent, stack);
4976                }
4977            }
4978        }
4979    }
4980
4981    public void removeStack(int stackId) {
4982        mStackIdToStack.remove(stackId);
4983    }
4984
4985    void removeTaskLocked(Task task) {
4986        final int taskId = task.taskId;
4987        final TaskStack stack = task.mStack;
4988        if (stack.isAnimating()) {
4989            if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId);
4990            task.mDeferRemoval = true;
4991            return;
4992        }
4993        if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId);
4994        EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask");
4995        task.mDeferRemoval = false;
4996        task.mStack.removeTask(task);
4997        mTaskIdToTask.delete(task.taskId);
4998    }
4999
5000    public void removeTask(int taskId) {
5001        synchronized (mWindowMap) {
5002            Task task = mTaskIdToTask.get(taskId);
5003            if (task == null) {
5004                if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId);
5005                return;
5006            }
5007            removeTaskLocked(task);
5008        }
5009    }
5010
5011    public void addTask(int taskId, int stackId, boolean toTop) {
5012        synchronized (mWindowMap) {
5013            if (DEBUG_STACK) Slog.i(TAG, "addTask: adding taskId=" + taskId
5014                    + " to " + (toTop ? "top" : "bottom"));
5015            Task task = mTaskIdToTask.get(taskId);
5016            if (task == null) {
5017                return;
5018            }
5019            TaskStack stack = mStackIdToStack.get(stackId);
5020            stack.addTask(task, toTop);
5021            final DisplayContent displayContent = stack.getDisplayContent();
5022            displayContent.layoutNeeded = true;
5023            performLayoutAndPlaceSurfacesLocked();
5024        }
5025    }
5026
5027    public void resizeStack(int stackId, Rect bounds) {
5028        synchronized (mWindowMap) {
5029            final TaskStack stack = mStackIdToStack.get(stackId);
5030            if (stack == null) {
5031                throw new IllegalArgumentException("resizeStack: stackId " + stackId
5032                        + " not found.");
5033            }
5034            if (stack.setBounds(bounds)) {
5035                stack.resizeWindows();
5036                stack.getDisplayContent().layoutNeeded = true;
5037                performLayoutAndPlaceSurfacesLocked();
5038            }
5039        }
5040    }
5041
5042    public void getStackBounds(int stackId, Rect bounds) {
5043        final TaskStack stack = mStackIdToStack.get(stackId);
5044        if (stack != null) {
5045            stack.getBounds(bounds);
5046            return;
5047        }
5048        bounds.setEmpty();
5049    }
5050
5051    // -------------------------------------------------------------
5052    // Misc IWindowSession methods
5053    // -------------------------------------------------------------
5054
5055    @Override
5056    public void startFreezingScreen(int exitAnim, int enterAnim) {
5057        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5058                "startFreezingScreen()")) {
5059            throw new SecurityException("Requires FREEZE_SCREEN permission");
5060        }
5061
5062        synchronized(mWindowMap) {
5063            if (!mClientFreezingScreen) {
5064                mClientFreezingScreen = true;
5065                final long origId = Binder.clearCallingIdentity();
5066                try {
5067                    startFreezingDisplayLocked(false, exitAnim, enterAnim);
5068                    mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
5069                    mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
5070                } finally {
5071                    Binder.restoreCallingIdentity(origId);
5072                }
5073            }
5074        }
5075    }
5076
5077    @Override
5078    public void stopFreezingScreen() {
5079        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5080                "stopFreezingScreen()")) {
5081            throw new SecurityException("Requires FREEZE_SCREEN permission");
5082        }
5083
5084        synchronized(mWindowMap) {
5085            if (mClientFreezingScreen) {
5086                mClientFreezingScreen = false;
5087                mLastFinishedFreezeSource = "client";
5088                final long origId = Binder.clearCallingIdentity();
5089                try {
5090                    stopFreezingDisplayLocked();
5091                } finally {
5092                    Binder.restoreCallingIdentity(origId);
5093                }
5094            }
5095        }
5096    }
5097
5098    @Override
5099    public void disableKeyguard(IBinder token, String tag) {
5100        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5101            != PackageManager.PERMISSION_GRANTED) {
5102            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5103        }
5104
5105        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5106                KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
5107    }
5108
5109    @Override
5110    public void reenableKeyguard(IBinder token) {
5111        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5112            != PackageManager.PERMISSION_GRANTED) {
5113            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5114        }
5115
5116        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5117                KeyguardDisableHandler.KEYGUARD_REENABLE, token));
5118    }
5119
5120    /**
5121     * @see android.app.KeyguardManager#exitKeyguardSecurely
5122     */
5123    @Override
5124    public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
5125        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5126            != PackageManager.PERMISSION_GRANTED) {
5127            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5128        }
5129        mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
5130            @Override
5131            public void onKeyguardExitResult(boolean success) {
5132                try {
5133                    callback.onKeyguardExitResult(success);
5134                } catch (RemoteException e) {
5135                    // Client has died, we don't care.
5136                }
5137            }
5138        });
5139    }
5140
5141    @Override
5142    public boolean inKeyguardRestrictedInputMode() {
5143        return mPolicy.inKeyguardRestrictedKeyInputMode();
5144    }
5145
5146    @Override
5147    public boolean isKeyguardLocked() {
5148        return mPolicy.isKeyguardLocked();
5149    }
5150
5151    @Override
5152    public boolean isKeyguardSecure() {
5153        return mPolicy.isKeyguardSecure();
5154    }
5155
5156    @Override
5157    public void dismissKeyguard() {
5158        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5159                != PackageManager.PERMISSION_GRANTED) {
5160            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5161        }
5162        synchronized(mWindowMap) {
5163            mPolicy.dismissKeyguardLw();
5164        }
5165    }
5166
5167    @Override
5168    public void closeSystemDialogs(String reason) {
5169        synchronized(mWindowMap) {
5170            final int numDisplays = mDisplayContents.size();
5171            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5172                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5173                final int numWindows = windows.size();
5174                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5175                    final WindowState w = windows.get(winNdx);
5176                    if (w.mHasSurface) {
5177                        try {
5178                            w.mClient.closeSystemDialogs(reason);
5179                        } catch (RemoteException e) {
5180                        }
5181                    }
5182                }
5183            }
5184        }
5185    }
5186
5187    static float fixScale(float scale) {
5188        if (scale < 0) scale = 0;
5189        else if (scale > 20) scale = 20;
5190        return Math.abs(scale);
5191    }
5192
5193    @Override
5194    public void setAnimationScale(int which, float scale) {
5195        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5196                "setAnimationScale()")) {
5197            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5198        }
5199
5200        scale = fixScale(scale);
5201        switch (which) {
5202            case 0: mWindowAnimationScale = scale; break;
5203            case 1: mTransitionAnimationScale = scale; break;
5204            case 2: mAnimatorDurationScale = scale; break;
5205        }
5206
5207        // Persist setting
5208        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5209    }
5210
5211    @Override
5212    public void setAnimationScales(float[] scales) {
5213        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5214                "setAnimationScale()")) {
5215            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5216        }
5217
5218        if (scales != null) {
5219            if (scales.length >= 1) {
5220                mWindowAnimationScale = fixScale(scales[0]);
5221            }
5222            if (scales.length >= 2) {
5223                mTransitionAnimationScale = fixScale(scales[1]);
5224            }
5225            if (scales.length >= 3) {
5226                setAnimatorDurationScale(fixScale(scales[2]));
5227            }
5228        }
5229
5230        // Persist setting
5231        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5232    }
5233
5234    private void setAnimatorDurationScale(float scale) {
5235        mAnimatorDurationScale = scale;
5236        ValueAnimator.setDurationScale(scale);
5237    }
5238
5239    @Override
5240    public float getAnimationScale(int which) {
5241        switch (which) {
5242            case 0: return mWindowAnimationScale;
5243            case 1: return mTransitionAnimationScale;
5244            case 2: return mAnimatorDurationScale;
5245        }
5246        return 0;
5247    }
5248
5249    @Override
5250    public float[] getAnimationScales() {
5251        return new float[] { mWindowAnimationScale, mTransitionAnimationScale,
5252                mAnimatorDurationScale };
5253    }
5254
5255    @Override
5256    public void registerPointerEventListener(PointerEventListener listener) {
5257        mPointerEventDispatcher.registerInputEventListener(listener);
5258    }
5259
5260    @Override
5261    public void unregisterPointerEventListener(PointerEventListener listener) {
5262        mPointerEventDispatcher.unregisterInputEventListener(listener);
5263    }
5264
5265    // Called by window manager policy. Not exposed externally.
5266    @Override
5267    public int getLidState() {
5268        int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5269                InputManagerService.SW_LID);
5270        if (sw > 0) {
5271            // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5272            return LID_CLOSED;
5273        } else if (sw == 0) {
5274            // Switch state: AKEY_STATE_UP.
5275            return LID_OPEN;
5276        } else {
5277            // Switch state: AKEY_STATE_UNKNOWN.
5278            return LID_ABSENT;
5279        }
5280    }
5281
5282    // Called by window manager policy.  Not exposed externally.
5283    @Override
5284    public void switchKeyboardLayout(int deviceId, int direction) {
5285        mInputManager.switchKeyboardLayout(deviceId, direction);
5286    }
5287
5288    // Called by window manager policy.  Not exposed externally.
5289    @Override
5290    public void shutdown(boolean confirm) {
5291        ShutdownThread.shutdown(mContext, confirm);
5292    }
5293
5294    // Called by window manager policy.  Not exposed externally.
5295    @Override
5296    public void rebootSafeMode(boolean confirm) {
5297        ShutdownThread.rebootSafeMode(mContext, confirm);
5298    }
5299
5300    @Override
5301    public void setInputFilter(IInputFilter filter) {
5302        if (!checkCallingPermission(android.Manifest.permission.FILTER_EVENTS, "setInputFilter()")) {
5303            throw new SecurityException("Requires FILTER_EVENTS permission");
5304        }
5305        mInputManager.setInputFilter(filter);
5306    }
5307
5308    @Override
5309    public void setTouchExplorationEnabled(boolean enabled) {
5310        mPolicy.setTouchExplorationEnabled(enabled);
5311    }
5312
5313    public void setCurrentUser(final int newUserId) {
5314        synchronized (mWindowMap) {
5315            int oldUserId = mCurrentUserId;
5316            mCurrentUserId = newUserId;
5317            mAppTransition.setCurrentUser(newUserId);
5318            mPolicy.setCurrentUserLw(newUserId);
5319
5320            // Hide windows that should not be seen by the new user.
5321            final int numDisplays = mDisplayContents.size();
5322            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5323                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
5324                displayContent.switchUserStacks(newUserId);
5325                rebuildAppWindowListLocked(displayContent);
5326            }
5327            performLayoutAndPlaceSurfacesLocked();
5328        }
5329    }
5330
5331    public void enableScreenAfterBoot() {
5332        synchronized(mWindowMap) {
5333            if (DEBUG_BOOT) {
5334                RuntimeException here = new RuntimeException("here");
5335                here.fillInStackTrace();
5336                Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
5337                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
5338                        + " mShowingBootMessages=" + mShowingBootMessages
5339                        + " mSystemBooted=" + mSystemBooted, here);
5340            }
5341            if (mSystemBooted) {
5342                return;
5343            }
5344            mSystemBooted = true;
5345            hideBootMessagesLocked();
5346            // If the screen still doesn't come up after 30 seconds, give
5347            // up and turn it on.
5348            mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
5349        }
5350
5351        mPolicy.systemBooted();
5352
5353        performEnableScreen();
5354    }
5355
5356    void enableScreenIfNeededLocked() {
5357        if (DEBUG_BOOT) {
5358            RuntimeException here = new RuntimeException("here");
5359            here.fillInStackTrace();
5360            Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
5361                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5362                    + " mShowingBootMessages=" + mShowingBootMessages
5363                    + " mSystemBooted=" + mSystemBooted, here);
5364        }
5365        if (mDisplayEnabled) {
5366            return;
5367        }
5368        if (!mSystemBooted && !mShowingBootMessages) {
5369            return;
5370        }
5371        mH.sendEmptyMessage(H.ENABLE_SCREEN);
5372    }
5373
5374    public void performBootTimeout() {
5375        synchronized(mWindowMap) {
5376            if (mDisplayEnabled) {
5377                return;
5378            }
5379            Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled");
5380            mForceDisplayEnabled = true;
5381        }
5382        performEnableScreen();
5383    }
5384
5385    public void performEnableScreen() {
5386        synchronized(mWindowMap) {
5387            if (DEBUG_BOOT) {
5388                RuntimeException here = new RuntimeException("here");
5389                here.fillInStackTrace();
5390                Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
5391                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
5392                        + " mShowingBootMessages=" + mShowingBootMessages
5393                        + " mSystemBooted=" + mSystemBooted
5394                        + " mOnlyCore=" + mOnlyCore, here);
5395            }
5396            if (mDisplayEnabled) {
5397                return;
5398            }
5399            if (!mSystemBooted && !mShowingBootMessages) {
5400                return;
5401            }
5402
5403            if (!mForceDisplayEnabled) {
5404                // Don't enable the screen until all existing windows
5405                // have been drawn.
5406                boolean haveBootMsg = false;
5407                boolean haveApp = false;
5408                // if the wallpaper service is disabled on the device, we're never going to have
5409                // wallpaper, don't bother waiting for it
5410                boolean haveWallpaper = false;
5411                boolean wallpaperEnabled = mContext.getResources().getBoolean(
5412                        com.android.internal.R.bool.config_enableWallpaperService)
5413                        && !mOnlyCore;
5414                boolean haveKeyguard = true;
5415                // TODO(multidisplay): Expand to all displays?
5416                final WindowList windows = getDefaultWindowListLocked();
5417                final int N = windows.size();
5418                for (int i=0; i<N; i++) {
5419                    WindowState w = windows.get(i);
5420                    if (w.mAttrs.type == TYPE_KEYGUARD) {
5421                        // Only if there is a keyguard attached to the window manager
5422                        // will we consider ourselves as having a keyguard.  If it
5423                        // isn't attached, we don't know if it wants to be shown or
5424                        // hidden.  If it is attached, we will say we have a keyguard
5425                        // if the window doesn't want to be visible, because in that
5426                        // case it explicitly doesn't want to be shown so we should
5427                        // not delay turning the screen on for it.
5428                        boolean vis = w.mViewVisibility == View.VISIBLE
5429                                && w.mPolicyVisibility;
5430                        haveKeyguard = !vis;
5431                    }
5432                    if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
5433                        return;
5434                    }
5435                    if (w.isDrawnLw()) {
5436                        if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
5437                            haveBootMsg = true;
5438                        } else if (w.mAttrs.type == TYPE_APPLICATION) {
5439                            haveApp = true;
5440                        } else if (w.mAttrs.type == TYPE_WALLPAPER) {
5441                            haveWallpaper = true;
5442                        } else if (w.mAttrs.type == TYPE_KEYGUARD) {
5443                            haveKeyguard = true;
5444                        }
5445                    }
5446                }
5447
5448                if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
5449                    Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
5450                            + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
5451                            + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
5452                            + " haveKeyguard=" + haveKeyguard);
5453                }
5454
5455                // If we are turning on the screen to show the boot message,
5456                // don't do it until the boot message is actually displayed.
5457                if (!mSystemBooted && !haveBootMsg) {
5458                    return;
5459                }
5460
5461                // If we are turning on the screen after the boot is completed
5462                // normally, don't do so until we have the application and
5463                // wallpaper.
5464                if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
5465                        (wallpaperEnabled && !haveWallpaper))) {
5466                    return;
5467                }
5468            }
5469
5470            mDisplayEnabled = true;
5471            if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
5472            if (false) {
5473                StringWriter sw = new StringWriter();
5474                PrintWriter pw = new FastPrintWriter(sw, false, 1024);
5475                this.dump(null, pw, null);
5476                pw.flush();
5477                Slog.i(TAG, sw.toString());
5478            }
5479            try {
5480                IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
5481                if (surfaceFlinger != null) {
5482                    //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
5483                    Parcel data = Parcel.obtain();
5484                    data.writeInterfaceToken("android.ui.ISurfaceComposer");
5485                    surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
5486                                            data, null, 0);
5487                    data.recycle();
5488                }
5489            } catch (RemoteException ex) {
5490                Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
5491            }
5492
5493            // Enable input dispatch.
5494            mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
5495        }
5496
5497        mPolicy.enableScreenAfterBoot();
5498
5499        // Make sure the last requested orientation has been applied.
5500        updateRotationUnchecked(false, false);
5501    }
5502
5503    public void showBootMessage(final CharSequence msg, final boolean always) {
5504        boolean first = false;
5505        synchronized(mWindowMap) {
5506            if (DEBUG_BOOT) {
5507                RuntimeException here = new RuntimeException("here");
5508                here.fillInStackTrace();
5509                Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always
5510                        + " mAllowBootMessages=" + mAllowBootMessages
5511                        + " mShowingBootMessages=" + mShowingBootMessages
5512                        + " mSystemBooted=" + mSystemBooted, here);
5513            }
5514            if (!mAllowBootMessages) {
5515                return;
5516            }
5517            if (!mShowingBootMessages) {
5518                if (!always) {
5519                    return;
5520                }
5521                first = true;
5522            }
5523            if (mSystemBooted) {
5524                return;
5525            }
5526            mShowingBootMessages = true;
5527            mPolicy.showBootMessage(msg, always);
5528        }
5529        if (first) {
5530            performEnableScreen();
5531        }
5532    }
5533
5534    public void hideBootMessagesLocked() {
5535        if (DEBUG_BOOT) {
5536            RuntimeException here = new RuntimeException("here");
5537            here.fillInStackTrace();
5538            Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
5539                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5540                    + " mShowingBootMessages=" + mShowingBootMessages
5541                    + " mSystemBooted=" + mSystemBooted, here);
5542        }
5543        if (mShowingBootMessages) {
5544            mShowingBootMessages = false;
5545            mPolicy.hideBootMessages();
5546        }
5547    }
5548
5549    @Override
5550    public void setInTouchMode(boolean mode) {
5551        synchronized(mWindowMap) {
5552            mInTouchMode = mode;
5553        }
5554    }
5555
5556    public void showCircularDisplayMaskIfNeeded() {
5557        // we're fullscreen and not hosted in an ActivityView
5558        if (mContext.getResources().getBoolean(
5559                com.android.internal.R.bool.config_windowIsRound)) {
5560            mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK));
5561        }
5562    }
5563
5564    public void showCircularMask() {
5565        synchronized(mWindowMap) {
5566
5567            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5568                    ">>> OPEN TRANSACTION showDisplayMask");
5569            SurfaceControl.openTransaction();
5570            try {
5571                // TODO(multi-display): support multiple displays
5572                if (mCircularDisplayMask == null) {
5573                    mCircularDisplayMask = new CircularDisplayMask(
5574                            getDefaultDisplayContentLocked().getDisplay(),
5575                            mFxSession,
5576                            mPolicy.windowTypeToLayerLw(
5577                                    WindowManager.LayoutParams.TYPE_POINTER)
5578                                    * TYPE_LAYER_MULTIPLIER + 10);
5579                }
5580                mCircularDisplayMask.setVisibility(true);
5581            } finally {
5582                SurfaceControl.closeTransaction();
5583                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5584                        "<<< CLOSE TRANSACTION showDisplayMask");
5585            }
5586        }
5587    }
5588
5589    // TODO: more accounting of which pid(s) turned it on, keep count,
5590    // only allow disables from pids which have count on, etc.
5591    @Override
5592    public void showStrictModeViolation(boolean on) {
5593        int pid = Binder.getCallingPid();
5594        mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
5595    }
5596
5597    private void showStrictModeViolation(int arg, int pid) {
5598        final boolean on = arg != 0;
5599        synchronized(mWindowMap) {
5600            // Ignoring requests to enable the red border from clients
5601            // which aren't on screen.  (e.g. Broadcast Receivers in
5602            // the background..)
5603            if (on) {
5604                boolean isVisible = false;
5605                final int numDisplays = mDisplayContents.size();
5606                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5607                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5608                    final int numWindows = windows.size();
5609                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5610                        final WindowState ws = windows.get(winNdx);
5611                        if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
5612                            isVisible = true;
5613                            break;
5614                        }
5615                    }
5616                }
5617                if (!isVisible) {
5618                    return;
5619                }
5620            }
5621
5622            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5623                    ">>> OPEN TRANSACTION showStrictModeViolation");
5624            SurfaceControl.openTransaction();
5625            try {
5626                // TODO(multi-display): support multiple displays
5627                if (mStrictModeFlash == null) {
5628                    mStrictModeFlash = new StrictModeFlash(
5629                            getDefaultDisplayContentLocked().getDisplay(), mFxSession);
5630                }
5631                mStrictModeFlash.setVisibility(on);
5632            } finally {
5633                SurfaceControl.closeTransaction();
5634                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5635                        "<<< CLOSE TRANSACTION showStrictModeViolation");
5636            }
5637        }
5638    }
5639
5640    @Override
5641    public void setStrictModeVisualIndicatorPreference(String value) {
5642        SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
5643    }
5644
5645    /**
5646     * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
5647     * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
5648     * of the target image.
5649     *
5650     * @param displayId the Display to take a screenshot of.
5651     * @param width the width of the target bitmap
5652     * @param height the height of the target bitmap
5653     * @param force565 if true the returned bitmap will be RGB_565, otherwise it
5654     *                 will be the same config as the surface
5655     */
5656    @Override
5657    public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
5658            int height, boolean force565) {
5659        if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5660                "screenshotApplications()")) {
5661            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
5662        }
5663
5664        Bitmap rawss = null;
5665
5666        int maxLayer = 0;
5667        final Rect frame = new Rect();
5668
5669        float scale = 0;
5670        int dw, dh;
5671        int rot = Surface.ROTATION_0;
5672
5673        boolean screenshotReady;
5674        int minLayer;
5675        if (appToken == null) {
5676            screenshotReady = true;
5677            minLayer = 0;
5678        } else {
5679            screenshotReady = false;
5680            minLayer = Integer.MAX_VALUE;
5681        }
5682
5683        int retryCount = 0;
5684        WindowState appWin = null;
5685
5686        do {
5687            if (retryCount++ > 0) {
5688                try {
5689                    Thread.sleep(100);
5690                } catch (InterruptedException e) {
5691                }
5692            }
5693            synchronized(mWindowMap) {
5694                final DisplayContent displayContent = getDisplayContentLocked(displayId);
5695                if (displayContent == null) {
5696                    return null;
5697                }
5698                final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5699                dw = displayInfo.logicalWidth;
5700                dh = displayInfo.logicalHeight;
5701
5702                int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION)
5703                        * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
5704                aboveAppLayer += TYPE_LAYER_MULTIPLIER;
5705
5706                boolean isImeTarget = mInputMethodTarget != null
5707                        && mInputMethodTarget.mAppToken != null
5708                        && mInputMethodTarget.mAppToken.appToken != null
5709                        && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
5710
5711                // Figure out the part of the screen that is actually the app.
5712                boolean including = false;
5713                appWin = null;
5714                final WindowList windows = displayContent.getWindowList();
5715                final Rect stackBounds = new Rect();
5716                for (int i = windows.size() - 1; i >= 0; i--) {
5717                    WindowState ws = windows.get(i);
5718                    if (!ws.mHasSurface) {
5719                        continue;
5720                    }
5721                    if (ws.mLayer >= aboveAppLayer) {
5722                        continue;
5723                    }
5724                    // When we will skip windows: when we are not including
5725                    // ones behind a window we didn't skip, and we are actually
5726                    // taking a screenshot of a specific app.
5727                    if (!including && appToken != null) {
5728                        // Also, we can possibly skip this window if it is not
5729                        // an IME target or the application for the screenshot
5730                        // is not the current IME target.
5731                        if (!ws.mIsImWindow || !isImeTarget) {
5732                            // And finally, this window is of no interest if it
5733                            // is not associated with the screenshot app.
5734                            if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
5735                                continue;
5736                            }
5737                            appWin = ws;
5738                            ws.getStackBounds(stackBounds);
5739                        }
5740                    }
5741
5742                    // We keep on including windows until we go past a full-screen
5743                    // window.
5744                    including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh);
5745
5746                    final WindowStateAnimator winAnim = ws.mWinAnimator;
5747                    if (maxLayer < winAnim.mSurfaceLayer) {
5748                        maxLayer = winAnim.mSurfaceLayer;
5749                    }
5750                    if (minLayer > winAnim.mSurfaceLayer) {
5751                        minLayer = winAnim.mSurfaceLayer;
5752                    }
5753
5754                    // Don't include wallpaper in bounds calculation
5755                    if (!ws.mIsWallpaper) {
5756                        final Rect wf = ws.mFrame;
5757                        final Rect cr = ws.mContentInsets;
5758                        int left = wf.left + cr.left;
5759                        int top = wf.top + cr.top;
5760                        int right = wf.right - cr.right;
5761                        int bottom = wf.bottom - cr.bottom;
5762                        frame.union(left, top, right, bottom);
5763                        frame.intersect(stackBounds);
5764                    }
5765
5766                    if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
5767                            ws.isDisplayedLw()) {
5768                        screenshotReady = true;
5769                    }
5770                }
5771
5772                if (appToken != null && appWin == null) {
5773                    // Can't find a window to snapshot.
5774                    if (DEBUG_SCREENSHOT) Slog.i(TAG,
5775                            "Screenshot: Couldn't find a surface matching " + appToken);
5776                    return null;
5777                }
5778                if (!screenshotReady) {
5779                    // Delay and hope that window gets drawn.
5780                    if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken
5781                            + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState);
5782                    continue;
5783                }
5784
5785                // Constrain frame to the screen size.
5786                frame.intersect(0, 0, dw, dh);
5787
5788                if (frame.isEmpty() || maxLayer == 0) {
5789                    if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
5790                            + ": returning null frame=" + frame.toShortString() + " maxLayer="
5791                            + maxLayer);
5792                    return null;
5793                }
5794
5795                // The screenshot API does not apply the current screen rotation.
5796                rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
5797                int fw = frame.width();
5798                int fh = frame.height();
5799
5800                // Constrain thumbnail to smaller of screen width or height. Assumes aspect
5801                // of thumbnail is the same as the screen (in landscape) or square.
5802                scale = Math.max(width / (float) fw, height / (float) fh);
5803                /*
5804                float targetWidthScale = width / (float) fw;
5805                float targetHeightScale = height / (float) fh;
5806                if (fw <= fh) {
5807                    scale = targetWidthScale;
5808                    // If aspect of thumbnail is the same as the screen (in landscape),
5809                    // select the slightly larger value so we fill the entire bitmap
5810                    if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) {
5811                        scale = targetHeightScale;
5812                    }
5813                } else {
5814                    scale = targetHeightScale;
5815                    // If aspect of thumbnail is the same as the screen (in landscape),
5816                    // select the slightly larger value so we fill the entire bitmap
5817                    if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) {
5818                        scale = targetWidthScale;
5819                    }
5820                }
5821                */
5822
5823                // The screen shot will contain the entire screen.
5824                dw = (int)(dw*scale);
5825                dh = (int)(dh*scale);
5826                if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
5827                    int tmp = dw;
5828                    dw = dh;
5829                    dh = tmp;
5830                    rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
5831                }
5832                if (DEBUG_SCREENSHOT) {
5833                    Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
5834                            + maxLayer + " appToken=" + appToken);
5835                    for (int i = 0; i < windows.size(); i++) {
5836                        WindowState win = windows.get(i);
5837                        Slog.i(TAG, win + ": " + win.mLayer
5838                                + " animLayer=" + win.mWinAnimator.mAnimLayer
5839                                + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
5840                    }
5841                }
5842                rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer);
5843            }
5844        } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES);
5845        if (retryCount > MAX_SCREENSHOT_RETRIES)  Slog.i(TAG, "Screenshot max retries " +
5846                retryCount + " of " + appToken + " appWin=" + (appWin == null ?
5847                        "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState)));
5848
5849        if (rawss == null) {
5850            Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
5851                    + ") to layer " + maxLayer);
5852            return null;
5853        }
5854
5855        Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig());
5856        frame.scale(scale);
5857        Matrix matrix = new Matrix();
5858        ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
5859        // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left
5860        matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top));
5861        Canvas canvas = new Canvas(bm);
5862        canvas.drawColor(0xFF000000);
5863        canvas.drawBitmap(rawss, matrix, null);
5864        canvas.setBitmap(null);
5865
5866        if (DEBUG_SCREENSHOT) {
5867            // TEST IF IT's ALL BLACK
5868            int[] buffer = new int[bm.getWidth() * bm.getHeight()];
5869            bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
5870            boolean allBlack = true;
5871            final int firstColor = buffer[0];
5872            for (int i = 0; i < buffer.length; i++) {
5873                if (buffer[i] != firstColor) {
5874                    allBlack = false;
5875                    break;
5876                }
5877            }
5878            if (allBlack) {
5879                Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" +
5880                        Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
5881                        (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") +
5882                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
5883            }
5884        }
5885
5886        rawss.recycle();
5887        return bm;
5888    }
5889
5890    /**
5891     * Freeze rotation changes.  (Enable "rotation lock".)
5892     * Persists across reboots.
5893     * @param rotation The desired rotation to freeze to, or -1 to use the
5894     * current rotation.
5895     */
5896    @Override
5897    public void freezeRotation(int rotation) {
5898        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5899                "freezeRotation()")) {
5900            throw new SecurityException("Requires SET_ORIENTATION permission");
5901        }
5902        if (rotation < -1 || rotation > Surface.ROTATION_270) {
5903            throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
5904                    + "rotation constant.");
5905        }
5906
5907        if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation);
5908
5909        long origId = Binder.clearCallingIdentity();
5910        try {
5911            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
5912                    rotation == -1 ? mRotation : rotation);
5913        } finally {
5914            Binder.restoreCallingIdentity(origId);
5915        }
5916
5917        updateRotationUnchecked(false, false);
5918    }
5919
5920    /**
5921     * Thaw rotation changes.  (Disable "rotation lock".)
5922     * Persists across reboots.
5923     */
5924    @Override
5925    public void thawRotation() {
5926        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5927                "thawRotation()")) {
5928            throw new SecurityException("Requires SET_ORIENTATION permission");
5929        }
5930
5931        if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
5932
5933        long origId = Binder.clearCallingIdentity();
5934        try {
5935            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
5936                    777); // rot not used
5937        } finally {
5938            Binder.restoreCallingIdentity(origId);
5939        }
5940
5941        updateRotationUnchecked(false, false);
5942    }
5943
5944    /**
5945     * Recalculate the current rotation.
5946     *
5947     * Called by the window manager policy whenever the state of the system changes
5948     * such that the current rotation might need to be updated, such as when the
5949     * device is docked or rotated into a new posture.
5950     */
5951    @Override
5952    public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
5953        updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
5954    }
5955
5956    /**
5957     * Temporarily pauses rotation changes until resumed.
5958     *
5959     * This can be used to prevent rotation changes from occurring while the user is
5960     * performing certain operations, such as drag and drop.
5961     *
5962     * This call nests and must be matched by an equal number of calls to
5963     * {@link #resumeRotationLocked}.
5964     */
5965    void pauseRotationLocked() {
5966        mDeferredRotationPauseCount += 1;
5967    }
5968
5969    /**
5970     * Resumes normal rotation changes after being paused.
5971     */
5972    void resumeRotationLocked() {
5973        if (mDeferredRotationPauseCount > 0) {
5974            mDeferredRotationPauseCount -= 1;
5975            if (mDeferredRotationPauseCount == 0) {
5976                boolean changed = updateRotationUncheckedLocked(false);
5977                if (changed) {
5978                    mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
5979                }
5980            }
5981        }
5982    }
5983
5984    public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
5985        if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
5986                   + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
5987
5988        long origId = Binder.clearCallingIdentity();
5989        boolean changed;
5990        synchronized(mWindowMap) {
5991            changed = updateRotationUncheckedLocked(false);
5992            if (!changed || forceRelayout) {
5993                getDefaultDisplayContentLocked().layoutNeeded = true;
5994                performLayoutAndPlaceSurfacesLocked();
5995            }
5996        }
5997
5998        if (changed || alwaysSendConfiguration) {
5999            sendNewConfiguration();
6000        }
6001
6002        Binder.restoreCallingIdentity(origId);
6003    }
6004
6005    // TODO(multidisplay): Rotate any display?
6006    /**
6007     * Updates the current rotation.
6008     *
6009     * Returns true if the rotation has been changed.  In this case YOU
6010     * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
6011     */
6012    public boolean updateRotationUncheckedLocked(boolean inTransaction) {
6013        if (mDeferredRotationPauseCount > 0) {
6014            // Rotation updates have been paused temporarily.  Defer the update until
6015            // updates have been resumed.
6016            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused.");
6017            return false;
6018        }
6019
6020        ScreenRotationAnimation screenRotationAnimation =
6021                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6022        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
6023            // Rotation updates cannot be performed while the previous rotation change
6024            // animation is still in progress.  Skip this update.  We will try updating
6025            // again after the animation is finished and the display is unfrozen.
6026            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress.");
6027            return false;
6028        }
6029
6030        if (!mDisplayEnabled) {
6031            // No point choosing a rotation if the display is not enabled.
6032            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled.");
6033            return false;
6034        }
6035
6036        // TODO: Implement forced rotation changes.
6037        //       Set mAltOrientation to indicate that the application is receiving
6038        //       an orientation that has different metrics than it expected.
6039        //       eg. Portrait instead of Landscape.
6040
6041        int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
6042        boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
6043                mForcedAppOrientation, rotation);
6044
6045        if (DEBUG_ORIENTATION) {
6046            Slog.v(TAG, "Application requested orientation "
6047                    + mForcedAppOrientation + ", got rotation " + rotation
6048                    + " which has " + (altOrientation ? "incompatible" : "compatible")
6049                    + " metrics");
6050        }
6051
6052        if (mRotation == rotation && mAltOrientation == altOrientation) {
6053            // No change.
6054            return false;
6055        }
6056
6057        if (DEBUG_ORIENTATION) {
6058            Slog.v(TAG,
6059                "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
6060                + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
6061                + ", forceApp=" + mForcedAppOrientation);
6062        }
6063
6064        mRotation = rotation;
6065        mAltOrientation = altOrientation;
6066        mPolicy.setRotationLw(mRotation);
6067
6068        mWindowsFreezingScreen = true;
6069        mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
6070        mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
6071        mWaitingForConfig = true;
6072        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6073        displayContent.layoutNeeded = true;
6074        final int[] anim = new int[2];
6075        if (displayContent.isDimming()) {
6076            anim[0] = anim[1] = 0;
6077        } else {
6078            mPolicy.selectRotationAnimationLw(anim);
6079        }
6080        startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
6081        // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
6082        screenRotationAnimation =
6083                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6084
6085        // We need to update our screen size information to match the new
6086        // rotation.  Note that this is redundant with the later call to
6087        // sendNewConfiguration() that must be called after this function
6088        // returns...  however we need to do the screen size part of that
6089        // before then so we have the correct size to use when initializing
6090        // the rotation animation for the new rotation.
6091        computeScreenConfigurationLocked(null);
6092
6093        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6094        if (!inTransaction) {
6095            if (SHOW_TRANSACTIONS) {
6096                Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");
6097            }
6098            SurfaceControl.openTransaction();
6099        }
6100        try {
6101            // NOTE: We disable the rotation in the emulator because
6102            //       it doesn't support hardware OpenGL emulation yet.
6103            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
6104                    && screenRotationAnimation.hasScreenshot()) {
6105                if (screenRotationAnimation.setRotationInTransaction(
6106                        rotation, mFxSession,
6107                        MAX_ANIMATION_DURATION, mTransitionAnimationScale,
6108                        displayInfo.logicalWidth, displayInfo.logicalHeight)) {
6109                    scheduleAnimationLocked();
6110                }
6111            }
6112
6113            mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
6114        } finally {
6115            if (!inTransaction) {
6116                SurfaceControl.closeTransaction();
6117                if (SHOW_LIGHT_TRANSACTIONS) {
6118                    Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");
6119                }
6120            }
6121        }
6122
6123        final WindowList windows = displayContent.getWindowList();
6124        for (int i = windows.size() - 1; i >= 0; i--) {
6125            WindowState w = windows.get(i);
6126            if (w.mHasSurface) {
6127                if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
6128                w.mOrientationChanging = true;
6129                mInnerFields.mOrientationChangeComplete = false;
6130            }
6131            w.mLastFreezeDuration = 0;
6132        }
6133
6134        for (int i=mRotationWatchers.size()-1; i>=0; i--) {
6135            try {
6136                mRotationWatchers.get(i).watcher.onRotationChanged(rotation);
6137            } catch (RemoteException e) {
6138            }
6139        }
6140
6141        //TODO (multidisplay): Magnification is supported only for the default display.
6142        if (mDisplayMagnifier != null
6143                && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
6144            mDisplayMagnifier.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation);
6145        }
6146
6147        return true;
6148    }
6149
6150    @Override
6151    public int getRotation() {
6152        return mRotation;
6153    }
6154
6155    @Override
6156    public boolean isRotationFrozen() {
6157        return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
6158    }
6159
6160    @Override
6161    public int watchRotation(IRotationWatcher watcher) {
6162        final IBinder watcherBinder = watcher.asBinder();
6163        IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
6164            @Override
6165            public void binderDied() {
6166                synchronized (mWindowMap) {
6167                    for (int i=0; i<mRotationWatchers.size(); i++) {
6168                        if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) {
6169                            RotationWatcher removed = mRotationWatchers.remove(i);
6170                            if (removed != null) {
6171                                removed.watcher.asBinder().unlinkToDeath(this, 0);
6172                            }
6173                            i--;
6174                        }
6175                    }
6176                }
6177            }
6178        };
6179
6180        synchronized (mWindowMap) {
6181            try {
6182                watcher.asBinder().linkToDeath(dr, 0);
6183                mRotationWatchers.add(new RotationWatcher(watcher, dr));
6184            } catch (RemoteException e) {
6185                // Client died, no cleanup needed.
6186            }
6187
6188            return mRotation;
6189        }
6190    }
6191
6192    @Override
6193    public void removeRotationWatcher(IRotationWatcher watcher) {
6194        final IBinder watcherBinder = watcher.asBinder();
6195        synchronized (mWindowMap) {
6196            for (int i=0; i<mRotationWatchers.size(); i++) {
6197                RotationWatcher rotationWatcher = mRotationWatchers.get(i);
6198                if (watcherBinder == rotationWatcher.watcher.asBinder()) {
6199                    RotationWatcher removed = mRotationWatchers.remove(i);
6200                    if (removed != null) {
6201                        removed.watcher.asBinder().unlinkToDeath(removed.dr, 0);
6202                        i--;
6203                    }
6204                }
6205            }
6206        }
6207    }
6208
6209    /**
6210     * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
6211     * theme attribute) on devices that feature a physical options menu key attempt to position
6212     * their menu panel window along the edge of the screen nearest the physical menu key.
6213     * This lowers the travel distance between invoking the menu panel and selecting
6214     * a menu option.
6215     *
6216     * This method helps control where that menu is placed. Its current implementation makes
6217     * assumptions about the menu key and its relationship to the screen based on whether
6218     * the device's natural orientation is portrait (width < height) or landscape.
6219     *
6220     * The menu key is assumed to be located along the bottom edge of natural-portrait
6221     * devices and along the right edge of natural-landscape devices. If these assumptions
6222     * do not hold for the target device, this method should be changed to reflect that.
6223     *
6224     * @return A {@link Gravity} value for placing the options menu window
6225     */
6226    @Override
6227    public int getPreferredOptionsPanelGravity() {
6228        synchronized (mWindowMap) {
6229            final int rotation = getRotation();
6230
6231            // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
6232            final DisplayContent displayContent = getDefaultDisplayContentLocked();
6233            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
6234                // On devices with a natural orientation of portrait
6235                switch (rotation) {
6236                    default:
6237                    case Surface.ROTATION_0:
6238                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6239                    case Surface.ROTATION_90:
6240                        return Gravity.RIGHT | Gravity.BOTTOM;
6241                    case Surface.ROTATION_180:
6242                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6243                    case Surface.ROTATION_270:
6244                        return Gravity.START | Gravity.BOTTOM;
6245                }
6246            }
6247
6248            // On devices with a natural orientation of landscape
6249            switch (rotation) {
6250                default:
6251                case Surface.ROTATION_0:
6252                    return Gravity.RIGHT | Gravity.BOTTOM;
6253                case Surface.ROTATION_90:
6254                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6255                case Surface.ROTATION_180:
6256                    return Gravity.START | Gravity.BOTTOM;
6257                case Surface.ROTATION_270:
6258                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6259            }
6260        }
6261    }
6262
6263    /**
6264     * Starts the view server on the specified port.
6265     *
6266     * @param port The port to listener to.
6267     *
6268     * @return True if the server was successfully started, false otherwise.
6269     *
6270     * @see com.android.server.wm.ViewServer
6271     * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
6272     */
6273    @Override
6274    public boolean startViewServer(int port) {
6275        if (isSystemSecure()) {
6276            return false;
6277        }
6278
6279        if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
6280            return false;
6281        }
6282
6283        if (port < 1024) {
6284            return false;
6285        }
6286
6287        if (mViewServer != null) {
6288            if (!mViewServer.isRunning()) {
6289                try {
6290                    return mViewServer.start();
6291                } catch (IOException e) {
6292                    Slog.w(TAG, "View server did not start");
6293                }
6294            }
6295            return false;
6296        }
6297
6298        try {
6299            mViewServer = new ViewServer(this, port);
6300            return mViewServer.start();
6301        } catch (IOException e) {
6302            Slog.w(TAG, "View server did not start");
6303        }
6304        return false;
6305    }
6306
6307    private boolean isSystemSecure() {
6308        return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
6309                "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
6310    }
6311
6312    /**
6313     * Stops the view server if it exists.
6314     *
6315     * @return True if the server stopped, false if it wasn't started or
6316     *         couldn't be stopped.
6317     *
6318     * @see com.android.server.wm.ViewServer
6319     */
6320    @Override
6321    public boolean stopViewServer() {
6322        if (isSystemSecure()) {
6323            return false;
6324        }
6325
6326        if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
6327            return false;
6328        }
6329
6330        if (mViewServer != null) {
6331            return mViewServer.stop();
6332        }
6333        return false;
6334    }
6335
6336    /**
6337     * Indicates whether the view server is running.
6338     *
6339     * @return True if the server is running, false otherwise.
6340     *
6341     * @see com.android.server.wm.ViewServer
6342     */
6343    @Override
6344    public boolean isViewServerRunning() {
6345        if (isSystemSecure()) {
6346            return false;
6347        }
6348
6349        if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
6350            return false;
6351        }
6352
6353        return mViewServer != null && mViewServer.isRunning();
6354    }
6355
6356    /**
6357     * Lists all availble windows in the system. The listing is written in the
6358     * specified Socket's output stream with the following syntax:
6359     * windowHashCodeInHexadecimal windowName
6360     * Each line of the ouput represents a different window.
6361     *
6362     * @param client The remote client to send the listing to.
6363     * @return False if an error occured, true otherwise.
6364     */
6365    boolean viewServerListWindows(Socket client) {
6366        if (isSystemSecure()) {
6367            return false;
6368        }
6369
6370        boolean result = true;
6371
6372        WindowList windows = new WindowList();
6373        synchronized (mWindowMap) {
6374            //noinspection unchecked
6375            final int numDisplays = mDisplayContents.size();
6376            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6377                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
6378                windows.addAll(displayContent.getWindowList());
6379            }
6380        }
6381
6382        BufferedWriter out = null;
6383
6384        // Any uncaught exception will crash the system process
6385        try {
6386            OutputStream clientStream = client.getOutputStream();
6387            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6388
6389            final int count = windows.size();
6390            for (int i = 0; i < count; i++) {
6391                final WindowState w = windows.get(i);
6392                out.write(Integer.toHexString(System.identityHashCode(w)));
6393                out.write(' ');
6394                out.append(w.mAttrs.getTitle());
6395                out.write('\n');
6396            }
6397
6398            out.write("DONE.\n");
6399            out.flush();
6400        } catch (Exception e) {
6401            result = false;
6402        } finally {
6403            if (out != null) {
6404                try {
6405                    out.close();
6406                } catch (IOException e) {
6407                    result = false;
6408                }
6409            }
6410        }
6411
6412        return result;
6413    }
6414
6415    // TODO(multidisplay): Extend to multiple displays.
6416    /**
6417     * Returns the focused window in the following format:
6418     * windowHashCodeInHexadecimal windowName
6419     *
6420     * @param client The remote client to send the listing to.
6421     * @return False if an error occurred, true otherwise.
6422     */
6423    boolean viewServerGetFocusedWindow(Socket client) {
6424        if (isSystemSecure()) {
6425            return false;
6426        }
6427
6428        boolean result = true;
6429
6430        WindowState focusedWindow = getFocusedWindow();
6431
6432        BufferedWriter out = null;
6433
6434        // Any uncaught exception will crash the system process
6435        try {
6436            OutputStream clientStream = client.getOutputStream();
6437            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6438
6439            if(focusedWindow != null) {
6440                out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
6441                out.write(' ');
6442                out.append(focusedWindow.mAttrs.getTitle());
6443            }
6444            out.write('\n');
6445            out.flush();
6446        } catch (Exception e) {
6447            result = false;
6448        } finally {
6449            if (out != null) {
6450                try {
6451                    out.close();
6452                } catch (IOException e) {
6453                    result = false;
6454                }
6455            }
6456        }
6457
6458        return result;
6459    }
6460
6461    /**
6462     * Sends a command to a target window. The result of the command, if any, will be
6463     * written in the output stream of the specified socket.
6464     *
6465     * The parameters must follow this syntax:
6466     * windowHashcode extra
6467     *
6468     * Where XX is the length in characeters of the windowTitle.
6469     *
6470     * The first parameter is the target window. The window with the specified hashcode
6471     * will be the target. If no target can be found, nothing happens. The extra parameters
6472     * will be delivered to the target window and as parameters to the command itself.
6473     *
6474     * @param client The remote client to sent the result, if any, to.
6475     * @param command The command to execute.
6476     * @param parameters The command parameters.
6477     *
6478     * @return True if the command was successfully delivered, false otherwise. This does
6479     *         not indicate whether the command itself was successful.
6480     */
6481    boolean viewServerWindowCommand(Socket client, String command, String parameters) {
6482        if (isSystemSecure()) {
6483            return false;
6484        }
6485
6486        boolean success = true;
6487        Parcel data = null;
6488        Parcel reply = null;
6489
6490        BufferedWriter out = null;
6491
6492        // Any uncaught exception will crash the system process
6493        try {
6494            // Find the hashcode of the window
6495            int index = parameters.indexOf(' ');
6496            if (index == -1) {
6497                index = parameters.length();
6498            }
6499            final String code = parameters.substring(0, index);
6500            int hashCode = (int) Long.parseLong(code, 16);
6501
6502            // Extract the command's parameter after the window description
6503            if (index < parameters.length()) {
6504                parameters = parameters.substring(index + 1);
6505            } else {
6506                parameters = "";
6507            }
6508
6509            final WindowState window = findWindow(hashCode);
6510            if (window == null) {
6511                return false;
6512            }
6513
6514            data = Parcel.obtain();
6515            data.writeInterfaceToken("android.view.IWindow");
6516            data.writeString(command);
6517            data.writeString(parameters);
6518            data.writeInt(1);
6519            ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
6520
6521            reply = Parcel.obtain();
6522
6523            final IBinder binder = window.mClient.asBinder();
6524            // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
6525            binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
6526
6527            reply.readException();
6528
6529            if (!client.isOutputShutdown()) {
6530                out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
6531                out.write("DONE\n");
6532                out.flush();
6533            }
6534
6535        } catch (Exception e) {
6536            Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
6537            success = false;
6538        } finally {
6539            if (data != null) {
6540                data.recycle();
6541            }
6542            if (reply != null) {
6543                reply.recycle();
6544            }
6545            if (out != null) {
6546                try {
6547                    out.close();
6548                } catch (IOException e) {
6549
6550                }
6551            }
6552        }
6553
6554        return success;
6555    }
6556
6557    public void addWindowChangeListener(WindowChangeListener listener) {
6558        synchronized(mWindowMap) {
6559            mWindowChangeListeners.add(listener);
6560        }
6561    }
6562
6563    public void removeWindowChangeListener(WindowChangeListener listener) {
6564        synchronized(mWindowMap) {
6565            mWindowChangeListeners.remove(listener);
6566        }
6567    }
6568
6569    private void notifyWindowsChanged() {
6570        WindowChangeListener[] windowChangeListeners;
6571        synchronized(mWindowMap) {
6572            if(mWindowChangeListeners.isEmpty()) {
6573                return;
6574            }
6575            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6576            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6577        }
6578        int N = windowChangeListeners.length;
6579        for(int i = 0; i < N; i++) {
6580            windowChangeListeners[i].windowsChanged();
6581        }
6582    }
6583
6584    private void notifyFocusChanged() {
6585        WindowChangeListener[] windowChangeListeners;
6586        synchronized(mWindowMap) {
6587            if(mWindowChangeListeners.isEmpty()) {
6588                return;
6589            }
6590            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6591            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6592        }
6593        int N = windowChangeListeners.length;
6594        for(int i = 0; i < N; i++) {
6595            windowChangeListeners[i].focusChanged();
6596        }
6597    }
6598
6599    private WindowState findWindow(int hashCode) {
6600        if (hashCode == -1) {
6601            // TODO(multidisplay): Extend to multiple displays.
6602            return getFocusedWindow();
6603        }
6604
6605        synchronized (mWindowMap) {
6606            final int numDisplays = mDisplayContents.size();
6607            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6608                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
6609                final int numWindows = windows.size();
6610                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
6611                    final WindowState w = windows.get(winNdx);
6612                    if (System.identityHashCode(w) == hashCode) {
6613                        return w;
6614                    }
6615                }
6616            }
6617        }
6618
6619        return null;
6620    }
6621
6622    /*
6623     * Instruct the Activity Manager to fetch the current configuration and broadcast
6624     * that to config-changed listeners if appropriate.
6625     */
6626    void sendNewConfiguration() {
6627        try {
6628            mActivityManager.updateConfiguration(null);
6629        } catch (RemoteException e) {
6630        }
6631    }
6632
6633    public Configuration computeNewConfiguration() {
6634        synchronized (mWindowMap) {
6635            Configuration config = computeNewConfigurationLocked();
6636            if (config == null && mWaitingForConfig) {
6637                // Nothing changed but we are waiting for something... stop that!
6638                mWaitingForConfig = false;
6639                mLastFinishedFreezeSource = "new-config";
6640                performLayoutAndPlaceSurfacesLocked();
6641            }
6642            return config;
6643        }
6644    }
6645
6646    Configuration computeNewConfigurationLocked() {
6647        Configuration config = new Configuration();
6648        config.fontScale = 0;
6649        if (!computeScreenConfigurationLocked(config)) {
6650            return null;
6651        }
6652        return config;
6653    }
6654
6655    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
6656        // TODO: Multidisplay: for now only use with default display.
6657        final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
6658        if (width < displayInfo.smallestNominalAppWidth) {
6659            displayInfo.smallestNominalAppWidth = width;
6660        }
6661        if (width > displayInfo.largestNominalAppWidth) {
6662            displayInfo.largestNominalAppWidth = width;
6663        }
6664        final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
6665        if (height < displayInfo.smallestNominalAppHeight) {
6666            displayInfo.smallestNominalAppHeight = height;
6667        }
6668        if (height > displayInfo.largestNominalAppHeight) {
6669            displayInfo.largestNominalAppHeight = height;
6670        }
6671    }
6672
6673    private int reduceConfigLayout(int curLayout, int rotation, float density,
6674            int dw, int dh) {
6675        // TODO: Multidisplay: for now only use with default display.
6676        // Get the app screen size at this rotation.
6677        int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6678        int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6679
6680        // Compute the screen layout size class for this rotation.
6681        int longSize = w;
6682        int shortSize = h;
6683        if (longSize < shortSize) {
6684            int tmp = longSize;
6685            longSize = shortSize;
6686            shortSize = tmp;
6687        }
6688        longSize = (int)(longSize/density);
6689        shortSize = (int)(shortSize/density);
6690        return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
6691    }
6692
6693    private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
6694                  int dw, int dh, float density, Configuration outConfig) {
6695        // TODO: Multidisplay: for now only use with default display.
6696
6697        // We need to determine the smallest width that will occur under normal
6698        // operation.  To this, start with the base screen size and compute the
6699        // width under the different possible rotations.  We need to un-rotate
6700        // the current screen dimensions before doing this.
6701        int unrotDw, unrotDh;
6702        if (rotated) {
6703            unrotDw = dh;
6704            unrotDh = dw;
6705        } else {
6706            unrotDw = dw;
6707            unrotDh = dh;
6708        }
6709        displayInfo.smallestNominalAppWidth = 1<<30;
6710        displayInfo.smallestNominalAppHeight = 1<<30;
6711        displayInfo.largestNominalAppWidth = 0;
6712        displayInfo.largestNominalAppHeight = 0;
6713        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
6714        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
6715        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
6716        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
6717        int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
6718        sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
6719        sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
6720        sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
6721        sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
6722        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
6723        outConfig.screenLayout = sl;
6724    }
6725
6726    private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
6727            int dw, int dh) {
6728        // TODO: Multidisplay: for now only use with default display.
6729        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6730        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6731        float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
6732        int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
6733        if (curSize == 0 || size < curSize) {
6734            curSize = size;
6735        }
6736        return curSize;
6737    }
6738
6739    private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) {
6740        // TODO: Multidisplay: for now only use with default display.
6741        mTmpDisplayMetrics.setTo(dm);
6742        final DisplayMetrics tmpDm = mTmpDisplayMetrics;
6743        final int unrotDw, unrotDh;
6744        if (rotated) {
6745            unrotDw = dh;
6746            unrotDh = dw;
6747        } else {
6748            unrotDw = dw;
6749            unrotDh = dh;
6750        }
6751        int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh);
6752        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw);
6753        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh);
6754        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw);
6755        return sw;
6756    }
6757
6758    boolean computeScreenConfigurationLocked(Configuration config) {
6759        if (!mDisplayReady) {
6760            return false;
6761        }
6762
6763        // TODO(multidisplay): For now, apply Configuration to main screen only.
6764        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6765
6766        // Use the effective "visual" dimensions based on current rotation
6767        final boolean rotated = (mRotation == Surface.ROTATION_90
6768                || mRotation == Surface.ROTATION_270);
6769        final int realdw = rotated ?
6770                displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
6771        final int realdh = rotated ?
6772                displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
6773        int dw = realdw;
6774        int dh = realdh;
6775
6776        if (mAltOrientation) {
6777            if (realdw > realdh) {
6778                // Turn landscape into portrait.
6779                int maxw = (int)(realdh/1.3f);
6780                if (maxw < realdw) {
6781                    dw = maxw;
6782                }
6783            } else {
6784                // Turn portrait into landscape.
6785                int maxh = (int)(realdw/1.3f);
6786                if (maxh < realdh) {
6787                    dh = maxh;
6788                }
6789            }
6790        }
6791
6792        if (config != null) {
6793            config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
6794                    Configuration.ORIENTATION_LANDSCAPE;
6795        }
6796
6797        // Update application display metrics.
6798        final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
6799        final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
6800        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6801        synchronized(displayContent.mDisplaySizeLock) {
6802            displayInfo.rotation = mRotation;
6803            displayInfo.logicalWidth = dw;
6804            displayInfo.logicalHeight = dh;
6805            displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
6806            displayInfo.appWidth = appWidth;
6807            displayInfo.appHeight = appHeight;
6808            displayInfo.getLogicalMetrics(mRealDisplayMetrics,
6809                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
6810            displayInfo.getAppMetrics(mDisplayMetrics);
6811            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
6812                    displayContent.getDisplayId(), displayInfo);
6813        }
6814        if (false) {
6815            Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
6816        }
6817
6818        final DisplayMetrics dm = mDisplayMetrics;
6819        mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
6820                mCompatDisplayMetrics);
6821
6822        if (config != null) {
6823            config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
6824                    / dm.density);
6825            config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
6826                    / dm.density);
6827            computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
6828
6829            config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
6830            config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
6831            config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
6832            config.densityDpi = displayContent.mBaseDisplayDensity;
6833
6834            // Update the configuration based on available input devices, lid switch,
6835            // and platform configuration.
6836            config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6837            config.keyboard = Configuration.KEYBOARD_NOKEYS;
6838            config.navigation = Configuration.NAVIGATION_NONAV;
6839
6840            int keyboardPresence = 0;
6841            int navigationPresence = 0;
6842            final InputDevice[] devices = mInputManager.getInputDevices();
6843            final int len = devices.length;
6844            for (int i = 0; i < len; i++) {
6845                InputDevice device = devices[i];
6846                if (!device.isVirtual()) {
6847                    final int sources = device.getSources();
6848                    final int presenceFlag = device.isExternal() ?
6849                            WindowManagerPolicy.PRESENCE_EXTERNAL :
6850                                    WindowManagerPolicy.PRESENCE_INTERNAL;
6851
6852                    if (mIsTouchDevice) {
6853                        if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
6854                                InputDevice.SOURCE_TOUCHSCREEN) {
6855                            config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
6856                        }
6857                    } else {
6858                        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6859                    }
6860
6861                    if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
6862                        config.navigation = Configuration.NAVIGATION_TRACKBALL;
6863                        navigationPresence |= presenceFlag;
6864                    } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
6865                            && config.navigation == Configuration.NAVIGATION_NONAV) {
6866                        config.navigation = Configuration.NAVIGATION_DPAD;
6867                        navigationPresence |= presenceFlag;
6868                    }
6869
6870                    if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
6871                        config.keyboard = Configuration.KEYBOARD_QWERTY;
6872                        keyboardPresence |= presenceFlag;
6873                    }
6874                }
6875            }
6876
6877            // Determine whether a hard keyboard is available and enabled.
6878            boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
6879            if (hardKeyboardAvailable != mHardKeyboardAvailable) {
6880                mHardKeyboardAvailable = hardKeyboardAvailable;
6881                mHardKeyboardEnabled = hardKeyboardAvailable;
6882                mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6883                mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6884            }
6885            if (!mHardKeyboardEnabled) {
6886                config.keyboard = Configuration.KEYBOARD_NOKEYS;
6887            }
6888
6889            // Let the policy update hidden states.
6890            config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
6891            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
6892            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
6893            mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
6894        }
6895
6896        return true;
6897    }
6898
6899    public boolean isHardKeyboardAvailable() {
6900        synchronized (mWindowMap) {
6901            return mHardKeyboardAvailable;
6902        }
6903    }
6904
6905    public boolean isHardKeyboardEnabled() {
6906        synchronized (mWindowMap) {
6907            return mHardKeyboardEnabled;
6908        }
6909    }
6910
6911    public void setHardKeyboardEnabled(boolean enabled) {
6912        synchronized (mWindowMap) {
6913            if (mHardKeyboardEnabled != enabled) {
6914                mHardKeyboardEnabled = enabled;
6915                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6916            }
6917        }
6918    }
6919
6920    public void setOnHardKeyboardStatusChangeListener(
6921            OnHardKeyboardStatusChangeListener listener) {
6922        synchronized (mWindowMap) {
6923            mHardKeyboardStatusChangeListener = listener;
6924        }
6925    }
6926
6927    void notifyHardKeyboardStatusChange() {
6928        final boolean available, enabled;
6929        final OnHardKeyboardStatusChangeListener listener;
6930        synchronized (mWindowMap) {
6931            listener = mHardKeyboardStatusChangeListener;
6932            available = mHardKeyboardAvailable;
6933            enabled = mHardKeyboardEnabled;
6934        }
6935        if (listener != null) {
6936            listener.onHardKeyboardStatusChange(available, enabled);
6937        }
6938    }
6939
6940    // -------------------------------------------------------------
6941    // Drag and drop
6942    // -------------------------------------------------------------
6943
6944    IBinder prepareDragSurface(IWindow window, SurfaceSession session,
6945            int flags, int width, int height, Surface outSurface) {
6946        if (DEBUG_DRAG) {
6947            Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height
6948                    + " flags=" + Integer.toHexString(flags) + " win=" + window
6949                    + " asbinder=" + window.asBinder());
6950        }
6951
6952        final int callerPid = Binder.getCallingPid();
6953        final long origId = Binder.clearCallingIdentity();
6954        IBinder token = null;
6955
6956        try {
6957            synchronized (mWindowMap) {
6958                try {
6959                    if (mDragState == null) {
6960                        // TODO(multi-display): support other displays
6961                        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6962                        final Display display = displayContent.getDisplay();
6963                        SurfaceControl surface = new SurfaceControl(session, "drag surface",
6964                                width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
6965                        surface.setLayerStack(display.getLayerStack());
6966                        if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
6967                                + surface + ": CREATE");
6968                        outSurface.copyFrom(surface);
6969                        final IBinder winBinder = window.asBinder();
6970                        token = new Binder();
6971                        mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder);
6972                        token = mDragState.mToken = new Binder();
6973
6974                        // 5 second timeout for this window to actually begin the drag
6975                        mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
6976                        Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
6977                        mH.sendMessageDelayed(msg, 5000);
6978                    } else {
6979                        Slog.w(TAG, "Drag already in progress");
6980                    }
6981                } catch (OutOfResourcesException e) {
6982                    Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e);
6983                    if (mDragState != null) {
6984                        mDragState.reset();
6985                        mDragState = null;
6986                    }
6987                }
6988            }
6989        } finally {
6990            Binder.restoreCallingIdentity(origId);
6991        }
6992
6993        return token;
6994    }
6995
6996    // -------------------------------------------------------------
6997    // Input Events and Focus Management
6998    // -------------------------------------------------------------
6999
7000    final InputMonitor mInputMonitor = new InputMonitor(this);
7001    private boolean mEventDispatchingEnabled;
7002
7003    @Override
7004    public void pauseKeyDispatching(IBinder _token) {
7005        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7006                "pauseKeyDispatching()")) {
7007            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7008        }
7009
7010        synchronized (mWindowMap) {
7011            WindowToken token = mTokenMap.get(_token);
7012            if (token != null) {
7013                mInputMonitor.pauseDispatchingLw(token);
7014            }
7015        }
7016    }
7017
7018    @Override
7019    public void resumeKeyDispatching(IBinder _token) {
7020        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7021                "resumeKeyDispatching()")) {
7022            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7023        }
7024
7025        synchronized (mWindowMap) {
7026            WindowToken token = mTokenMap.get(_token);
7027            if (token != null) {
7028                mInputMonitor.resumeDispatchingLw(token);
7029            }
7030        }
7031    }
7032
7033    @Override
7034    public void setEventDispatching(boolean enabled) {
7035        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7036                "setEventDispatching()")) {
7037            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7038        }
7039
7040        synchronized (mWindowMap) {
7041            mEventDispatchingEnabled = enabled;
7042            if (mDisplayEnabled) {
7043                mInputMonitor.setEventDispatchingLw(enabled);
7044            }
7045        }
7046    }
7047
7048    @Override
7049    public IBinder getFocusedWindowToken() {
7050        if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
7051                "getFocusedWindowToken()")) {
7052            throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
7053        }
7054        synchronized (mWindowMap) {
7055            WindowState windowState = getFocusedWindowLocked();
7056            if (windowState != null) {
7057                return windowState.mClient.asBinder();
7058            }
7059            return null;
7060        }
7061    }
7062
7063    private WindowState getFocusedWindow() {
7064        synchronized (mWindowMap) {
7065            return getFocusedWindowLocked();
7066        }
7067    }
7068
7069    private WindowState getFocusedWindowLocked() {
7070        return mCurrentFocus;
7071    }
7072
7073    public boolean detectSafeMode() {
7074        if (!mInputMonitor.waitForInputDevicesReady(
7075                INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
7076            Slog.w(TAG, "Devices still not ready after waiting "
7077                   + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
7078                   + " milliseconds before attempting to detect safe mode.");
7079        }
7080
7081        int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
7082                KeyEvent.KEYCODE_MENU);
7083        int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
7084        int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
7085                KeyEvent.KEYCODE_DPAD_CENTER);
7086        int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
7087                InputManagerService.BTN_MOUSE);
7088        int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
7089                KeyEvent.KEYCODE_VOLUME_DOWN);
7090        mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
7091                || volumeDownState > 0;
7092        try {
7093            if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) {
7094                mSafeMode = true;
7095                SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
7096            }
7097        } catch (IllegalArgumentException e) {
7098        }
7099        if (mSafeMode) {
7100            Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
7101                    + " dpad=" + dpadState + " trackball=" + trackballState + ")");
7102        } else {
7103            Log.i(TAG, "SAFE MODE not enabled");
7104        }
7105        mPolicy.setSafeMode(mSafeMode);
7106        return mSafeMode;
7107    }
7108
7109    public void displayReady() {
7110        displayReady(Display.DEFAULT_DISPLAY);
7111
7112        synchronized(mWindowMap) {
7113            final DisplayContent displayContent = getDefaultDisplayContentLocked();
7114            readForcedDisplaySizeAndDensityLocked(displayContent);
7115            mDisplayReady = true;
7116        }
7117
7118        try {
7119            mActivityManager.updateConfiguration(null);
7120        } catch (RemoteException e) {
7121        }
7122
7123        synchronized(mWindowMap) {
7124            mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
7125                    PackageManager.FEATURE_TOUCHSCREEN);
7126            configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
7127        }
7128
7129        try {
7130            mActivityManager.updateConfiguration(null);
7131        } catch (RemoteException e) {
7132        }
7133    }
7134
7135    private void displayReady(int displayId) {
7136        synchronized(mWindowMap) {
7137            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7138            if (displayContent != null) {
7139                mAnimator.addDisplayLocked(displayId);
7140                synchronized(displayContent.mDisplaySizeLock) {
7141                    // Bootstrap the default logical display from the display manager.
7142                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7143                    DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId);
7144                    if (newDisplayInfo != null) {
7145                        displayInfo.copyFrom(newDisplayInfo);
7146                    }
7147                    displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
7148                    displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
7149                    displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
7150                    displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
7151                    displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
7152                    displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
7153                    displayContent.mBaseDisplayRect.set(0, 0,
7154                            displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight);
7155                }
7156            }
7157        }
7158    }
7159
7160    public void systemReady() {
7161        mPolicy.systemReady();
7162    }
7163
7164    // -------------------------------------------------------------
7165    // Async Handler
7166    // -------------------------------------------------------------
7167
7168    final class H extends Handler {
7169        public static final int REPORT_FOCUS_CHANGE = 2;
7170        public static final int REPORT_LOSING_FOCUS = 3;
7171        public static final int DO_TRAVERSAL = 4;
7172        public static final int ADD_STARTING = 5;
7173        public static final int REMOVE_STARTING = 6;
7174        public static final int FINISHED_STARTING = 7;
7175        public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
7176        public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
7177        public static final int WINDOW_FREEZE_TIMEOUT = 11;
7178
7179        public static final int APP_TRANSITION_TIMEOUT = 13;
7180        public static final int PERSIST_ANIMATION_SCALE = 14;
7181        public static final int FORCE_GC = 15;
7182        public static final int ENABLE_SCREEN = 16;
7183        public static final int APP_FREEZE_TIMEOUT = 17;
7184        public static final int SEND_NEW_CONFIGURATION = 18;
7185        public static final int REPORT_WINDOWS_CHANGE = 19;
7186        public static final int DRAG_START_TIMEOUT = 20;
7187        public static final int DRAG_END_TIMEOUT = 21;
7188        public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
7189        public static final int BOOT_TIMEOUT = 23;
7190        public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
7191        public static final int SHOW_STRICT_MODE_VIOLATION = 25;
7192        public static final int DO_ANIMATION_CALLBACK = 26;
7193
7194        public static final int DO_DISPLAY_ADDED = 27;
7195        public static final int DO_DISPLAY_REMOVED = 28;
7196        public static final int DO_DISPLAY_CHANGED = 29;
7197
7198        public static final int CLIENT_FREEZE_TIMEOUT = 30;
7199        public static final int TAP_OUTSIDE_STACK = 31;
7200        public static final int NOTIFY_ACTIVITY_DRAWN = 32;
7201
7202        public static final int REMOVE_STARTING_TIMEOUT = 33;
7203
7204        public static final int SHOW_DISPLAY_MASK = 34;
7205        public static final int ALL_WINDOWS_DRAWN = 35;
7206
7207        @Override
7208        public void handleMessage(Message msg) {
7209            if (DEBUG_WINDOW_TRACE) {
7210                Slog.v(TAG, "handleMessage: entry what=" + msg.what);
7211            }
7212            switch (msg.what) {
7213                case REPORT_FOCUS_CHANGE: {
7214                    WindowState lastFocus;
7215                    WindowState newFocus;
7216
7217                    synchronized(mWindowMap) {
7218                        lastFocus = mLastFocus;
7219                        newFocus = mCurrentFocus;
7220                        if (lastFocus == newFocus) {
7221                            // Focus is not changing, so nothing to do.
7222                            return;
7223                        }
7224                        mLastFocus = newFocus;
7225                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus +
7226                                " to " + newFocus);
7227                        if (newFocus != null && lastFocus != null
7228                                && !newFocus.isDisplayedLw()) {
7229                            //Slog.i(TAG, "Delaying loss of focus...");
7230                            mLosingFocus.add(lastFocus);
7231                            lastFocus = null;
7232                        }
7233                    }
7234
7235                    //System.out.println("Changing focus from " + lastFocus
7236                    //                   + " to " + newFocus);
7237                    if (newFocus != null) {
7238                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus);
7239                        newFocus.reportFocusChangedSerialized(true, mInTouchMode);
7240                        notifyFocusChanged();
7241                    }
7242
7243                    if (lastFocus != null) {
7244                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus);
7245                        lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
7246                    }
7247                } break;
7248
7249                case REPORT_LOSING_FOCUS: {
7250                    ArrayList<WindowState> losers;
7251
7252                    synchronized(mWindowMap) {
7253                        losers = mLosingFocus;
7254                        mLosingFocus = new ArrayList<WindowState>();
7255                    }
7256
7257                    final int N = losers.size();
7258                    for (int i=0; i<N; i++) {
7259                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " +
7260                                losers.get(i));
7261                        losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
7262                    }
7263                } break;
7264
7265                case DO_TRAVERSAL: {
7266                    synchronized(mWindowMap) {
7267                        mTraversalScheduled = false;
7268                        performLayoutAndPlaceSurfacesLocked();
7269                    }
7270                } break;
7271
7272                case ADD_STARTING: {
7273                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7274                    final StartingData sd = wtoken.startingData;
7275
7276                    if (sd == null) {
7277                        // Animation has been canceled... do nothing.
7278                        return;
7279                    }
7280
7281                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
7282                            + wtoken + ": pkg=" + sd.pkg);
7283
7284                    View view = null;
7285                    try {
7286                        view = mPolicy.addStartingWindow(
7287                            wtoken.token, sd.pkg, sd.theme, sd.compatInfo,
7288                            sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags);
7289                    } catch (Exception e) {
7290                        Slog.w(TAG, "Exception when adding starting window", e);
7291                    }
7292
7293                    if (view != null) {
7294                        boolean abort = false;
7295
7296                        synchronized(mWindowMap) {
7297                            if (wtoken.removed || wtoken.startingData == null) {
7298                                // If the window was successfully added, then
7299                                // we need to remove it.
7300                                if (wtoken.startingWindow != null) {
7301                                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7302                                            "Aborted starting " + wtoken
7303                                            + ": removed=" + wtoken.removed
7304                                            + " startingData=" + wtoken.startingData);
7305                                    removeStartingWindowTimeout(wtoken);
7306                                    wtoken.startingWindow = null;
7307                                    wtoken.startingData = null;
7308                                    abort = true;
7309                                }
7310                            } else {
7311                                wtoken.startingView = view;
7312                            }
7313                            if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
7314                                    "Added starting " + wtoken
7315                                    + ": startingWindow="
7316                                    + wtoken.startingWindow + " startingView="
7317                                    + wtoken.startingView);
7318                        }
7319
7320                        if (abort) {
7321                            try {
7322                                mPolicy.removeStartingWindow(wtoken.token, view);
7323                            } catch (Exception e) {
7324                                Slog.w(TAG, "Exception when removing starting window", e);
7325                            }
7326                        }
7327                    }
7328                } break;
7329
7330                case REMOVE_STARTING_TIMEOUT: {
7331                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7332                    Slog.e(TAG, "Starting window " + wtoken + " timed out");
7333                    // Fall through.
7334                }
7335                case REMOVE_STARTING: {
7336                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7337                    IBinder token = null;
7338                    View view = null;
7339                    synchronized (mWindowMap) {
7340                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
7341                                + wtoken + ": startingWindow="
7342                                + wtoken.startingWindow + " startingView="
7343                                + wtoken.startingView);
7344                        if (wtoken.startingWindow != null) {
7345                            view = wtoken.startingView;
7346                            token = wtoken.token;
7347                            wtoken.startingData = null;
7348                            wtoken.startingView = null;
7349                            wtoken.startingWindow = null;
7350                            wtoken.startingDisplayed = false;
7351                        }
7352                    }
7353                    if (view != null) {
7354                        try {
7355                            mPolicy.removeStartingWindow(token, view);
7356                        } catch (Exception e) {
7357                            Slog.w(TAG, "Exception when removing starting window", e);
7358                        }
7359                    }
7360                } break;
7361
7362                case FINISHED_STARTING: {
7363                    IBinder token = null;
7364                    View view = null;
7365                    while (true) {
7366                        synchronized (mWindowMap) {
7367                            final int N = mFinishedStarting.size();
7368                            if (N <= 0) {
7369                                break;
7370                            }
7371                            AppWindowToken wtoken = mFinishedStarting.remove(N-1);
7372
7373                            if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7374                                    "Finished starting " + wtoken
7375                                    + ": startingWindow=" + wtoken.startingWindow
7376                                    + " startingView=" + wtoken.startingView);
7377
7378                            if (wtoken.startingWindow == null) {
7379                                continue;
7380                            }
7381
7382                            view = wtoken.startingView;
7383                            token = wtoken.token;
7384                            wtoken.startingData = null;
7385                            wtoken.startingView = null;
7386                            wtoken.startingWindow = null;
7387                            wtoken.startingDisplayed = false;
7388                        }
7389
7390                        try {
7391                            mPolicy.removeStartingWindow(token, view);
7392                        } catch (Exception e) {
7393                            Slog.w(TAG, "Exception when removing starting window", e);
7394                        }
7395                    }
7396                } break;
7397
7398                case REPORT_APPLICATION_TOKEN_DRAWN: {
7399                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7400
7401                    try {
7402                        if (DEBUG_VISIBILITY) Slog.v(
7403                                TAG, "Reporting drawn in " + wtoken);
7404                        wtoken.appToken.windowsDrawn();
7405                    } catch (RemoteException ex) {
7406                    }
7407                } break;
7408
7409                case REPORT_APPLICATION_TOKEN_WINDOWS: {
7410                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7411
7412                    boolean nowVisible = msg.arg1 != 0;
7413                    boolean nowGone = msg.arg2 != 0;
7414
7415                    try {
7416                        if (DEBUG_VISIBILITY) Slog.v(
7417                                TAG, "Reporting visible in " + wtoken
7418                                + " visible=" + nowVisible
7419                                + " gone=" + nowGone);
7420                        if (nowVisible) {
7421                            wtoken.appToken.windowsVisible();
7422                        } else {
7423                            wtoken.appToken.windowsGone();
7424                        }
7425                    } catch (RemoteException ex) {
7426                    }
7427                } break;
7428
7429                case WINDOW_FREEZE_TIMEOUT: {
7430                    // TODO(multidisplay): Can non-default displays rotate?
7431                    synchronized (mWindowMap) {
7432                        Slog.w(TAG, "Window freeze timeout expired.");
7433                        final WindowList windows = getDefaultWindowListLocked();
7434                        int i = windows.size();
7435                        while (i > 0) {
7436                            i--;
7437                            WindowState w = windows.get(i);
7438                            if (w.mOrientationChanging) {
7439                                w.mOrientationChanging = false;
7440                                w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
7441                                        - mDisplayFreezeTime);
7442                                Slog.w(TAG, "Force clearing orientation change: " + w);
7443                            }
7444                        }
7445                        performLayoutAndPlaceSurfacesLocked();
7446                    }
7447                    break;
7448                }
7449
7450                case APP_TRANSITION_TIMEOUT: {
7451                    synchronized (mWindowMap) {
7452                        if (mAppTransition.isTransitionSet()) {
7453                            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT");
7454                            mAppTransition.setTimeout();
7455                            performLayoutAndPlaceSurfacesLocked();
7456                        }
7457                    }
7458                    break;
7459                }
7460
7461                case PERSIST_ANIMATION_SCALE: {
7462                    Settings.Global.putFloat(mContext.getContentResolver(),
7463                            Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
7464                    Settings.Global.putFloat(mContext.getContentResolver(),
7465                            Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
7466                    Settings.Global.putFloat(mContext.getContentResolver(),
7467                            Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale);
7468                    break;
7469                }
7470
7471                case FORCE_GC: {
7472                    synchronized (mWindowMap) {
7473                        // Since we're holding both mWindowMap and mAnimator we don't need to
7474                        // hold mAnimator.mLayoutToAnim.
7475                        if (mAnimator.mAnimating || mAnimationScheduled) {
7476                            // If we are animating, don't do the gc now but
7477                            // delay a bit so we don't interrupt the animation.
7478                            sendEmptyMessageDelayed(H.FORCE_GC, 2000);
7479                            return;
7480                        }
7481                        // If we are currently rotating the display, it will
7482                        // schedule a new message when done.
7483                        if (mDisplayFrozen) {
7484                            return;
7485                        }
7486                    }
7487                    Runtime.getRuntime().gc();
7488                    break;
7489                }
7490
7491                case ENABLE_SCREEN: {
7492                    performEnableScreen();
7493                    break;
7494                }
7495
7496                case APP_FREEZE_TIMEOUT: {
7497                    synchronized (mWindowMap) {
7498                        Slog.w(TAG, "App freeze timeout expired.");
7499                        final int numStacks = mStackIdToStack.size();
7500                        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
7501                            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
7502                            final ArrayList<Task> tasks = stack.getTasks();
7503                            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
7504                                AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
7505                                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
7506                                    AppWindowToken tok = tokens.get(tokenNdx);
7507                                    if (tok.mAppAnimator.freezingScreen) {
7508                                        Slog.w(TAG, "Force clearing freeze: " + tok);
7509                                        unsetAppFreezingScreenLocked(tok, true, true);
7510                                    }
7511                                }
7512                            }
7513                        }
7514                    }
7515                    break;
7516                }
7517
7518                case CLIENT_FREEZE_TIMEOUT: {
7519                    synchronized (mWindowMap) {
7520                        if (mClientFreezingScreen) {
7521                            mClientFreezingScreen = false;
7522                            mLastFinishedFreezeSource = "client-timeout";
7523                            stopFreezingDisplayLocked();
7524                        }
7525                    }
7526                    break;
7527                }
7528
7529                case SEND_NEW_CONFIGURATION: {
7530                    removeMessages(SEND_NEW_CONFIGURATION);
7531                    sendNewConfiguration();
7532                    break;
7533                }
7534
7535                case REPORT_WINDOWS_CHANGE: {
7536                    if (mWindowsChanged) {
7537                        synchronized (mWindowMap) {
7538                            mWindowsChanged = false;
7539                        }
7540                        notifyWindowsChanged();
7541                    }
7542                    break;
7543                }
7544
7545                case DRAG_START_TIMEOUT: {
7546                    IBinder win = (IBinder)msg.obj;
7547                    if (DEBUG_DRAG) {
7548                        Slog.w(TAG, "Timeout starting drag by win " + win);
7549                    }
7550                    synchronized (mWindowMap) {
7551                        // !!! TODO: ANR the app that has failed to start the drag in time
7552                        if (mDragState != null) {
7553                            mDragState.unregister();
7554                            mInputMonitor.updateInputWindowsLw(true /*force*/);
7555                            mDragState.reset();
7556                            mDragState = null;
7557                        }
7558                    }
7559                    break;
7560                }
7561
7562                case DRAG_END_TIMEOUT: {
7563                    IBinder win = (IBinder)msg.obj;
7564                    if (DEBUG_DRAG) {
7565                        Slog.w(TAG, "Timeout ending drag to win " + win);
7566                    }
7567                    synchronized (mWindowMap) {
7568                        // !!! TODO: ANR the drag-receiving app
7569                        if (mDragState != null) {
7570                            mDragState.mDragResult = false;
7571                            mDragState.endDragLw();
7572                        }
7573                    }
7574                    break;
7575                }
7576
7577                case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
7578                    notifyHardKeyboardStatusChange();
7579                    break;
7580                }
7581
7582                case BOOT_TIMEOUT: {
7583                    performBootTimeout();
7584                    break;
7585                }
7586
7587                case WAITING_FOR_DRAWN_TIMEOUT: {
7588                    IRemoteCallback callback = null;
7589                    synchronized (mWindowMap) {
7590                        Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
7591                        mWaitingForDrawn.clear();
7592                        callback = mWaitingForDrawnCallback;
7593                        mWaitingForDrawnCallback = null;
7594                    }
7595                    if (callback != null) {
7596                        try {
7597                            callback.sendResult(null);
7598                        } catch (RemoteException e) {
7599                        }
7600                    }
7601                    break;
7602                }
7603
7604                case SHOW_STRICT_MODE_VIOLATION: {
7605                    showStrictModeViolation(msg.arg1, msg.arg2);
7606                    break;
7607                }
7608
7609                case SHOW_DISPLAY_MASK: {
7610                    showCircularMask();
7611                    break;
7612                }
7613
7614                case DO_ANIMATION_CALLBACK: {
7615                    try {
7616                        ((IRemoteCallback)msg.obj).sendResult(null);
7617                    } catch (RemoteException e) {
7618                    }
7619                    break;
7620                }
7621
7622                case DO_DISPLAY_ADDED:
7623                    handleDisplayAdded(msg.arg1);
7624                    break;
7625
7626                case DO_DISPLAY_REMOVED:
7627                    synchronized (mWindowMap) {
7628                        handleDisplayRemovedLocked(msg.arg1);
7629                    }
7630                    break;
7631
7632                case DO_DISPLAY_CHANGED:
7633                    synchronized (mWindowMap) {
7634                        handleDisplayChangedLocked(msg.arg1);
7635                    }
7636                    break;
7637
7638                case TAP_OUTSIDE_STACK: {
7639                    int stackId;
7640                    synchronized (mWindowMap) {
7641                        stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
7642                    }
7643                    if (stackId >= 0) {
7644                        try {
7645                            mActivityManager.setFocusedStack(stackId);
7646                        } catch (RemoteException e) {
7647                        }
7648                    }
7649                }
7650                break;
7651                case NOTIFY_ACTIVITY_DRAWN:
7652                    try {
7653                        mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
7654                    } catch (RemoteException e) {
7655                    }
7656                    break;
7657                case ALL_WINDOWS_DRAWN: {
7658                    IRemoteCallback callback;
7659                    synchronized (mWindowMap) {
7660                        callback = mWaitingForDrawnCallback;
7661                        mWaitingForDrawnCallback = null;
7662                    }
7663                    if (callback != null) {
7664                        try {
7665                            callback.sendResult(null);
7666                        } catch (RemoteException e) {
7667                        }
7668                    }
7669                }
7670            }
7671            if (DEBUG_WINDOW_TRACE) {
7672                Slog.v(TAG, "handleMessage: exit");
7673            }
7674        }
7675    }
7676
7677    // -------------------------------------------------------------
7678    // IWindowManager API
7679    // -------------------------------------------------------------
7680
7681    @Override
7682    public IWindowSession openSession(IInputMethodClient client,
7683            IInputContext inputContext) {
7684        if (client == null) throw new IllegalArgumentException("null client");
7685        if (inputContext == null) throw new IllegalArgumentException("null inputContext");
7686        Session session = new Session(this, client, inputContext);
7687        return session;
7688    }
7689
7690    @Override
7691    public boolean inputMethodClientHasFocus(IInputMethodClient client) {
7692        synchronized (mWindowMap) {
7693            // The focus for the client is the window immediately below
7694            // where we would place the input method window.
7695            int idx = findDesiredInputMethodWindowIndexLocked(false);
7696            if (idx > 0) {
7697                // TODO(multidisplay): IMEs are only supported on the default display.
7698                WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
7699                if (DEBUG_INPUT_METHOD) {
7700                    Slog.i(TAG, "Desired input method target: " + imFocus);
7701                    Slog.i(TAG, "Current focus: " + mCurrentFocus);
7702                    Slog.i(TAG, "Last focus: " + mLastFocus);
7703                }
7704                if (imFocus != null) {
7705                    // This may be a starting window, in which case we still want
7706                    // to count it as okay.
7707                    if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING
7708                            && imFocus.mAppToken != null) {
7709                        // The client has definitely started, so it really should
7710                        // have a window in this app token.  Let's look for it.
7711                        for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
7712                            WindowState w = imFocus.mAppToken.windows.get(i);
7713                            if (w != imFocus) {
7714                                Log.i(TAG, "Switching to real app window: " + w);
7715                                imFocus = w;
7716                                break;
7717                            }
7718                        }
7719                    }
7720                    if (DEBUG_INPUT_METHOD) {
7721                        Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient);
7722                        if (imFocus.mSession.mClient != null) {
7723                            Slog.i(TAG, "IM target client binder: "
7724                                    + imFocus.mSession.mClient.asBinder());
7725                            Slog.i(TAG, "Requesting client binder: " + client.asBinder());
7726                        }
7727                    }
7728                    if (imFocus.mSession.mClient != null &&
7729                            imFocus.mSession.mClient.asBinder() == client.asBinder()) {
7730                        return true;
7731                    }
7732                }
7733            }
7734
7735            // Okay, how about this...  what is the current focus?
7736            // It seems in some cases we may not have moved the IM
7737            // target window, such as when it was in a pop-up window,
7738            // so let's also look at the current focus.  (An example:
7739            // go to Gmail, start searching so the keyboard goes up,
7740            // press home.  Sometimes the IME won't go down.)
7741            // Would be nice to fix this more correctly, but it's
7742            // way at the end of a release, and this should be good enough.
7743            if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
7744                    && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
7745                return true;
7746            }
7747        }
7748        return false;
7749    }
7750
7751    @Override
7752    public void getInitialDisplaySize(int displayId, Point size) {
7753        synchronized (mWindowMap) {
7754            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7755            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7756                synchronized(displayContent.mDisplaySizeLock) {
7757                    size.x = displayContent.mInitialDisplayWidth;
7758                    size.y = displayContent.mInitialDisplayHeight;
7759                }
7760            }
7761        }
7762    }
7763
7764    @Override
7765    public void getBaseDisplaySize(int displayId, Point size) {
7766        synchronized (mWindowMap) {
7767            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7768            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7769                synchronized(displayContent.mDisplaySizeLock) {
7770                    size.x = displayContent.mBaseDisplayWidth;
7771                    size.y = displayContent.mBaseDisplayHeight;
7772                }
7773            }
7774        }
7775    }
7776
7777    @Override
7778    public void setForcedDisplaySize(int displayId, int width, int height) {
7779        if (mContext.checkCallingOrSelfPermission(
7780                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7781                PackageManager.PERMISSION_GRANTED) {
7782            throw new SecurityException("Must hold permission " +
7783                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7784        }
7785        if (displayId != Display.DEFAULT_DISPLAY) {
7786            throw new IllegalArgumentException("Can only set the default display");
7787        }
7788        final long ident = Binder.clearCallingIdentity();
7789        try {
7790            synchronized(mWindowMap) {
7791                // Set some sort of reasonable bounds on the size of the display that we
7792                // will try to emulate.
7793                final int MIN_WIDTH = 200;
7794                final int MIN_HEIGHT = 200;
7795                final int MAX_SCALE = 2;
7796                final DisplayContent displayContent = getDisplayContentLocked(displayId);
7797                if (displayContent != null) {
7798                    width = Math.min(Math.max(width, MIN_WIDTH),
7799                            displayContent.mInitialDisplayWidth * MAX_SCALE);
7800                    height = Math.min(Math.max(height, MIN_HEIGHT),
7801                            displayContent.mInitialDisplayHeight * MAX_SCALE);
7802                    setForcedDisplaySizeLocked(displayContent, width, height);
7803                    Settings.Global.putString(mContext.getContentResolver(),
7804                            Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
7805                }
7806            }
7807        } finally {
7808            Binder.restoreCallingIdentity(ident);
7809        }
7810    }
7811
7812    private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) {
7813        String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
7814                Settings.Global.DISPLAY_SIZE_FORCED);
7815        if (sizeStr == null || sizeStr.length() == 0) {
7816            sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
7817        }
7818        if (sizeStr != null && sizeStr.length() > 0) {
7819            final int pos = sizeStr.indexOf(',');
7820            if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
7821                int width, height;
7822                try {
7823                    width = Integer.parseInt(sizeStr.substring(0, pos));
7824                    height = Integer.parseInt(sizeStr.substring(pos+1));
7825                    synchronized(displayContent.mDisplaySizeLock) {
7826                        if (displayContent.mBaseDisplayWidth != width
7827                                || displayContent.mBaseDisplayHeight != height) {
7828                            Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height);
7829                            displayContent.mBaseDisplayWidth = width;
7830                            displayContent.mBaseDisplayHeight = height;
7831                        }
7832                    }
7833                } catch (NumberFormatException ex) {
7834                }
7835            }
7836        }
7837        String densityStr = Settings.Global.getString(mContext.getContentResolver(),
7838                Settings.Global.DISPLAY_DENSITY_FORCED);
7839        if (densityStr == null || densityStr.length() == 0) {
7840            densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
7841        }
7842        if (densityStr != null && densityStr.length() > 0) {
7843            int density;
7844            try {
7845                density = Integer.parseInt(densityStr);
7846                synchronized(displayContent.mDisplaySizeLock) {
7847                    if (displayContent.mBaseDisplayDensity != density) {
7848                        Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density);
7849                        displayContent.mBaseDisplayDensity = density;
7850                    }
7851                }
7852            } catch (NumberFormatException ex) {
7853            }
7854        }
7855    }
7856
7857    // displayContent must not be null
7858    private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
7859        Slog.i(TAG, "Using new display size: " + width + "x" + height);
7860
7861        synchronized(displayContent.mDisplaySizeLock) {
7862            displayContent.mBaseDisplayWidth = width;
7863            displayContent.mBaseDisplayHeight = height;
7864        }
7865        reconfigureDisplayLocked(displayContent);
7866    }
7867
7868    @Override
7869    public void clearForcedDisplaySize(int displayId) {
7870        if (mContext.checkCallingOrSelfPermission(
7871                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7872                PackageManager.PERMISSION_GRANTED) {
7873            throw new SecurityException("Must hold permission " +
7874                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7875        }
7876        if (displayId != Display.DEFAULT_DISPLAY) {
7877            throw new IllegalArgumentException("Can only set the default display");
7878        }
7879        final long ident = Binder.clearCallingIdentity();
7880        try {
7881            synchronized(mWindowMap) {
7882                final DisplayContent displayContent = getDisplayContentLocked(displayId);
7883                if (displayContent != null) {
7884                    setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
7885                            displayContent.mInitialDisplayHeight);
7886                    Settings.Global.putString(mContext.getContentResolver(),
7887                            Settings.Global.DISPLAY_SIZE_FORCED, "");
7888                }
7889            }
7890        } finally {
7891            Binder.restoreCallingIdentity(ident);
7892        }
7893    }
7894
7895    @Override
7896    public int getInitialDisplayDensity(int displayId) {
7897        synchronized (mWindowMap) {
7898            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7899            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7900                synchronized(displayContent.mDisplaySizeLock) {
7901                    return displayContent.mInitialDisplayDensity;
7902                }
7903            }
7904        }
7905        return -1;
7906    }
7907
7908    @Override
7909    public int getBaseDisplayDensity(int displayId) {
7910        synchronized (mWindowMap) {
7911            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7912            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7913                synchronized(displayContent.mDisplaySizeLock) {
7914                    return displayContent.mBaseDisplayDensity;
7915                }
7916            }
7917        }
7918        return -1;
7919    }
7920
7921    @Override
7922    public void setForcedDisplayDensity(int displayId, int density) {
7923        if (mContext.checkCallingOrSelfPermission(
7924                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7925                PackageManager.PERMISSION_GRANTED) {
7926            throw new SecurityException("Must hold permission " +
7927                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7928        }
7929        if (displayId != Display.DEFAULT_DISPLAY) {
7930            throw new IllegalArgumentException("Can only set the default display");
7931        }
7932        final long ident = Binder.clearCallingIdentity();
7933        try {
7934            synchronized(mWindowMap) {
7935                final DisplayContent displayContent = getDisplayContentLocked(displayId);
7936                if (displayContent != null) {
7937                    setForcedDisplayDensityLocked(displayContent, density);
7938                    Settings.Global.putString(mContext.getContentResolver(),
7939                            Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
7940                }
7941            }
7942        } finally {
7943            Binder.restoreCallingIdentity(ident);
7944        }
7945    }
7946
7947    // displayContent must not be null
7948    private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
7949        Slog.i(TAG, "Using new display density: " + density);
7950
7951        synchronized(displayContent.mDisplaySizeLock) {
7952            displayContent.mBaseDisplayDensity = density;
7953        }
7954        reconfigureDisplayLocked(displayContent);
7955    }
7956
7957    @Override
7958    public void clearForcedDisplayDensity(int displayId) {
7959        if (mContext.checkCallingOrSelfPermission(
7960                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7961                PackageManager.PERMISSION_GRANTED) {
7962            throw new SecurityException("Must hold permission " +
7963                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7964        }
7965        if (displayId != Display.DEFAULT_DISPLAY) {
7966            throw new IllegalArgumentException("Can only set the default display");
7967        }
7968        final long ident = Binder.clearCallingIdentity();
7969        try {
7970            synchronized(mWindowMap) {
7971                final DisplayContent displayContent = getDisplayContentLocked(displayId);
7972                if (displayContent != null) {
7973                    setForcedDisplayDensityLocked(displayContent,
7974                            displayContent.mInitialDisplayDensity);
7975                    Settings.Global.putString(mContext.getContentResolver(),
7976                            Settings.Global.DISPLAY_DENSITY_FORCED, "");
7977                }
7978            }
7979        } finally {
7980            Binder.restoreCallingIdentity(ident);
7981        }
7982    }
7983
7984    // displayContent must not be null
7985    private void reconfigureDisplayLocked(DisplayContent displayContent) {
7986        // TODO: Multidisplay: for now only use with default display.
7987        configureDisplayPolicyLocked(displayContent);
7988        displayContent.layoutNeeded = true;
7989
7990        boolean configChanged = updateOrientationFromAppTokensLocked(false);
7991        mTempConfiguration.setToDefaults();
7992        mTempConfiguration.fontScale = mCurConfiguration.fontScale;
7993        if (computeScreenConfigurationLocked(mTempConfiguration)) {
7994            if (mCurConfiguration.diff(mTempConfiguration) != 0) {
7995                configChanged = true;
7996            }
7997        }
7998
7999        if (configChanged) {
8000            mWaitingForConfig = true;
8001            startFreezingDisplayLocked(false, 0, 0);
8002            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
8003        }
8004
8005        performLayoutAndPlaceSurfacesLocked();
8006    }
8007
8008    private void configureDisplayPolicyLocked(DisplayContent displayContent) {
8009        mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
8010                displayContent.mBaseDisplayWidth,
8011                displayContent.mBaseDisplayHeight,
8012                displayContent.mBaseDisplayDensity);
8013
8014        DisplayInfo displayInfo = displayContent.getDisplayInfo();
8015        mPolicy.setDisplayOverscan(displayContent.getDisplay(),
8016                displayInfo.overscanLeft, displayInfo.overscanTop,
8017                displayInfo.overscanRight, displayInfo.overscanBottom);
8018    }
8019
8020    @Override
8021    public void setOverscan(int displayId, int left, int top, int right, int bottom) {
8022        if (mContext.checkCallingOrSelfPermission(
8023                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8024                PackageManager.PERMISSION_GRANTED) {
8025            throw new SecurityException("Must hold permission " +
8026                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8027        }
8028        final long ident = Binder.clearCallingIdentity();
8029        try {
8030            synchronized(mWindowMap) {
8031                DisplayContent displayContent = getDisplayContentLocked(displayId);
8032                if (displayContent != null) {
8033                    setOverscanLocked(displayContent, left, top, right, bottom);
8034                }
8035            }
8036        } finally {
8037            Binder.restoreCallingIdentity(ident);
8038        }
8039    }
8040
8041    private void setOverscanLocked(DisplayContent displayContent,
8042            int left, int top, int right, int bottom) {
8043        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
8044        synchronized (displayContent.mDisplaySizeLock) {
8045            displayInfo.overscanLeft = left;
8046            displayInfo.overscanTop = top;
8047            displayInfo.overscanRight = right;
8048            displayInfo.overscanBottom = bottom;
8049        }
8050
8051        mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom);
8052        mDisplaySettings.writeSettingsLocked();
8053
8054        reconfigureDisplayLocked(displayContent);
8055    }
8056
8057    // -------------------------------------------------------------
8058    // Internals
8059    // -------------------------------------------------------------
8060
8061    final WindowState windowForClientLocked(Session session, IWindow client,
8062            boolean throwOnError) {
8063        return windowForClientLocked(session, client.asBinder(), throwOnError);
8064    }
8065
8066    final WindowState windowForClientLocked(Session session, IBinder client,
8067            boolean throwOnError) {
8068        WindowState win = mWindowMap.get(client);
8069        if (localLOGV) Slog.v(
8070            TAG, "Looking up client " + client + ": " + win);
8071        if (win == null) {
8072            RuntimeException ex = new IllegalArgumentException(
8073                    "Requested window " + client + " does not exist");
8074            if (throwOnError) {
8075                throw ex;
8076            }
8077            Slog.w(TAG, "Failed looking up window", ex);
8078            return null;
8079        }
8080        if (session != null && win.mSession != session) {
8081            RuntimeException ex = new IllegalArgumentException(
8082                    "Requested window " + client + " is in session " +
8083                    win.mSession + ", not " + session);
8084            if (throwOnError) {
8085                throw ex;
8086            }
8087            Slog.w(TAG, "Failed looking up window", ex);
8088            return null;
8089        }
8090
8091        return win;
8092    }
8093
8094    final void rebuildAppWindowListLocked() {
8095        rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
8096    }
8097
8098    private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
8099        final WindowList windows = displayContent.getWindowList();
8100        int NW = windows.size();
8101        int i;
8102        int lastBelow = -1;
8103        int numRemoved = 0;
8104
8105        if (mRebuildTmp.length < NW) {
8106            mRebuildTmp = new WindowState[NW+10];
8107        }
8108
8109        // First remove all existing app windows.
8110        i=0;
8111        while (i < NW) {
8112            WindowState w = windows.get(i);
8113            if (w.mAppToken != null) {
8114                WindowState win = windows.remove(i);
8115                win.mRebuilding = true;
8116                mRebuildTmp[numRemoved] = win;
8117                mWindowsChanged = true;
8118                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win);
8119                NW--;
8120                numRemoved++;
8121                continue;
8122            } else if (lastBelow == i-1) {
8123                if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8124                    lastBelow = i;
8125                }
8126            }
8127            i++;
8128        }
8129
8130        // Keep whatever windows were below the app windows still below,
8131        // by skipping them.
8132        lastBelow++;
8133        i = lastBelow;
8134
8135        // First add all of the exiting app tokens...  these are no longer
8136        // in the main app list, but still have windows shown.  We put them
8137        // in the back because now that the animation is over we no longer
8138        // will care about them.
8139        final ArrayList<TaskStack> stacks = displayContent.getStacks();
8140        final int numStacks = stacks.size();
8141        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8142            AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens;
8143            int NT = exitingAppTokens.size();
8144            for (int j = 0; j < NT; j++) {
8145                i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
8146            }
8147        }
8148
8149        // And add in the still active app tokens in Z order.
8150        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8151            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
8152            final int numTasks = tasks.size();
8153            for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
8154                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8155                final int numTokens = tokens.size();
8156                for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
8157                    final AppWindowToken wtoken = tokens.get(tokenNdx);
8158                    if (wtoken.mDeferRemoval) {
8159                        continue;
8160                    }
8161                    i = reAddAppWindowsLocked(displayContent, i, wtoken);
8162                }
8163            }
8164        }
8165
8166        i -= lastBelow;
8167        if (i != numRemoved) {
8168            Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " +
8169                    numRemoved + " windows but added " + i,
8170                    new RuntimeException("here").fillInStackTrace());
8171            for (i=0; i<numRemoved; i++) {
8172                WindowState ws = mRebuildTmp[i];
8173                if (ws.mRebuilding) {
8174                    StringWriter sw = new StringWriter();
8175                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
8176                    ws.dump(pw, "", true);
8177                    pw.flush();
8178                    Slog.w(TAG, "This window was lost: " + ws);
8179                    Slog.w(TAG, sw.toString());
8180                    ws.mWinAnimator.destroySurfaceLocked();
8181                }
8182            }
8183            Slog.w(TAG, "Current app token list:");
8184            dumpAppTokensLocked();
8185            Slog.w(TAG, "Final window list:");
8186            dumpWindowsLocked();
8187        }
8188    }
8189
8190    private final void assignLayersLocked(WindowList windows) {
8191        int N = windows.size();
8192        int curBaseLayer = 0;
8193        int curLayer = 0;
8194        int i;
8195
8196        if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows,
8197                new RuntimeException("here").fillInStackTrace());
8198
8199        boolean anyLayerChanged = false;
8200
8201        for (i=0; i<N; i++) {
8202            final WindowState w = windows.get(i);
8203            final WindowStateAnimator winAnimator = w.mWinAnimator;
8204            boolean layerChanged = false;
8205            int oldLayer = w.mLayer;
8206            if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
8207                    || (i > 0 && w.mIsWallpaper)) {
8208                curLayer += WINDOW_LAYER_MULTIPLIER;
8209                w.mLayer = curLayer;
8210            } else {
8211                curBaseLayer = curLayer = w.mBaseLayer;
8212                w.mLayer = curLayer;
8213            }
8214            if (w.mLayer != oldLayer) {
8215                layerChanged = true;
8216                anyLayerChanged = true;
8217            }
8218            final AppWindowToken wtoken = w.mAppToken;
8219            oldLayer = winAnimator.mAnimLayer;
8220            if (w.mTargetAppToken != null) {
8221                winAnimator.mAnimLayer =
8222                        w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment;
8223            } else if (wtoken != null) {
8224                winAnimator.mAnimLayer =
8225                        w.mLayer + wtoken.mAppAnimator.animLayerAdjustment;
8226            } else {
8227                winAnimator.mAnimLayer = w.mLayer;
8228            }
8229            if (w.mIsImWindow) {
8230                winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment;
8231            } else if (w.mIsWallpaper) {
8232                winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment;
8233            }
8234            if (winAnimator.mAnimLayer != oldLayer) {
8235                layerChanged = true;
8236                anyLayerChanged = true;
8237            }
8238            if (layerChanged && w.getStack().isDimming(winAnimator)) {
8239                // Force an animation pass just to update the mDimLayer layer.
8240                scheduleAnimationLocked();
8241            }
8242            if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
8243                    + "mBase=" + w.mBaseLayer
8244                    + " mLayer=" + w.mLayer
8245                    + (wtoken == null ?
8246                            "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment)
8247                    + " =mAnimLayer=" + winAnimator.mAnimLayer);
8248            //System.out.println(
8249            //    "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
8250        }
8251
8252        //TODO (multidisplay): Magnification is supported only for the default display.
8253        if (mDisplayMagnifier != null && anyLayerChanged
8254                && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) {
8255            mDisplayMagnifier.onWindowLayersChangedLocked();
8256        }
8257    }
8258
8259    private final void performLayoutAndPlaceSurfacesLocked() {
8260        int loopCount = 6;
8261        do {
8262            mTraversalScheduled = false;
8263            performLayoutAndPlaceSurfacesLockedLoop();
8264            mH.removeMessages(H.DO_TRAVERSAL);
8265            loopCount--;
8266        } while (mTraversalScheduled && loopCount > 0);
8267        mInnerFields.mWallpaperActionPending = false;
8268    }
8269
8270    private boolean mInLayout = false;
8271    private final void performLayoutAndPlaceSurfacesLockedLoop() {
8272        if (mInLayout) {
8273            if (DEBUG) {
8274                throw new RuntimeException("Recursive call!");
8275            }
8276            Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
8277                    + Debug.getCallers(3));
8278            return;
8279        }
8280
8281        if (mWaitingForConfig) {
8282            // Our configuration has changed (most likely rotation), but we
8283            // don't yet have the complete configuration to report to
8284            // applications.  Don't do any window layout until we have it.
8285            return;
8286        }
8287
8288        if (!mDisplayReady) {
8289            // Not yet initialized, nothing to do.
8290            return;
8291        }
8292
8293        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
8294        mInLayout = true;
8295        boolean recoveringMemory = false;
8296
8297        try {
8298            if (mForceRemoves != null) {
8299                recoveringMemory = true;
8300                // Wait a little bit for things to settle down, and off we go.
8301                for (int i=0; i<mForceRemoves.size(); i++) {
8302                    WindowState ws = mForceRemoves.get(i);
8303                    Slog.i(TAG, "Force removing: " + ws);
8304                    removeWindowInnerLocked(ws.mSession, ws);
8305                }
8306                mForceRemoves = null;
8307                Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
8308                Object tmp = new Object();
8309                synchronized (tmp) {
8310                    try {
8311                        tmp.wait(250);
8312                    } catch (InterruptedException e) {
8313                    }
8314                }
8315            }
8316        } catch (RuntimeException e) {
8317            Log.wtf(TAG, "Unhandled exception while force removing for memory", e);
8318        }
8319
8320        try {
8321            performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
8322
8323            mInLayout = false;
8324
8325            if (needsLayout()) {
8326                if (++mLayoutRepeatCount < 6) {
8327                    requestTraversalLocked();
8328                } else {
8329                    Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
8330                    mLayoutRepeatCount = 0;
8331                }
8332            } else {
8333                mLayoutRepeatCount = 0;
8334            }
8335
8336            if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
8337                mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
8338                mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE);
8339            }
8340        } catch (RuntimeException e) {
8341            mInLayout = false;
8342            Log.wtf(TAG, "Unhandled exception while laying out windows", e);
8343        }
8344
8345        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
8346    }
8347
8348    private final void performLayoutLockedInner(final DisplayContent displayContent,
8349                                    boolean initial, boolean updateInputWindows) {
8350        if (!displayContent.layoutNeeded) {
8351            return;
8352        }
8353        displayContent.layoutNeeded = false;
8354        WindowList windows = displayContent.getWindowList();
8355        boolean isDefaultDisplay = displayContent.isDefaultDisplay;
8356
8357        DisplayInfo displayInfo = displayContent.getDisplayInfo();
8358        final int dw = displayInfo.logicalWidth;
8359        final int dh = displayInfo.logicalHeight;
8360
8361        final int NFW = mFakeWindows.size();
8362        for (int i=0; i<NFW; i++) {
8363            mFakeWindows.get(i).layout(dw, dh);
8364        }
8365
8366        final int N = windows.size();
8367        int i;
8368
8369        if (DEBUG_LAYOUT) {
8370            Slog.v(TAG, "-------------------------------------");
8371            Slog.v(TAG, "performLayout: needed="
8372                    + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
8373        }
8374
8375        WindowStateAnimator universeBackground = null;
8376
8377        mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
8378        if (isDefaultDisplay) {
8379            // Not needed on non-default displays.
8380            mSystemDecorLayer = mPolicy.getSystemDecorLayerLw();
8381            mScreenRect.set(0, 0, dw, dh);
8382        }
8383
8384        mPolicy.getContentRectLw(mTmpContentRect);
8385        displayContent.resize(mTmpContentRect);
8386
8387        int seq = mLayoutSeq+1;
8388        if (seq < 0) seq = 0;
8389        mLayoutSeq = seq;
8390
8391        boolean behindDream = false;
8392
8393        // First perform layout of any root windows (not attached
8394        // to another window).
8395        int topAttached = -1;
8396        for (i = N-1; i >= 0; i--) {
8397            final WindowState win = windows.get(i);
8398
8399            // Don't do layout of a window if it is not visible, or
8400            // soon won't be visible, to avoid wasting time and funky
8401            // changes while a window is animating away.
8402            final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs))
8403                    || win.isGoneForLayoutLw();
8404
8405            if (DEBUG_LAYOUT && !win.mLayoutAttached) {
8406                Slog.v(TAG, "1ST PASS " + win
8407                        + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
8408                        + " mLayoutAttached=" + win.mLayoutAttached
8409                        + " screen changed=" + win.isConfigChanged());
8410                final AppWindowToken atoken = win.mAppToken;
8411                if (gone) Slog.v(TAG, "  GONE: mViewVisibility="
8412                        + win.mViewVisibility + " mRelayoutCalled="
8413                        + win.mRelayoutCalled + " hidden="
8414                        + win.mRootToken.hidden + " hiddenRequested="
8415                        + (atoken != null && atoken.hiddenRequested)
8416                        + " mAttachedHidden=" + win.mAttachedHidden);
8417                else Slog.v(TAG, "  VIS: mViewVisibility="
8418                        + win.mViewVisibility + " mRelayoutCalled="
8419                        + win.mRelayoutCalled + " hidden="
8420                        + win.mRootToken.hidden + " hiddenRequested="
8421                        + (atoken != null && atoken.hiddenRequested)
8422                        + " mAttachedHidden=" + win.mAttachedHidden);
8423            }
8424
8425            // If this view is GONE, then skip it -- keep the current
8426            // frame, and let the caller know so they can ignore it
8427            // if they want.  (We do the normal layout for INVISIBLE
8428            // windows, since that means "perform layout as normal,
8429            // just don't display").
8430            if (!gone || !win.mHaveFrame || win.mLayoutNeeded
8431                    || ((win.isConfigChanged() || win.setInsetsChanged()) &&
8432                            (win.mAttrs.type == TYPE_KEYGUARD ||
8433                            win.mAppToken != null && win.mAppToken.layoutConfigChanges))
8434                    || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8435                if (!win.mLayoutAttached) {
8436                    if (initial) {
8437                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8438                        win.mContentChanged = false;
8439                    }
8440                    if (win.mAttrs.type == TYPE_DREAM) {
8441                        // Don't layout windows behind a dream, so that if it
8442                        // does stuff like hide the status bar we won't get a
8443                        // bad transition when it goes away.
8444                        behindDream = true;
8445                    }
8446                    win.mLayoutNeeded = false;
8447                    win.prelayout();
8448                    mPolicy.layoutWindowLw(win, win.mAttrs, null);
8449                    win.mLayoutSeq = seq;
8450                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8451                            + win.mFrame + " mContainingFrame="
8452                            + win.mContainingFrame + " mDisplayFrame="
8453                            + win.mDisplayFrame);
8454                } else {
8455                    if (topAttached < 0) topAttached = i;
8456                }
8457            }
8458            if (win.mViewVisibility == View.VISIBLE
8459                    && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
8460                    && universeBackground == null) {
8461                universeBackground = win.mWinAnimator;
8462            }
8463        }
8464
8465        if (mAnimator.mUniverseBackground  != universeBackground) {
8466            mFocusMayChange = true;
8467            mAnimator.mUniverseBackground = universeBackground;
8468        }
8469
8470        boolean attachedBehindDream = false;
8471
8472        // Now perform layout of attached windows, which usually
8473        // depend on the position of the window they are attached to.
8474        // XXX does not deal with windows that are attached to windows
8475        // that are themselves attached.
8476        for (i = topAttached; i >= 0; i--) {
8477            final WindowState win = windows.get(i);
8478
8479            if (win.mLayoutAttached) {
8480                if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win
8481                        + " mHaveFrame=" + win.mHaveFrame
8482                        + " mViewVisibility=" + win.mViewVisibility
8483                        + " mRelayoutCalled=" + win.mRelayoutCalled);
8484                // If this view is GONE, then skip it -- keep the current
8485                // frame, and let the caller know so they can ignore it
8486                // if they want.  (We do the normal layout for INVISIBLE
8487                // windows, since that means "perform layout as normal,
8488                // just don't display").
8489                if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) {
8490                    continue;
8491                }
8492                if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
8493                        || !win.mHaveFrame || win.mLayoutNeeded) {
8494                    if (initial) {
8495                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8496                        win.mContentChanged = false;
8497                    }
8498                    win.mLayoutNeeded = false;
8499                    win.prelayout();
8500                    mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
8501                    win.mLayoutSeq = seq;
8502                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8503                            + win.mFrame + " mContainingFrame="
8504                            + win.mContainingFrame + " mDisplayFrame="
8505                            + win.mDisplayFrame);
8506                }
8507            } else if (win.mAttrs.type == TYPE_DREAM) {
8508                // Don't layout windows behind a dream, so that if it
8509                // does stuff like hide the status bar we won't get a
8510                // bad transition when it goes away.
8511                attachedBehindDream = behindDream;
8512            }
8513        }
8514
8515        // Window frames may have changed.  Tell the input dispatcher about it.
8516        mInputMonitor.setUpdateInputWindowsNeededLw();
8517        if (updateInputWindows) {
8518            mInputMonitor.updateInputWindowsLw(false /*force*/);
8519        }
8520
8521        mPolicy.finishLayoutLw();
8522    }
8523
8524    void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
8525        // If the screen is currently frozen or off, then keep
8526        // it frozen/off until this window draws at its new
8527        // orientation.
8528        if (!okToDisplay()) {
8529            if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w);
8530            w.mOrientationChanging = true;
8531            w.mLastFreezeDuration = 0;
8532            mInnerFields.mOrientationChangeComplete = false;
8533            if (!mWindowsFreezingScreen) {
8534                mWindowsFreezingScreen = true;
8535                // XXX should probably keep timeout from
8536                // when we first froze the display.
8537                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
8538                mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
8539                        WINDOW_FREEZE_TIMEOUT_DURATION);
8540            }
8541        }
8542    }
8543
8544    /**
8545     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8546     * @param windows List of windows on default display.
8547     * @return bitmap indicating if another pass through layout must be made.
8548     */
8549    public int handleAppTransitionReadyLocked(WindowList windows) {
8550        int changes = 0;
8551        int i;
8552        int NN = mOpeningApps.size();
8553        boolean goodToGo = true;
8554        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8555                "Checking " + NN + " opening apps (frozen="
8556                + mDisplayFrozen + " timeout="
8557                + mAppTransition.isTimeout() + ")...");
8558        if (!mDisplayFrozen && !mAppTransition.isTimeout()) {
8559            // If the display isn't frozen, wait to do anything until
8560            // all of the apps are ready.  Otherwise just go because
8561            // we'll unfreeze the display when everyone is ready.
8562            for (i=0; i<NN && goodToGo; i++) {
8563                AppWindowToken wtoken = mOpeningApps.get(i);
8564                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8565                        "Check opening app=" + wtoken + ": allDrawn="
8566                        + wtoken.allDrawn + " startingDisplayed="
8567                        + wtoken.startingDisplayed + " startingMoved="
8568                        + wtoken.startingMoved);
8569                if (!wtoken.allDrawn && !wtoken.startingDisplayed
8570                        && !wtoken.startingMoved) {
8571                    goodToGo = false;
8572                }
8573            }
8574        }
8575        if (goodToGo) {
8576            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
8577            int transit = mAppTransition.getAppTransition();
8578            if (mSkipAppTransitionAnimation) {
8579                transit = AppTransition.TRANSIT_UNSET;
8580            }
8581            mAppTransition.goodToGo();
8582            mStartingIconInTransition = false;
8583            mSkipAppTransitionAnimation = false;
8584
8585            mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
8586
8587            rebuildAppWindowListLocked();
8588
8589            // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
8590            WindowState oldWallpaper =
8591                    mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
8592                        && !mWallpaperTarget.mWinAnimator.isDummyAnimation()
8593                    ? null : mWallpaperTarget;
8594
8595            mInnerFields.mWallpaperMayChange = false;
8596
8597            // The top-most window will supply the layout params,
8598            // and we will determine it below.
8599            LayoutParams animLp = null;
8600            int bestAnimLayer = -1;
8601            boolean fullscreenAnim = false;
8602
8603            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8604                    "New wallpaper target=" + mWallpaperTarget
8605                    + ", oldWallpaper=" + oldWallpaper
8606                    + ", lower target=" + mLowerWallpaperTarget
8607                    + ", upper target=" + mUpperWallpaperTarget);
8608
8609            boolean openingAppHasWallpaper = false;
8610            boolean closingAppHasWallpaper = false;
8611            final AppWindowToken lowerWallpaperAppToken;
8612            final AppWindowToken upperWallpaperAppToken;
8613            if (mLowerWallpaperTarget == null) {
8614                lowerWallpaperAppToken = upperWallpaperAppToken = null;
8615            } else {
8616                lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken;
8617                upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken;
8618            }
8619
8620            // Do a first pass through the tokens for two
8621            // things:
8622            // (1) Determine if both the closing and opening
8623            // app token sets are wallpaper targets, in which
8624            // case special animations are needed
8625            // (since the wallpaper needs to stay static
8626            // behind them).
8627            // (2) Find the layout params of the top-most
8628            // application window in the tokens, which is
8629            // what will control the animation theme.
8630            final int NC = mClosingApps.size();
8631            NN = NC + mOpeningApps.size();
8632            for (i=0; i<NN; i++) {
8633                final AppWindowToken wtoken;
8634                if (i < NC) {
8635                    wtoken = mClosingApps.get(i);
8636                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8637                        closingAppHasWallpaper = true;
8638                    }
8639                } else {
8640                    wtoken = mOpeningApps.get(i - NC);
8641                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8642                        openingAppHasWallpaper = true;
8643                    }
8644                }
8645
8646                if (wtoken.appFullscreen) {
8647                    WindowState ws = wtoken.findMainWindow();
8648                    if (ws != null) {
8649                        animLp = ws.mAttrs;
8650                        bestAnimLayer = ws.mLayer;
8651                        fullscreenAnim = true;
8652                    }
8653                } else if (!fullscreenAnim) {
8654                    WindowState ws = wtoken.findMainWindow();
8655                    if (ws != null) {
8656                        if (ws.mLayer > bestAnimLayer) {
8657                            animLp = ws.mAttrs;
8658                            bestAnimLayer = ws.mLayer;
8659                        }
8660                    }
8661                }
8662            }
8663
8664            mAnimateWallpaperWithTarget = false;
8665            if (closingAppHasWallpaper && openingAppHasWallpaper) {
8666                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
8667                switch (transit) {
8668                    case AppTransition.TRANSIT_ACTIVITY_OPEN:
8669                    case AppTransition.TRANSIT_TASK_OPEN:
8670                    case AppTransition.TRANSIT_TASK_TO_FRONT:
8671                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
8672                        break;
8673                    case AppTransition.TRANSIT_ACTIVITY_CLOSE:
8674                    case AppTransition.TRANSIT_TASK_CLOSE:
8675                    case AppTransition.TRANSIT_TASK_TO_BACK:
8676                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
8677                        break;
8678                }
8679                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit);
8680            } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty()
8681                    && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
8682                // We are transitioning from an activity with
8683                // a wallpaper to one without.
8684                transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
8685                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8686                        "New transit away from wallpaper: " + transit);
8687            } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
8688                // We are transitioning from an activity without
8689                // a wallpaper to now showing the wallpaper
8690                transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
8691                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8692                        "New transit into wallpaper: " + transit);
8693            } else {
8694                mAnimateWallpaperWithTarget = true;
8695            }
8696
8697            // If all closing windows are obscured, then there is
8698            // no need to do an animation.  This is the case, for
8699            // example, when this transition is being done behind
8700            // the lock screen.
8701            if (!mPolicy.allowAppAnimationsLw()) {
8702                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8703                        "Animations disallowed by keyguard or dream.");
8704                animLp = null;
8705            }
8706
8707            AppWindowToken topOpeningApp = null;
8708            int topOpeningLayer = 0;
8709
8710            NN = mOpeningApps.size();
8711            for (i=0; i<NN; i++) {
8712                AppWindowToken wtoken = mOpeningApps.get(i);
8713                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
8714                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
8715                appAnimator.clearThumbnail();
8716                wtoken.inPendingTransaction = false;
8717                appAnimator.animation = null;
8718                setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
8719                wtoken.updateReportedVisibilityLocked();
8720                wtoken.waitingToShow = false;
8721
8722                appAnimator.mAllAppWinAnimators.clear();
8723                final int N = wtoken.allAppWindows.size();
8724                for (int j = 0; j < N; j++) {
8725                    appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
8726                }
8727                mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
8728
8729                if (animLp != null) {
8730                    int layer = -1;
8731                    for (int j=0; j<wtoken.windows.size(); j++) {
8732                        WindowState win = wtoken.windows.get(j);
8733                        if (win.mWinAnimator.mAnimLayer > layer) {
8734                            layer = win.mWinAnimator.mAnimLayer;
8735                        }
8736                    }
8737                    if (topOpeningApp == null || layer > topOpeningLayer) {
8738                        topOpeningApp = wtoken;
8739                        topOpeningLayer = layer;
8740                    }
8741                }
8742            }
8743            NN = mClosingApps.size();
8744            for (i=0; i<NN; i++) {
8745                AppWindowToken wtoken = mClosingApps.get(i);
8746                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
8747                wtoken.mAppAnimator.clearThumbnail();
8748                wtoken.inPendingTransaction = false;
8749                wtoken.mAppAnimator.animation = null;
8750                setTokenVisibilityLocked(wtoken, animLp, false, transit, false);
8751                wtoken.updateReportedVisibilityLocked();
8752                wtoken.waitingToHide = false;
8753                // Force the allDrawn flag, because we want to start
8754                // this guy's animations regardless of whether it's
8755                // gotten drawn.
8756                wtoken.allDrawn = true;
8757                wtoken.deferClearAllDrawn = false;
8758            }
8759
8760            AppWindowAnimator appAnimator =
8761                    topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
8762            Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
8763            if (nextAppTransitionThumbnail != null && appAnimator != null
8764                    && appAnimator.animation != null) {
8765                // This thumbnail animation is very special, we need to have
8766                // an extra surface with the thumbnail included with the animation.
8767                Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
8768                        nextAppTransitionThumbnail.getHeight());
8769                try {
8770                    // TODO(multi-display): support other displays
8771                    final DisplayContent displayContent = getDefaultDisplayContentLocked();
8772                    final Display display = displayContent.getDisplay();
8773                    SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
8774                            "thumbnail anim",
8775                            dirty.width(), dirty.height(),
8776                            PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
8777                    surfaceControl.setLayerStack(display.getLayerStack());
8778                    appAnimator.thumbnail = surfaceControl;
8779                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
8780                    Surface drawSurface = new Surface();
8781                    drawSurface.copyFrom(surfaceControl);
8782                    Canvas c = drawSurface.lockCanvas(dirty);
8783                    c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
8784                    drawSurface.unlockCanvasAndPost(c);
8785                    drawSurface.release();
8786                    appAnimator.thumbnailLayer = topOpeningLayer;
8787                    DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
8788                    Animation anim = mAppTransition.createThumbnailAnimationLocked(
8789                            transit, true, true, displayInfo.appWidth, displayInfo.appHeight);
8790                    appAnimator.thumbnailAnimation = anim;
8791                    anim.restrictDuration(MAX_ANIMATION_DURATION);
8792                    anim.scaleCurrentDuration(mTransitionAnimationScale);
8793                    Point p = new Point();
8794                    mAppTransition.getStartingPoint(p);
8795                    appAnimator.thumbnailX = p.x;
8796                    appAnimator.thumbnailY = p.y;
8797                } catch (OutOfResourcesException e) {
8798                    Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
8799                            + " h=" + dirty.height(), e);
8800                    appAnimator.clearThumbnail();
8801                }
8802            }
8803
8804            mAppTransition.postAnimationCallback();
8805            mAppTransition.clear();
8806
8807            mOpeningApps.clear();
8808            mClosingApps.clear();
8809
8810            // This has changed the visibility of windows, so perform
8811            // a new layout to get them all up-to-date.
8812            changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
8813                    | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
8814            getDefaultDisplayContentLocked().layoutNeeded = true;
8815
8816            // TODO(multidisplay): IMEs are only supported on the default display.
8817            if (windows == getDefaultWindowListLocked()
8818                    && !moveInputMethodWindowsIfNeededLocked(true)) {
8819                assignLayersLocked(windows);
8820            }
8821            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/);
8822            mFocusMayChange = false;
8823        }
8824
8825        return changes;
8826    }
8827
8828    /**
8829     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8830     * @return bitmap indicating if another pass through layout must be made.
8831     */
8832    private int handleAnimatingStoppedAndTransitionLocked() {
8833        int changes = 0;
8834
8835        mAppTransition.setIdle();
8836        // Restore window app tokens to the ActivityManager views
8837        ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks();
8838        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
8839            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
8840            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
8841                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8842                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
8843                    tokens.get(tokenNdx).sendingToBottom = false;
8844                }
8845            }
8846        }
8847        rebuildAppWindowListLocked();
8848
8849        changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
8850        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
8851                "Wallpaper layer changed: assigning layers + relayout");
8852        moveInputMethodWindowsIfNeededLocked(true);
8853        mInnerFields.mWallpaperMayChange = true;
8854        // Since the window list has been rebuilt, focus might
8855        // have to be recomputed since the actual order of windows
8856        // might have changed again.
8857        mFocusMayChange = true;
8858
8859        return changes;
8860    }
8861
8862    private void updateResizingWindows(final WindowState w) {
8863        final WindowStateAnimator winAnimator = w.mWinAnimator;
8864        if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
8865            w.setInsetsChanged();
8866            boolean configChanged = w.isConfigChanged();
8867            if (DEBUG_CONFIGURATION && configChanged) {
8868                Slog.v(TAG, "Win " + w + " config changed: "
8869                        + mCurConfiguration);
8870            }
8871            if (localLOGV) Slog.v(TAG, "Resizing " + w
8872                    + ": configChanged=" + configChanged
8873                    + " last=" + w.mLastFrame + " frame=" + w.mFrame);
8874            w.mLastFrame.set(w.mFrame);
8875            if (w.mContentInsetsChanged
8876                    || w.mVisibleInsetsChanged
8877                    || winAnimator.mSurfaceResized
8878                    || configChanged) {
8879                if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
8880                    Slog.v(TAG, "Resize reasons for w=" + w + ": "
8881                            + " contentInsetsChanged=" + w.mContentInsetsChanged
8882                            + " " + w.mContentInsets.toShortString()
8883                            + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
8884                            + " " + w.mVisibleInsets.toShortString()
8885                            + " surfaceResized=" + winAnimator.mSurfaceResized
8886                            + " configChanged=" + configChanged);
8887                }
8888
8889                w.mLastOverscanInsets.set(w.mOverscanInsets);
8890                w.mLastContentInsets.set(w.mContentInsets);
8891                w.mLastVisibleInsets.set(w.mVisibleInsets);
8892                makeWindowFreezingScreenIfNeededLocked(w);
8893                // If the orientation is changing, then we need to
8894                // hold off on unfreezing the display until this
8895                // window has been redrawn; to do that, we need
8896                // to go through the process of getting informed
8897                // by the application when it has finished drawing.
8898                if (w.mOrientationChanging) {
8899                    if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG,
8900                            "Orientation start waiting for draw mDrawState=DRAW_PENDING in "
8901                            + w + ", surface " + winAnimator.mSurfaceControl);
8902                    winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
8903                    if (w.mAppToken != null) {
8904                        w.mAppToken.allDrawn = false;
8905                        w.mAppToken.deferClearAllDrawn = false;
8906                    }
8907                }
8908                if (!mResizingWindows.contains(w)) {
8909                    if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
8910                            "Resizing window " + w + " to " + winAnimator.mSurfaceW
8911                            + "x" + winAnimator.mSurfaceH);
8912                    mResizingWindows.add(w);
8913                }
8914            } else if (w.mOrientationChanging) {
8915                if (w.isDrawnLw()) {
8916                    if (DEBUG_ORIENTATION) Slog.v(TAG,
8917                            "Orientation not waiting for draw in "
8918                            + w + ", surface " + winAnimator.mSurfaceControl);
8919                    w.mOrientationChanging = false;
8920                    w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
8921                            - mDisplayFreezeTime);
8922                }
8923            }
8924        }
8925    }
8926
8927    /**
8928     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8929     *
8930     * @param w WindowState this method is applied to.
8931     * @param currentTime The time which animations use for calculating transitions.
8932     * @param innerDw Width of app window.
8933     * @param innerDh Height of app window.
8934     */
8935    private void handleNotObscuredLocked(final WindowState w, final long currentTime,
8936                                         final int innerDw, final int innerDh) {
8937        final WindowManager.LayoutParams attrs = w.mAttrs;
8938        final int attrFlags = attrs.flags;
8939        final boolean canBeSeen = w.isDisplayedLw();
8940        final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
8941
8942        if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
8943            // This window completely covers everything behind it,
8944            // so we want to leave all of them as undimmed (for
8945            // performance reasons).
8946            mInnerFields.mObscured = true;
8947        }
8948
8949        if (w.mHasSurface) {
8950            if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
8951                mInnerFields.mHoldScreen = w.mSession;
8952            }
8953            if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0
8954                    && mInnerFields.mScreenBrightness < 0) {
8955                mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness;
8956            }
8957            if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0
8958                    && mInnerFields.mButtonBrightness < 0) {
8959                mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness;
8960            }
8961            if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0
8962                    && mInnerFields.mUserActivityTimeout < 0) {
8963                mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout;
8964            }
8965
8966            final int type = attrs.type;
8967            if (canBeSeen
8968                    && (type == TYPE_SYSTEM_DIALOG
8969                     || type == TYPE_RECENTS_OVERLAY
8970                     || type == TYPE_KEYGUARD
8971                     || type == TYPE_SYSTEM_ERROR)) {
8972                mInnerFields.mSyswin = true;
8973            }
8974
8975            if (canBeSeen) {
8976                // This function assumes that the contents of the default display are
8977                // processed first before secondary displays.
8978                final DisplayContent displayContent = w.getDisplayContent();
8979                if (displayContent != null && displayContent.isDefaultDisplay) {
8980                    // While a dream or keyguard is showing, obscure ordinary application
8981                    // content on secondary displays (by forcibly enabling mirroring unless
8982                    // there is other content we want to show) but still allow opaque
8983                    // keyguard dialogs to be shown.
8984                    if (type == TYPE_DREAM || type == TYPE_KEYGUARD) {
8985                        mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true;
8986                    }
8987                    mInnerFields.mDisplayHasContent = true;
8988                } else if (displayContent != null &&
8989                        (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays
8990                        || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) {
8991                    // Allow full screen keyguard presentation dialogs to be seen.
8992                    mInnerFields.mDisplayHasContent = true;
8993                }
8994            }
8995        }
8996    }
8997
8998    private void handleFlagDimBehind(WindowState w) {
8999        final WindowManager.LayoutParams attrs = w.mAttrs;
9000        if ((attrs.flags & FLAG_DIM_BEHIND) != 0
9001                && w.isDisplayedLw()
9002                && !w.mExiting) {
9003            final WindowStateAnimator winAnimator = w.mWinAnimator;
9004            final TaskStack stack = w.getStack();
9005            stack.setDimmingTag();
9006            if (!stack.isDimming(winAnimator)) {
9007                if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming.");
9008                stack.startDimmingIfNeeded(winAnimator);
9009            }
9010        }
9011    }
9012
9013    private void updateAllDrawnLocked(DisplayContent displayContent) {
9014        // See if any windows have been drawn, so they (and others
9015        // associated with them) can now be shown.
9016        ArrayList<TaskStack> stacks = displayContent.getStacks();
9017        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
9018            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
9019            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9020                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9021                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9022                    final AppWindowToken wtoken = tokens.get(tokenNdx);
9023                    if (!wtoken.allDrawn) {
9024                        int numInteresting = wtoken.numInterestingWindows;
9025                        if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
9026                            if (DEBUG_VISIBILITY) Slog.v(TAG,
9027                                    "allDrawn: " + wtoken
9028                                    + " interesting=" + numInteresting
9029                                    + " drawn=" + wtoken.numDrawnWindows);
9030                            wtoken.allDrawn = true;
9031                            mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget();
9032                        }
9033                    }
9034                }
9035            }
9036        }
9037    }
9038
9039    // "Something has changed!  Let's make it correct now."
9040    private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
9041        if (DEBUG_WINDOW_TRACE) {
9042            Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
9043                    + Debug.getCallers(3));
9044        }
9045
9046        final long currentTime = SystemClock.uptimeMillis();
9047
9048        int i;
9049
9050        if (mFocusMayChange) {
9051            mFocusMayChange = false;
9052            updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
9053                    false /*updateInputWindows*/);
9054        }
9055
9056        // Initialize state of exiting tokens.
9057        final int numDisplays = mDisplayContents.size();
9058        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9059            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9060            for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
9061                displayContent.mExitingTokens.get(i).hasVisible = false;
9062            }
9063        }
9064
9065        for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
9066            // Initialize state of exiting applications.
9067            final AppTokenList exitingAppTokens =
9068                    mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
9069            for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9070                exitingAppTokens.get(tokenNdx).hasVisible = false;
9071            }
9072        }
9073
9074        mInnerFields.mHoldScreen = null;
9075        mInnerFields.mScreenBrightness = -1;
9076        mInnerFields.mButtonBrightness = -1;
9077        mInnerFields.mUserActivityTimeout = -1;
9078        mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false;
9079
9080        mTransactionSequence++;
9081
9082        final DisplayContent defaultDisplay = getDefaultDisplayContentLocked();
9083        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
9084        final int defaultDw = defaultInfo.logicalWidth;
9085        final int defaultDh = defaultInfo.logicalHeight;
9086
9087        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
9088                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
9089        SurfaceControl.openTransaction();
9090        try {
9091
9092            if (mWatermark != null) {
9093                mWatermark.positionSurface(defaultDw, defaultDh);
9094            }
9095            if (mStrictModeFlash != null) {
9096                mStrictModeFlash.positionSurface(defaultDw, defaultDh);
9097            }
9098            if (mCircularDisplayMask != null) {
9099                mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation);
9100            }
9101
9102            boolean focusDisplayed = false;
9103
9104            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9105                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9106                boolean updateAllDrawn = false;
9107                WindowList windows = displayContent.getWindowList();
9108                DisplayInfo displayInfo = displayContent.getDisplayInfo();
9109                final int displayId = displayContent.getDisplayId();
9110                final int dw = displayInfo.logicalWidth;
9111                final int dh = displayInfo.logicalHeight;
9112                final int innerDw = displayInfo.appWidth;
9113                final int innerDh = displayInfo.appHeight;
9114                final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
9115
9116                // Reset for each display.
9117                mInnerFields.mDisplayHasContent = false;
9118
9119                int repeats = 0;
9120                do {
9121                    repeats++;
9122                    if (repeats > 6) {
9123                        Slog.w(TAG, "Animation repeat aborted after too many iterations");
9124                        displayContent.layoutNeeded = false;
9125                        break;
9126                    }
9127
9128                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
9129                        displayContent.pendingLayoutChanges);
9130
9131                    if ((displayContent.pendingLayoutChanges &
9132                            WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
9133                            (adjustWallpaperWindowsLocked() &
9134                                    ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
9135                        assignLayersLocked(windows);
9136                        displayContent.layoutNeeded = true;
9137                    }
9138
9139                    if (isDefaultDisplay && (displayContent.pendingLayoutChanges
9140                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
9141                        if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
9142                        if (updateOrientationFromAppTokensLocked(true)) {
9143                            displayContent.layoutNeeded = true;
9144                            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9145                        }
9146                    }
9147
9148                    if ((displayContent.pendingLayoutChanges
9149                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9150                        displayContent.layoutNeeded = true;
9151                    }
9152
9153                    // FIRST LOOP: Perform a layout, if needed.
9154                    if (repeats < 4) {
9155                        performLayoutLockedInner(displayContent, repeats == 1,
9156                                false /*updateInputWindows*/);
9157                    } else {
9158                        Slog.w(TAG, "Layout repeat skipped after too many iterations");
9159                    }
9160
9161                    // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
9162                    // it is animating.
9163                    displayContent.pendingLayoutChanges = 0;
9164
9165                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number "
9166                            + mLayoutRepeatCount, displayContent.pendingLayoutChanges);
9167
9168                    if (isDefaultDisplay) {
9169                        mPolicy.beginPostLayoutPolicyLw(dw, dh);
9170                        for (i = windows.size() - 1; i >= 0; i--) {
9171                            WindowState w = windows.get(i);
9172                            if (w.mHasSurface) {
9173                                mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs);
9174                            }
9175                        }
9176                        displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw();
9177                        if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
9178                            "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges);
9179                    }
9180                } while (displayContent.pendingLayoutChanges != 0);
9181
9182                mInnerFields.mObscured = false;
9183                mInnerFields.mSyswin = false;
9184                displayContent.resetDimming();
9185
9186                // Only used if default window
9187                final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
9188
9189                final int N = windows.size();
9190                for (i=N-1; i>=0; i--) {
9191                    WindowState w = windows.get(i);
9192                    final TaskStack stack = w.getStack();
9193                    if (stack == null) {
9194                        continue;
9195                    }
9196
9197                    final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
9198
9199                    // Update effect.
9200                    w.mObscured = mInnerFields.mObscured;
9201                    if (!mInnerFields.mObscured) {
9202                        handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
9203                    }
9204
9205                    if (!stack.testDimmingTag()) {
9206                        handleFlagDimBehind(w);
9207                    }
9208
9209                    if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
9210                            && w.isVisibleLw()) {
9211                        // This is the wallpaper target and its obscured state
9212                        // changed... make sure the current wallaper's visibility
9213                        // has been updated accordingly.
9214                        updateWallpaperVisibilityLocked();
9215                    }
9216
9217                    final WindowStateAnimator winAnimator = w.mWinAnimator;
9218
9219                    // If the window has moved due to its containing
9220                    // content frame changing, then we'd like to animate
9221                    // it.
9222                    if (w.mHasSurface && w.shouldAnimateMove()) {
9223                        // Frame has moved, containing content frame
9224                        // has also moved, and we're not currently animating...
9225                        // let's do something.
9226                        Animation a = AnimationUtils.loadAnimation(mContext,
9227                                com.android.internal.R.anim.window_move_from_decor);
9228                        winAnimator.setAnimation(a);
9229                        winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
9230                        winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
9231                        try {
9232                            w.mClient.moved(w.mFrame.left, w.mFrame.top);
9233                        } catch (RemoteException e) {
9234                        }
9235                    }
9236
9237                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
9238                    w.mContentChanged = false;
9239
9240                    // Moved from updateWindowsAndWallpaperLocked().
9241                    if (w.mHasSurface) {
9242                        // Take care of the window being ready to display.
9243                        final boolean committed =
9244                                winAnimator.commitFinishDrawingLocked(currentTime);
9245                        if (isDefaultDisplay && committed) {
9246                            if (w.mAttrs.type == TYPE_DREAM) {
9247                                // HACK: When a dream is shown, it may at that
9248                                // point hide the lock screen.  So we need to
9249                                // redo the layout to let the phone window manager
9250                                // make this happen.
9251                                displayContent.pendingLayoutChanges |=
9252                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9253                                if (DEBUG_LAYOUT_REPEATS) {
9254                                    debugLayoutRepeats(
9255                                        "dream and commitFinishDrawingLocked true",
9256                                        displayContent.pendingLayoutChanges);
9257                                }
9258                            }
9259                            if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
9260                                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
9261                                        "First draw done in potential wallpaper target " + w);
9262                                mInnerFields.mWallpaperMayChange = true;
9263                                displayContent.pendingLayoutChanges |=
9264                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9265                                if (DEBUG_LAYOUT_REPEATS) {
9266                                    debugLayoutRepeats(
9267                                        "wallpaper and commitFinishDrawingLocked true",
9268                                        displayContent.pendingLayoutChanges);
9269                                }
9270                            }
9271                        }
9272
9273                        winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
9274
9275                        final AppWindowToken atoken = w.mAppToken;
9276                        if (DEBUG_STARTING_WINDOW && atoken != null
9277                                && w == atoken.startingWindow) {
9278                            Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
9279                                + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
9280                                + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
9281                        }
9282                        if (atoken != null
9283                                && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
9284                            if (atoken.lastTransactionSequence != mTransactionSequence) {
9285                                atoken.lastTransactionSequence = mTransactionSequence;
9286                                atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
9287                                atoken.startingDisplayed = false;
9288                            }
9289                            if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
9290                                    && !w.mExiting && !w.mDestroying) {
9291                                if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
9292                                    Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
9293                                            + ", isAnimating=" + winAnimator.isAnimating());
9294                                    if (!w.isDrawnLw()) {
9295                                        Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
9296                                                + " pv=" + w.mPolicyVisibility
9297                                                + " mDrawState=" + winAnimator.mDrawState
9298                                                + " ah=" + w.mAttachedHidden
9299                                                + " th=" + atoken.hiddenRequested
9300                                                + " a=" + winAnimator.mAnimating);
9301                                    }
9302                                }
9303                                if (w != atoken.startingWindow) {
9304                                    if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
9305                                        atoken.numInterestingWindows++;
9306                                        if (w.isDrawnLw()) {
9307                                            atoken.numDrawnWindows++;
9308                                            if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
9309                                                    "tokenMayBeDrawn: " + atoken
9310                                                    + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
9311                                                    + " mAppFreezing=" + w.mAppFreezing);
9312                                            updateAllDrawn = true;
9313                                        }
9314                                    }
9315                                } else if (w.isDrawnLw()) {
9316                                    atoken.startingDisplayed = true;
9317                                }
9318                            }
9319                        }
9320                    }
9321
9322                    if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus)
9323                            && w.isDisplayedLw()) {
9324                        focusDisplayed = true;
9325                    }
9326
9327                    updateResizingWindows(w);
9328                }
9329
9330                mDisplayManagerInternal.setDisplayHasContent(displayId,
9331                        mInnerFields.mDisplayHasContent,
9332                        true /* inTraversal, must call performTraversalInTrans... below */);
9333
9334                getDisplayContentLocked(displayId).stopDimmingIfNeeded();
9335
9336                if (updateAllDrawn) {
9337                    updateAllDrawnLocked(displayContent);
9338                }
9339            }
9340
9341            if (focusDisplayed) {
9342                mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
9343            }
9344
9345            // Give the display manager a chance to adjust properties
9346            // like display rotation if it needs to.
9347            mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
9348
9349        } catch (RuntimeException e) {
9350            Log.wtf(TAG, "Unhandled exception in Window Manager", e);
9351        } finally {
9352            SurfaceControl.closeTransaction();
9353            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
9354                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
9355        }
9356
9357        final WindowList defaultWindows = defaultDisplay.getWindowList();
9358
9359        // If we are ready to perform an app transition, check through
9360        // all of the app tokens to be shown and see if they are ready
9361        // to go.
9362        if (mAppTransition.isReady()) {
9363            defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
9364            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
9365                    defaultDisplay.pendingLayoutChanges);
9366        }
9367
9368        if (!mAnimator.mAnimating && mAppTransition.isRunning()) {
9369            // We have finished the animation of an app transition.  To do
9370            // this, we have delayed a lot of operations like showing and
9371            // hiding apps, moving apps in Z-order, etc.  The app token list
9372            // reflects the correct Z-order, but the window list may now
9373            // be out of sync with it.  So here we will just rebuild the
9374            // entire app window list.  Fun!
9375            defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
9376            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock",
9377                defaultDisplay.pendingLayoutChanges);
9378        }
9379
9380        if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
9381                && !mAppTransition.isReady()) {
9382            // At this point, there was a window with a wallpaper that
9383            // was force hiding other windows behind it, but now it
9384            // is going away.  This may be simple -- just animate
9385            // away the wallpaper and its window -- or it may be
9386            // hard -- the wallpaper now needs to be shown behind
9387            // something that was hidden.
9388            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9389            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked",
9390                defaultDisplay.pendingLayoutChanges);
9391        }
9392        mInnerFields.mWallpaperForceHidingChanged = false;
9393
9394        if (mInnerFields.mWallpaperMayChange) {
9395            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change!  Adjusting");
9396            defaultDisplay.pendingLayoutChanges |=
9397                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9398            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
9399                    defaultDisplay.pendingLayoutChanges);
9400        }
9401
9402        if (mFocusMayChange) {
9403            mFocusMayChange = false;
9404            if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
9405                    false /*updateInputWindows*/)) {
9406                defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
9407            }
9408        }
9409
9410        if (needsLayout()) {
9411            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9412            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
9413                    defaultDisplay.pendingLayoutChanges);
9414        }
9415
9416        for (i = mResizingWindows.size() - 1; i >= 0; i--) {
9417            WindowState win = mResizingWindows.get(i);
9418            if (win.mAppFreezing) {
9419                // Don't remove this window until rotation has completed.
9420                continue;
9421            }
9422            win.reportResized();
9423            mResizingWindows.remove(i);
9424        }
9425
9426        if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
9427                "With display frozen, orientationChangeComplete="
9428                + mInnerFields.mOrientationChangeComplete);
9429        if (mInnerFields.mOrientationChangeComplete) {
9430            if (mWindowsFreezingScreen) {
9431                mWindowsFreezingScreen = false;
9432                mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource;
9433                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
9434            }
9435            stopFreezingDisplayLocked();
9436        }
9437
9438        // Destroy the surface of any windows that are no longer visible.
9439        boolean wallpaperDestroyed = false;
9440        i = mDestroySurface.size();
9441        if (i > 0) {
9442            do {
9443                i--;
9444                WindowState win = mDestroySurface.get(i);
9445                win.mDestroying = false;
9446                if (mInputMethodWindow == win) {
9447                    mInputMethodWindow = null;
9448                }
9449                if (win == mWallpaperTarget) {
9450                    wallpaperDestroyed = true;
9451                }
9452                win.mWinAnimator.destroySurfaceLocked();
9453            } while (i > 0);
9454            mDestroySurface.clear();
9455        }
9456
9457        // Time to remove any exiting tokens?
9458        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9459            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9460            ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
9461            for (i = exitingTokens.size() - 1; i >= 0; i--) {
9462                WindowToken token = exitingTokens.get(i);
9463                if (!token.hasVisible) {
9464                    exitingTokens.remove(i);
9465                    if (token.windowType == TYPE_WALLPAPER) {
9466                        mWallpaperTokens.remove(token);
9467                    }
9468                }
9469            }
9470        }
9471
9472        // Time to remove any exiting applications?
9473        for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
9474            // Initialize state of exiting applications.
9475            final AppTokenList exitingAppTokens =
9476                    mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
9477            for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
9478                AppWindowToken token = exitingAppTokens.get(i);
9479                if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) {
9480                    // Make sure there is no animation running on this token,
9481                    // so any windows associated with it will be removed as
9482                    // soon as their animations are complete
9483                    token.mAppAnimator.clearAnimation();
9484                    token.mAppAnimator.animating = false;
9485                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
9486                            "performLayout: App token exiting now removed" + token);
9487                    removeAppFromTaskLocked(token);
9488                    exitingAppTokens.remove(i);
9489                }
9490            }
9491        }
9492
9493        if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) {
9494            for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) {
9495                try {
9496                    mRelayoutWhileAnimating.get(j).mClient.doneAnimating();
9497                } catch (RemoteException e) {
9498                }
9499            }
9500            mRelayoutWhileAnimating.clear();
9501        }
9502
9503        if (wallpaperDestroyed) {
9504            defaultDisplay.pendingLayoutChanges |=
9505                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9506            defaultDisplay.layoutNeeded = true;
9507        }
9508
9509        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9510            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9511            if (displayContent.pendingLayoutChanges != 0) {
9512                displayContent.layoutNeeded = true;
9513            }
9514        }
9515
9516        // Finally update all input windows now that the window changes have stabilized.
9517        mInputMonitor.updateInputWindowsLw(true /*force*/);
9518
9519        setHoldScreenLocked(mInnerFields.mHoldScreen);
9520        if (!mDisplayFrozen) {
9521            if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
9522                mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
9523            } else {
9524                mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
9525                        toBrightnessOverride(mInnerFields.mScreenBrightness));
9526            }
9527            if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
9528                mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
9529            } else {
9530                mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
9531                        toBrightnessOverride(mInnerFields.mButtonBrightness));
9532            }
9533            mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
9534                    mInnerFields.mUserActivityTimeout);
9535        }
9536
9537        if (mTurnOnScreen) {
9538            if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
9539            mPowerManager.wakeUp(SystemClock.uptimeMillis());
9540            mTurnOnScreen = false;
9541        }
9542
9543        if (mInnerFields.mUpdateRotation) {
9544            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
9545            if (updateRotationUncheckedLocked(false)) {
9546                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9547            } else {
9548                mInnerFields.mUpdateRotation = false;
9549            }
9550        }
9551
9552        if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded
9553                && !mInnerFields.mUpdateRotation) {
9554            checkDrawnWindowsLocked();
9555        }
9556
9557        final int N = mPendingRemove.size();
9558        if (N > 0) {
9559            if (mPendingRemoveTmp.length < N) {
9560                mPendingRemoveTmp = new WindowState[N+10];
9561            }
9562            mPendingRemove.toArray(mPendingRemoveTmp);
9563            mPendingRemove.clear();
9564            DisplayContentList displayList = new DisplayContentList();
9565            for (i = 0; i < N; i++) {
9566                WindowState w = mPendingRemoveTmp[i];
9567                removeWindowInnerLocked(w.mSession, w);
9568                final DisplayContent displayContent = w.getDisplayContent();
9569                if (displayContent != null && !displayList.contains(displayContent)) {
9570                    displayList.add(displayContent);
9571                }
9572            }
9573
9574            for (DisplayContent displayContent : displayList) {
9575                assignLayersLocked(displayContent.getWindowList());
9576                displayContent.layoutNeeded = true;
9577            }
9578        }
9579
9580        // Remove all deferred displays stacks, tasks, and activities.
9581        for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
9582            mDisplayContents.valueAt(displayNdx).checkForDeferredActions();
9583        }
9584
9585        setFocusedStackFrame();
9586
9587        // Check to see if we are now in a state where the screen should
9588        // be enabled, because the window obscured flags have changed.
9589        enableScreenIfNeededLocked();
9590
9591        scheduleAnimationLocked();
9592
9593        if (DEBUG_WINDOW_TRACE) {
9594            Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating="
9595                    + mAnimator.mAnimating);
9596        }
9597    }
9598
9599    private int toBrightnessOverride(float value) {
9600        return (int)(value * PowerManager.BRIGHTNESS_ON);
9601    }
9602
9603    void checkDrawnWindowsLocked() {
9604        if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
9605            return;
9606        }
9607        for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
9608            WindowState win = mWaitingForDrawn.get(j);
9609            if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win +
9610                    ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
9611                    " mHasSurface=" + win.mHasSurface +
9612                    " drawState=" + win.mWinAnimator.mDrawState);
9613            if (win.mRemoved || !win.mHasSurface) {
9614                // Window has been removed; no draw will now happen, so stop waiting.
9615                if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win);
9616                mWaitingForDrawn.remove(win);
9617            } else if (win.hasDrawnLw()) {
9618                // Window is now drawn (and shown).
9619                if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win);
9620                mWaitingForDrawn.remove(win);
9621            }
9622        }
9623        if (mWaitingForDrawn.isEmpty()) {
9624            if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!");
9625            mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
9626            mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
9627        }
9628    }
9629
9630    void setHoldScreenLocked(final Session newHoldScreen) {
9631        final boolean hold = newHoldScreen != null;
9632
9633        if (hold && mHoldingScreenOn != newHoldScreen) {
9634            mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
9635        }
9636        mHoldingScreenOn = newHoldScreen;
9637
9638        final boolean state = mHoldingScreenWakeLock.isHeld();
9639        if (hold != state) {
9640            if (hold) {
9641                mHoldingScreenWakeLock.acquire();
9642                mPolicy.keepScreenOnStartedLw();
9643            } else {
9644                mPolicy.keepScreenOnStoppedLw();
9645                mHoldingScreenWakeLock.release();
9646            }
9647        }
9648    }
9649
9650    void requestTraversal() {
9651        synchronized (mWindowMap) {
9652            requestTraversalLocked();
9653        }
9654    }
9655
9656    void requestTraversalLocked() {
9657        if (!mTraversalScheduled) {
9658            mTraversalScheduled = true;
9659            mH.sendEmptyMessage(H.DO_TRAVERSAL);
9660        }
9661    }
9662
9663    /** Note that Locked in this case is on mLayoutToAnim */
9664    void scheduleAnimationLocked() {
9665        if (!mAnimationScheduled) {
9666            mAnimationScheduled = true;
9667            mChoreographer.postCallback(
9668                    Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);
9669        }
9670    }
9671
9672    private boolean needsLayout() {
9673        final int numDisplays = mDisplayContents.size();
9674        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9675            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9676            if (displayContent.layoutNeeded) {
9677                return true;
9678            }
9679        }
9680        return false;
9681    }
9682
9683    boolean copyAnimToLayoutParamsLocked() {
9684        boolean doRequest = false;
9685
9686        final int bulkUpdateParams = mAnimator.mBulkUpdateParams;
9687        if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
9688            mInnerFields.mUpdateRotation = true;
9689            doRequest = true;
9690        }
9691        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
9692            mInnerFields.mWallpaperMayChange = true;
9693            doRequest = true;
9694        }
9695        if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
9696            mInnerFields.mWallpaperForceHidingChanged = true;
9697            doRequest = true;
9698        }
9699        if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
9700            mInnerFields.mOrientationChangeComplete = false;
9701        } else {
9702            mInnerFields.mOrientationChangeComplete = true;
9703            mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource;
9704            if (mWindowsFreezingScreen) {
9705                doRequest = true;
9706            }
9707        }
9708        if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
9709            mTurnOnScreen = true;
9710        }
9711        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) {
9712            mInnerFields.mWallpaperActionPending = true;
9713        }
9714
9715        return doRequest;
9716    }
9717
9718    /** If a window that has an animation specifying a colored background and the current wallpaper
9719     * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
9720     * suddenly disappear. */
9721    int adjustAnimationBackground(WindowStateAnimator winAnimator) {
9722        WindowList windows = winAnimator.mWin.getWindowList();
9723        for (int i = windows.size() - 1; i >= 0; --i) {
9724            WindowState testWin = windows.get(i);
9725            if (testWin.mIsWallpaper && testWin.isVisibleNow()) {
9726                return testWin.mWinAnimator.mAnimLayer;
9727            }
9728        }
9729        return winAnimator.mAnimLayer;
9730    }
9731
9732    boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
9733                                           boolean secure) {
9734        final SurfaceControl surface = winAnimator.mSurfaceControl;
9735        boolean leakedSurface = false;
9736        boolean killedApps = false;
9737
9738        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
9739                winAnimator.mSession.mPid, operation);
9740
9741        if (mForceRemoves == null) {
9742            mForceRemoves = new ArrayList<WindowState>();
9743        }
9744
9745        long callingIdentity = Binder.clearCallingIdentity();
9746        try {
9747            // There was some problem...   first, do a sanity check of the
9748            // window list to make sure we haven't left any dangling surfaces
9749            // around.
9750
9751            Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
9752            final int numDisplays = mDisplayContents.size();
9753            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9754                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9755                final int numWindows = windows.size();
9756                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9757                    final WindowState ws = windows.get(winNdx);
9758                    WindowStateAnimator wsa = ws.mWinAnimator;
9759                    if (wsa.mSurfaceControl != null) {
9760                        if (!mSessions.contains(wsa.mSession)) {
9761                            Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
9762                                    + ws + " surface=" + wsa.mSurfaceControl
9763                                    + " token=" + ws.mToken
9764                                    + " pid=" + ws.mSession.mPid
9765                                    + " uid=" + ws.mSession.mUid);
9766                            if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9767                            wsa.mSurfaceControl.destroy();
9768                            wsa.mSurfaceShown = false;
9769                            wsa.mSurfaceControl = null;
9770                            ws.mHasSurface = false;
9771                            mForceRemoves.add(ws);
9772                            leakedSurface = true;
9773                        } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
9774                            Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
9775                                    + ws + " surface=" + wsa.mSurfaceControl
9776                                    + " token=" + ws.mAppToken);
9777                            if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9778                            wsa.mSurfaceControl.destroy();
9779                            wsa.mSurfaceShown = false;
9780                            wsa.mSurfaceControl = null;
9781                            ws.mHasSurface = false;
9782                            leakedSurface = true;
9783                        }
9784                    }
9785                }
9786            }
9787
9788            if (!leakedSurface) {
9789                Slog.w(TAG, "No leaked surfaces; killing applicatons!");
9790                SparseIntArray pidCandidates = new SparseIntArray();
9791                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9792                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9793                    final int numWindows = windows.size();
9794                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9795                        final WindowState ws = windows.get(winNdx);
9796                        if (mForceRemoves.contains(ws)) {
9797                            continue;
9798                        }
9799                        WindowStateAnimator wsa = ws.mWinAnimator;
9800                        if (wsa.mSurfaceControl != null) {
9801                            pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
9802                        }
9803                    }
9804                    if (pidCandidates.size() > 0) {
9805                        int[] pids = new int[pidCandidates.size()];
9806                        for (int i=0; i<pids.length; i++) {
9807                            pids[i] = pidCandidates.keyAt(i);
9808                        }
9809                        try {
9810                            if (mActivityManager.killPids(pids, "Free memory", secure)) {
9811                                killedApps = true;
9812                            }
9813                        } catch (RemoteException e) {
9814                        }
9815                    }
9816                }
9817            }
9818
9819            if (leakedSurface || killedApps) {
9820                // We managed to reclaim some memory, so get rid of the trouble
9821                // surface and ask the app to request another one.
9822                Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
9823                if (surface != null) {
9824                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
9825                            "RECOVER DESTROY", null);
9826                    surface.destroy();
9827                    winAnimator.mSurfaceShown = false;
9828                    winAnimator.mSurfaceControl = null;
9829                    winAnimator.mWin.mHasSurface = false;
9830                    scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken);
9831                }
9832
9833                try {
9834                    winAnimator.mWin.mClient.dispatchGetNewSurface();
9835                } catch (RemoteException e) {
9836                }
9837            }
9838        } finally {
9839            Binder.restoreCallingIdentity(callingIdentity);
9840        }
9841
9842        return leakedSurface || killedApps;
9843    }
9844
9845    private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
9846        WindowState newFocus = computeFocusedWindowLocked();
9847        if (mCurrentFocus != newFocus) {
9848            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
9849            // This check makes sure that we don't already have the focus
9850            // change message pending.
9851            mH.removeMessages(H.REPORT_FOCUS_CHANGE);
9852            mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
9853            // TODO(multidisplay): Focused windows on default display only.
9854            final DisplayContent displayContent = getDefaultDisplayContentLocked();
9855            final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked(
9856                    mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
9857                            && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
9858            if (imWindowChanged) {
9859                displayContent.layoutNeeded = true;
9860                newFocus = computeFocusedWindowLocked();
9861            }
9862
9863            if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " +
9864                    mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
9865            final WindowState oldFocus = mCurrentFocus;
9866            mCurrentFocus = newFocus;
9867            mLosingFocus.remove(newFocus);
9868            int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
9869
9870            if (imWindowChanged && oldFocus != mInputMethodWindow) {
9871                // Focus of the input method window changed. Perform layout if needed.
9872                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9873                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9874                    focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9875                } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
9876                    // Client will do the layout, but we need to assign layers
9877                    // for handleNewWindowLocked() below.
9878                    assignLayersLocked(displayContent.getWindowList());
9879                }
9880            }
9881
9882            if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9883                // The change in focus caused us to need to do a layout.  Okay.
9884                displayContent.layoutNeeded = true;
9885                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9886                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9887                }
9888            }
9889
9890            if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
9891                // If we defer assigning layers, then the caller is responsible for
9892                // doing this part.
9893                finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows);
9894            }
9895
9896            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
9897            return true;
9898        }
9899        return false;
9900    }
9901
9902    private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) {
9903        mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
9904    }
9905
9906    private WindowState computeFocusedWindowLocked() {
9907        if (mAnimator.mUniverseBackground != null
9908                && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
9909            return mAnimator.mUniverseBackground.mWin;
9910        }
9911
9912        final int displayCount = mDisplayContents.size();
9913        for (int i = 0; i < displayCount; i++) {
9914            final DisplayContent displayContent = mDisplayContents.valueAt(i);
9915            WindowState win = findFocusedWindowLocked(displayContent);
9916            if (win != null) {
9917                return win;
9918            }
9919        }
9920        return null;
9921    }
9922
9923    private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
9924        final WindowList windows = displayContent.getWindowList();
9925        for (int i = windows.size() - 1; i >= 0; i--) {
9926            final WindowState win = windows.get(i);
9927
9928            if (localLOGV || DEBUG_FOCUS) Slog.v(
9929                TAG, "Looking for focus: " + i
9930                + " = " + win
9931                + ", flags=" + win.mAttrs.flags
9932                + ", canReceive=" + win.canReceiveKeys());
9933
9934            AppWindowToken wtoken = win.mAppToken;
9935
9936            // If this window's application has been removed, just skip it.
9937            if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
9938                if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because "
9939                        + (wtoken.removed ? "removed" : "sendingToBottom"));
9940                continue;
9941            }
9942
9943            if (!win.canReceiveKeys()) {
9944                continue;
9945            }
9946
9947            // Descend through all of the app tokens and find the first that either matches
9948            // win.mAppToken (return win) or mFocusedApp (return null).
9949            if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
9950                    mFocusedApp != null) {
9951                ArrayList<Task> tasks = displayContent.getTasks();
9952                for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9953                    AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9954                    int tokenNdx = tokens.size() - 1;
9955                    for ( ; tokenNdx >= 0; --tokenNdx) {
9956                        final AppWindowToken token = tokens.get(tokenNdx);
9957                        if (wtoken == token) {
9958                            break;
9959                        }
9960                        if (mFocusedApp == token) {
9961                            // Whoops, we are below the focused app...  no focus for you!
9962                            if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG,
9963                                    "findFocusedWindow: Reached focused app=" + mFocusedApp);
9964                            return null;
9965                        }
9966                    }
9967                    if (tokenNdx >= 0) {
9968                        // Early exit from loop, must have found the matching token.
9969                        break;
9970                    }
9971                }
9972            }
9973
9974            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i +
9975                        " = " + win);
9976            return win;
9977        }
9978
9979        if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows.");
9980        return null;
9981    }
9982
9983    private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
9984        if (mDisplayFrozen) {
9985            return;
9986        }
9987
9988        if (!mDisplayReady || !mPolicy.isScreenOnFully()) {
9989            // No need to freeze the screen before the system is ready or if
9990            // the screen is off.
9991            return;
9992        }
9993
9994        mScreenFrozenLock.acquire();
9995
9996        mDisplayFrozen = true;
9997        mDisplayFreezeTime = SystemClock.elapsedRealtime();
9998        mLastFinishedFreezeSource = null;
9999
10000        mInputMonitor.freezeInputDispatchingLw();
10001
10002        // Clear the last input window -- that is just used for
10003        // clean transitions between IMEs, and if we are freezing
10004        // the screen then the whole world is changing behind the scenes.
10005        mPolicy.setLastInputMethodWindowLw(null, null);
10006
10007        if (mAppTransition.isTransitionSet()) {
10008            mAppTransition.freeze();
10009        }
10010
10011        if (PROFILE_ORIENTATION) {
10012            File file = new File("/data/system/frozen");
10013            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
10014        }
10015
10016        if (CUSTOM_SCREEN_ROTATION) {
10017            mExitAnimId = exitAnim;
10018            mEnterAnimId = enterAnim;
10019            final DisplayContent displayContent = getDefaultDisplayContentLocked();
10020            final int displayId = displayContent.getDisplayId();
10021            ScreenRotationAnimation screenRotationAnimation =
10022                    mAnimator.getScreenRotationAnimationLocked(displayId);
10023            if (screenRotationAnimation != null) {
10024                screenRotationAnimation.kill();
10025            }
10026
10027            // Check whether the current screen contains any secure content.
10028            boolean isSecure = false;
10029            final WindowList windows = getDefaultWindowListLocked();
10030            final int N = windows.size();
10031            for (int i = 0; i < N; i++) {
10032                WindowState ws = windows.get(i);
10033                if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) {
10034                    isSecure = true;
10035                    break;
10036                }
10037            }
10038
10039            // TODO(multidisplay): rotation on main screen only.
10040            displayContent.updateDisplayInfo();
10041            screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
10042                    mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure);
10043            mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10044        }
10045    }
10046
10047    private void stopFreezingDisplayLocked() {
10048        if (!mDisplayFrozen) {
10049            return;
10050        }
10051
10052        if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen
10053                || mClientFreezingScreen) {
10054            if (DEBUG_ORIENTATION) Slog.d(TAG,
10055                "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
10056                + ", mAppsFreezingScreen=" + mAppsFreezingScreen
10057                + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
10058                + ", mClientFreezingScreen=" + mClientFreezingScreen);
10059            return;
10060        }
10061
10062        mDisplayFrozen = false;
10063        mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
10064        StringBuilder sb = new StringBuilder(128);
10065        sb.append("Screen frozen for ");
10066        TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
10067        if (mLastFinishedFreezeSource != null) {
10068            sb.append(" due to ");
10069            sb.append(mLastFinishedFreezeSource);
10070        }
10071        Slog.i(TAG, sb.toString());
10072        mH.removeMessages(H.APP_FREEZE_TIMEOUT);
10073        mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
10074        if (PROFILE_ORIENTATION) {
10075            Debug.stopMethodTracing();
10076        }
10077
10078        boolean updateRotation = false;
10079
10080        final DisplayContent displayContent = getDefaultDisplayContentLocked();
10081        final int displayId = displayContent.getDisplayId();
10082        ScreenRotationAnimation screenRotationAnimation =
10083                mAnimator.getScreenRotationAnimationLocked(displayId);
10084        if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
10085                && screenRotationAnimation.hasScreenshot()) {
10086            if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
10087            // TODO(multidisplay): rotation on main screen only.
10088            DisplayInfo displayInfo = displayContent.getDisplayInfo();
10089            // Get rotation animation again, with new top window
10090            boolean isDimming = displayContent.isDimming();
10091            if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
10092                mExitAnimId = mEnterAnimId = 0;
10093            }
10094            if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
10095                    mTransitionAnimationScale, displayInfo.logicalWidth,
10096                        displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
10097                scheduleAnimationLocked();
10098            } else {
10099                screenRotationAnimation.kill();
10100                screenRotationAnimation = null;
10101                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10102                updateRotation = true;
10103            }
10104        } else {
10105            if (screenRotationAnimation != null) {
10106                screenRotationAnimation.kill();
10107                screenRotationAnimation = null;
10108                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10109            }
10110            updateRotation = true;
10111        }
10112
10113        mInputMonitor.thawInputDispatchingLw();
10114
10115        boolean configChanged;
10116
10117        // While the display is frozen we don't re-compute the orientation
10118        // to avoid inconsistent states.  However, something interesting
10119        // could have actually changed during that time so re-evaluate it
10120        // now to catch that.
10121        configChanged = updateOrientationFromAppTokensLocked(false);
10122
10123        // A little kludge: a lot could have happened while the
10124        // display was frozen, so now that we are coming back we
10125        // do a gc so that any remote references the system
10126        // processes holds on others can be released if they are
10127        // no longer needed.
10128        mH.removeMessages(H.FORCE_GC);
10129        mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
10130
10131        mScreenFrozenLock.release();
10132
10133        if (updateRotation) {
10134            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
10135            configChanged |= updateRotationUncheckedLocked(false);
10136        }
10137
10138        if (configChanged) {
10139            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
10140        }
10141    }
10142
10143    static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
10144            DisplayMetrics dm) {
10145        if (index < tokens.length) {
10146            String str = tokens[index];
10147            if (str != null && str.length() > 0) {
10148                try {
10149                    int val = Integer.parseInt(str);
10150                    return val;
10151                } catch (Exception e) {
10152                }
10153            }
10154        }
10155        if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
10156            return defDps;
10157        }
10158        int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
10159        return val;
10160    }
10161
10162    void createWatermarkInTransaction() {
10163        if (mWatermark != null) {
10164            return;
10165        }
10166
10167        File file = new File("/system/etc/setup.conf");
10168        FileInputStream in = null;
10169        DataInputStream ind = null;
10170        try {
10171            in = new FileInputStream(file);
10172            ind = new DataInputStream(in);
10173            String line = ind.readLine();
10174            if (line != null) {
10175                String[] toks = line.split("%");
10176                if (toks != null && toks.length > 0) {
10177                    mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
10178                            mRealDisplayMetrics, mFxSession, toks);
10179                }
10180            }
10181        } catch (FileNotFoundException e) {
10182        } catch (IOException e) {
10183        } finally {
10184            if (ind != null) {
10185                try {
10186                    ind.close();
10187                } catch (IOException e) {
10188                }
10189            } else if (in != null) {
10190                try {
10191                    in.close();
10192                } catch (IOException e) {
10193                }
10194            }
10195        }
10196    }
10197
10198    @Override
10199    public void statusBarVisibilityChanged(int visibility) {
10200        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
10201                != PackageManager.PERMISSION_GRANTED) {
10202            throw new SecurityException("Caller does not hold permission "
10203                    + android.Manifest.permission.STATUS_BAR);
10204        }
10205
10206        synchronized (mWindowMap) {
10207            mLastStatusBarVisibility = visibility;
10208            visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
10209            updateStatusBarVisibilityLocked(visibility);
10210        }
10211    }
10212
10213    // TOOD(multidisplay): StatusBar on multiple screens?
10214    void updateStatusBarVisibilityLocked(int visibility) {
10215        mInputManager.setSystemUiVisibility(visibility);
10216        final WindowList windows = getDefaultWindowListLocked();
10217        final int N = windows.size();
10218        for (int i = 0; i < N; i++) {
10219            WindowState ws = windows.get(i);
10220            try {
10221                int curValue = ws.mSystemUiVisibility;
10222                int diff = curValue ^ visibility;
10223                // We are only interested in differences of one of the
10224                // clearable flags...
10225                diff &= View.SYSTEM_UI_CLEARABLE_FLAGS;
10226                // ...if it has actually been cleared.
10227                diff &= ~visibility;
10228                int newValue = (curValue&~diff) | (visibility&diff);
10229                if (newValue != curValue) {
10230                    ws.mSeq++;
10231                    ws.mSystemUiVisibility = newValue;
10232                }
10233                if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
10234                    ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
10235                            visibility, newValue, diff);
10236                }
10237            } catch (RemoteException e) {
10238                // so sorry
10239            }
10240        }
10241    }
10242
10243    @Override
10244    public void reevaluateStatusBarVisibility() {
10245        synchronized (mWindowMap) {
10246            int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
10247            updateStatusBarVisibilityLocked(visibility);
10248            performLayoutAndPlaceSurfacesLocked();
10249        }
10250    }
10251
10252    @Override
10253    public FakeWindow addFakeWindow(Looper looper,
10254            InputEventReceiver.Factory inputEventReceiverFactory,
10255            String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags,
10256            boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) {
10257        synchronized (mWindowMap) {
10258            FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory,
10259                    name, windowType,
10260                    layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys,
10261                    hasFocus, touchFullscreen);
10262            int i=0;
10263            while (i<mFakeWindows.size()) {
10264                if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) {
10265                    break;
10266                }
10267            }
10268            mFakeWindows.add(i, fw);
10269            mInputMonitor.updateInputWindowsLw(true);
10270            return fw;
10271        }
10272    }
10273
10274    boolean removeFakeWindowLocked(FakeWindow window) {
10275        synchronized (mWindowMap) {
10276            if (mFakeWindows.remove(window)) {
10277                mInputMonitor.updateInputWindowsLw(true);
10278                return true;
10279            }
10280            return false;
10281        }
10282    }
10283
10284    // It is assumed that this method is called only by InputMethodManagerService.
10285    public void saveLastInputMethodWindowForTransition() {
10286        synchronized (mWindowMap) {
10287            // TODO(multidisplay): Pass in the displayID.
10288            DisplayContent displayContent = getDefaultDisplayContentLocked();
10289            if (mInputMethodWindow != null) {
10290                mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
10291            }
10292        }
10293    }
10294
10295    @Override
10296    public boolean hasNavigationBar() {
10297        return mPolicy.hasNavigationBar();
10298    }
10299
10300    @Override
10301    public void lockNow(Bundle options) {
10302        mPolicy.lockNow(options);
10303    }
10304
10305    @Override
10306    public boolean isSafeModeEnabled() {
10307        return mSafeMode;
10308    }
10309
10310    void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10311        pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
10312        mPolicy.dump("    ", pw, args);
10313    }
10314
10315    void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10316        pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
10317        mAnimator.dumpLocked(pw, "    ", dumpAll);
10318    }
10319
10320    void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
10321        pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
10322        if (mTokenMap.size() > 0) {
10323            pw.println("  All tokens:");
10324            Iterator<WindowToken> it = mTokenMap.values().iterator();
10325            while (it.hasNext()) {
10326                WindowToken token = it.next();
10327                pw.print("  "); pw.print(token);
10328                if (dumpAll) {
10329                    pw.println(':');
10330                    token.dump(pw, "    ");
10331                } else {
10332                    pw.println();
10333                }
10334            }
10335        }
10336        if (mWallpaperTokens.size() > 0) {
10337            pw.println();
10338            pw.println("  Wallpaper tokens:");
10339            for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
10340                WindowToken token = mWallpaperTokens.get(i);
10341                pw.print("  Wallpaper #"); pw.print(i);
10342                        pw.print(' '); pw.print(token);
10343                if (dumpAll) {
10344                    pw.println(':');
10345                    token.dump(pw, "    ");
10346                } else {
10347                    pw.println();
10348                }
10349            }
10350        }
10351        if (mFinishedStarting.size() > 0) {
10352            pw.println();
10353            pw.println("  Finishing start of application tokens:");
10354            for (int i=mFinishedStarting.size()-1; i>=0; i--) {
10355                WindowToken token = mFinishedStarting.get(i);
10356                pw.print("  Finished Starting #"); pw.print(i);
10357                        pw.print(' '); pw.print(token);
10358                if (dumpAll) {
10359                    pw.println(':');
10360                    token.dump(pw, "    ");
10361                } else {
10362                    pw.println();
10363                }
10364            }
10365        }
10366        if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
10367            pw.println();
10368            if (mOpeningApps.size() > 0) {
10369                pw.print("  mOpeningApps="); pw.println(mOpeningApps);
10370            }
10371            if (mClosingApps.size() > 0) {
10372                pw.print("  mClosingApps="); pw.println(mClosingApps);
10373            }
10374        }
10375    }
10376
10377    void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
10378        pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
10379        if (mSessions.size() > 0) {
10380            Iterator<Session> it = mSessions.iterator();
10381            while (it.hasNext()) {
10382                Session s = it.next();
10383                pw.print("  Session "); pw.print(s); pw.println(':');
10384                s.dump(pw, "    ");
10385            }
10386        }
10387    }
10388
10389    void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
10390        pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
10391        if (mDisplayReady) {
10392            final int numDisplays = mDisplayContents.size();
10393            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10394                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10395                displayContent.dump("  ", pw);
10396            }
10397        } else {
10398            pw.println("  NO DISPLAY");
10399        }
10400    }
10401
10402    void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
10403            ArrayList<WindowState> windows) {
10404        pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
10405        dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
10406    }
10407
10408    void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
10409            ArrayList<WindowState> windows) {
10410        final int numDisplays = mDisplayContents.size();
10411        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10412            final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
10413            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10414                final WindowState w = windowList.get(winNdx);
10415                if (windows == null || windows.contains(w)) {
10416                    pw.print("  Window #"); pw.print(winNdx); pw.print(' ');
10417                            pw.print(w); pw.println(":");
10418                    w.dump(pw, "    ", dumpAll || windows != null);
10419                }
10420            }
10421        }
10422        if (mInputMethodDialogs.size() > 0) {
10423            pw.println();
10424            pw.println("  Input method dialogs:");
10425            for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
10426                WindowState w = mInputMethodDialogs.get(i);
10427                if (windows == null || windows.contains(w)) {
10428                    pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
10429                }
10430            }
10431        }
10432        if (mPendingRemove.size() > 0) {
10433            pw.println();
10434            pw.println("  Remove pending for:");
10435            for (int i=mPendingRemove.size()-1; i>=0; i--) {
10436                WindowState w = mPendingRemove.get(i);
10437                if (windows == null || windows.contains(w)) {
10438                    pw.print("  Remove #"); pw.print(i); pw.print(' ');
10439                            pw.print(w);
10440                    if (dumpAll) {
10441                        pw.println(":");
10442                        w.dump(pw, "    ", true);
10443                    } else {
10444                        pw.println();
10445                    }
10446                }
10447            }
10448        }
10449        if (mForceRemoves != null && mForceRemoves.size() > 0) {
10450            pw.println();
10451            pw.println("  Windows force removing:");
10452            for (int i=mForceRemoves.size()-1; i>=0; i--) {
10453                WindowState w = mForceRemoves.get(i);
10454                pw.print("  Removing #"); pw.print(i); pw.print(' ');
10455                        pw.print(w);
10456                if (dumpAll) {
10457                    pw.println(":");
10458                    w.dump(pw, "    ", true);
10459                } else {
10460                    pw.println();
10461                }
10462            }
10463        }
10464        if (mDestroySurface.size() > 0) {
10465            pw.println();
10466            pw.println("  Windows waiting to destroy their surface:");
10467            for (int i=mDestroySurface.size()-1; i>=0; i--) {
10468                WindowState w = mDestroySurface.get(i);
10469                if (windows == null || windows.contains(w)) {
10470                    pw.print("  Destroy #"); pw.print(i); pw.print(' ');
10471                            pw.print(w);
10472                    if (dumpAll) {
10473                        pw.println(":");
10474                        w.dump(pw, "    ", true);
10475                    } else {
10476                        pw.println();
10477                    }
10478                }
10479            }
10480        }
10481        if (mLosingFocus.size() > 0) {
10482            pw.println();
10483            pw.println("  Windows losing focus:");
10484            for (int i=mLosingFocus.size()-1; i>=0; i--) {
10485                WindowState w = mLosingFocus.get(i);
10486                if (windows == null || windows.contains(w)) {
10487                    pw.print("  Losing #"); pw.print(i); pw.print(' ');
10488                            pw.print(w);
10489                    if (dumpAll) {
10490                        pw.println(":");
10491                        w.dump(pw, "    ", true);
10492                    } else {
10493                        pw.println();
10494                    }
10495                }
10496            }
10497        }
10498        if (mResizingWindows.size() > 0) {
10499            pw.println();
10500            pw.println("  Windows waiting to resize:");
10501            for (int i=mResizingWindows.size()-1; i>=0; i--) {
10502                WindowState w = mResizingWindows.get(i);
10503                if (windows == null || windows.contains(w)) {
10504                    pw.print("  Resizing #"); pw.print(i); pw.print(' ');
10505                            pw.print(w);
10506                    if (dumpAll) {
10507                        pw.println(":");
10508                        w.dump(pw, "    ", true);
10509                    } else {
10510                        pw.println();
10511                    }
10512                }
10513            }
10514        }
10515        if (mWaitingForDrawn.size() > 0) {
10516            pw.println();
10517            pw.println("  Clients waiting for these windows to be drawn:");
10518            for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
10519                WindowState win = mWaitingForDrawn.get(i);
10520                pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
10521            }
10522        }
10523        pw.println();
10524        pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
10525        pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
10526        if (mLastFocus != mCurrentFocus) {
10527            pw.print("  mLastFocus="); pw.println(mLastFocus);
10528        }
10529        pw.print("  mFocusedApp="); pw.println(mFocusedApp);
10530        if (mInputMethodTarget != null) {
10531            pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
10532        }
10533        pw.print("  mInTouchMode="); pw.print(mInTouchMode);
10534                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
10535        pw.print("  mLastDisplayFreezeDuration=");
10536                TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
10537                if ( mLastFinishedFreezeSource != null) {
10538                    pw.print(" due to ");
10539                    pw.print(mLastFinishedFreezeSource);
10540                }
10541                pw.println();
10542        if (dumpAll) {
10543            pw.print("  mSystemDecorLayer="); pw.print(mSystemDecorLayer);
10544                    pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
10545            if (mLastStatusBarVisibility != 0) {
10546                pw.print("  mLastStatusBarVisibility=0x");
10547                        pw.println(Integer.toHexString(mLastStatusBarVisibility));
10548            }
10549            if (mInputMethodWindow != null) {
10550                pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
10551            }
10552            pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
10553            if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
10554                pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
10555                pw.print("  mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
10556            }
10557            pw.print("  mLastWallpaperX="); pw.print(mLastWallpaperX);
10558                    pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
10559            if (mInputMethodAnimLayerAdjustment != 0 ||
10560                    mWallpaperAnimLayerAdjustment != 0) {
10561                pw.print("  mInputMethodAnimLayerAdjustment=");
10562                        pw.print(mInputMethodAnimLayerAdjustment);
10563                        pw.print("  mWallpaperAnimLayerAdjustment=");
10564                        pw.println(mWallpaperAnimLayerAdjustment);
10565            }
10566            pw.print("  mSystemBooted="); pw.print(mSystemBooted);
10567                    pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
10568            if (needsLayout()) {
10569                pw.print("  layoutNeeded on displays=");
10570                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10571                    final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10572                    if (displayContent.layoutNeeded) {
10573                        pw.print(displayContent.getDisplayId());
10574                    }
10575                }
10576                pw.println();
10577            }
10578            pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
10579            pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
10580                    pw.print(" windows="); pw.print(mWindowsFreezingScreen);
10581                    pw.print(" client="); pw.print(mClientFreezingScreen);
10582                    pw.print(" apps="); pw.print(mAppsFreezingScreen);
10583                    pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
10584            pw.print("  mRotation="); pw.print(mRotation);
10585                    pw.print(" mAltOrientation="); pw.println(mAltOrientation);
10586            pw.print("  mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
10587                    pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
10588            pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
10589            pw.print("  mWindowAnimationScale="); pw.print(mWindowAnimationScale);
10590                    pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale);
10591                    pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale);
10592            pw.print("  mTraversalScheduled="); pw.println(mTraversalScheduled);
10593            pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
10594                    pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
10595            pw.println("  mLayoutToAnim:");
10596            mAppTransition.dump(pw);
10597        }
10598    }
10599
10600    boolean dumpWindows(PrintWriter pw, String name, String[] args,
10601            int opti, boolean dumpAll) {
10602        WindowList windows = new WindowList();
10603        if ("visible".equals(name)) {
10604            synchronized(mWindowMap) {
10605                final int numDisplays = mDisplayContents.size();
10606                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10607                    final WindowList windowList =
10608                            mDisplayContents.valueAt(displayNdx).getWindowList();
10609                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10610                        final WindowState w = windowList.get(winNdx);
10611                        if (w.mWinAnimator.mSurfaceShown) {
10612                            windows.add(w);
10613                        }
10614                    }
10615                }
10616            }
10617        } else {
10618            int objectId = 0;
10619            // See if this is an object ID.
10620            try {
10621                objectId = Integer.parseInt(name, 16);
10622                name = null;
10623            } catch (RuntimeException e) {
10624            }
10625            synchronized(mWindowMap) {
10626                final int numDisplays = mDisplayContents.size();
10627                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10628                    final WindowList windowList =
10629                            mDisplayContents.valueAt(displayNdx).getWindowList();
10630                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10631                        final WindowState w = windowList.get(winNdx);
10632                        if (name != null) {
10633                            if (w.mAttrs.getTitle().toString().contains(name)) {
10634                                windows.add(w);
10635                            }
10636                        } else if (System.identityHashCode(w) == objectId) {
10637                            windows.add(w);
10638                        }
10639                    }
10640                }
10641            }
10642        }
10643
10644        if (windows.size() <= 0) {
10645            return false;
10646        }
10647
10648        synchronized(mWindowMap) {
10649            dumpWindowsLocked(pw, dumpAll, windows);
10650        }
10651        return true;
10652    }
10653
10654    void dumpLastANRLocked(PrintWriter pw) {
10655        pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
10656        if (mLastANRState == null) {
10657            pw.println("  <no ANR has occurred since boot>");
10658        } else {
10659            pw.println(mLastANRState);
10660        }
10661    }
10662
10663    /**
10664     * Saves information about the state of the window manager at
10665     * the time an ANR occurred before anything else in the system changes
10666     * in response.
10667     *
10668     * @param appWindowToken The application that ANR'd, may be null.
10669     * @param windowState The window that ANR'd, may be null.
10670     * @param reason The reason for the ANR, may be null.
10671     */
10672    public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState,
10673            String reason) {
10674        StringWriter sw = new StringWriter();
10675        PrintWriter pw = new FastPrintWriter(sw, false, 1024);
10676        pw.println("  ANR time: " + DateFormat.getInstance().format(new Date()));
10677        if (appWindowToken != null) {
10678            pw.println("  Application at fault: " + appWindowToken.stringName);
10679        }
10680        if (windowState != null) {
10681            pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
10682        }
10683        if (reason != null) {
10684            pw.println("  Reason: " + reason);
10685        }
10686        pw.println();
10687        dumpWindowsNoHeaderLocked(pw, true, null);
10688        pw.close();
10689        mLastANRState = sw.toString();
10690    }
10691
10692    @Override
10693    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10694        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
10695                != PackageManager.PERMISSION_GRANTED) {
10696            pw.println("Permission Denial: can't dump WindowManager from from pid="
10697                    + Binder.getCallingPid()
10698                    + ", uid=" + Binder.getCallingUid());
10699            return;
10700        }
10701
10702        boolean dumpAll = false;
10703
10704        int opti = 0;
10705        while (opti < args.length) {
10706            String opt = args[opti];
10707            if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10708                break;
10709            }
10710            opti++;
10711            if ("-a".equals(opt)) {
10712                dumpAll = true;
10713            } else if ("-h".equals(opt)) {
10714                pw.println("Window manager dump options:");
10715                pw.println("  [-a] [-h] [cmd] ...");
10716                pw.println("  cmd may be one of:");
10717                pw.println("    l[astanr]: last ANR information");
10718                pw.println("    p[policy]: policy state");
10719                pw.println("    a[animator]: animator state");
10720                pw.println("    s[essions]: active sessions");
10721                pw.println("    d[isplays]: active display contents");
10722                pw.println("    t[okens]: token list");
10723                pw.println("    w[indows]: window list");
10724                pw.println("  cmd may also be a NAME to dump windows.  NAME may");
10725                pw.println("    be a partial substring in a window name, a");
10726                pw.println("    Window hex object identifier, or");
10727                pw.println("    \"all\" for all windows, or");
10728                pw.println("    \"visible\" for the visible windows.");
10729                pw.println("  -a: include all available server state.");
10730                return;
10731            } else {
10732                pw.println("Unknown argument: " + opt + "; use -h for help");
10733            }
10734        }
10735
10736        // Is the caller requesting to dump a particular piece of data?
10737        if (opti < args.length) {
10738            String cmd = args[opti];
10739            opti++;
10740            if ("lastanr".equals(cmd) || "l".equals(cmd)) {
10741                synchronized(mWindowMap) {
10742                    dumpLastANRLocked(pw);
10743                }
10744                return;
10745            } else if ("policy".equals(cmd) || "p".equals(cmd)) {
10746                synchronized(mWindowMap) {
10747                    dumpPolicyLocked(pw, args, true);
10748                }
10749                return;
10750            } else if ("animator".equals(cmd) || "a".equals(cmd)) {
10751                synchronized(mWindowMap) {
10752                    dumpAnimatorLocked(pw, args, true);
10753                }
10754                return;
10755            } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
10756                synchronized(mWindowMap) {
10757                    dumpSessionsLocked(pw, true);
10758                }
10759                return;
10760            } else if ("displays".equals(cmd) || "d".equals(cmd)) {
10761                synchronized(mWindowMap) {
10762                    dumpDisplayContentsLocked(pw, true);
10763                }
10764                return;
10765            } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
10766                synchronized(mWindowMap) {
10767                    dumpTokensLocked(pw, true);
10768                }
10769                return;
10770            } else if ("windows".equals(cmd) || "w".equals(cmd)) {
10771                synchronized(mWindowMap) {
10772                    dumpWindowsLocked(pw, true, null);
10773                }
10774                return;
10775            } else if ("all".equals(cmd) || "a".equals(cmd)) {
10776                synchronized(mWindowMap) {
10777                    dumpWindowsLocked(pw, true, null);
10778                }
10779                return;
10780            } else {
10781                // Dumping a single name?
10782                if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
10783                    pw.println("Bad window command, or no windows match: " + cmd);
10784                    pw.println("Use -h for help.");
10785                }
10786                return;
10787            }
10788        }
10789
10790        synchronized(mWindowMap) {
10791            pw.println();
10792            if (dumpAll) {
10793                pw.println("-------------------------------------------------------------------------------");
10794            }
10795            dumpLastANRLocked(pw);
10796            pw.println();
10797            if (dumpAll) {
10798                pw.println("-------------------------------------------------------------------------------");
10799            }
10800            dumpPolicyLocked(pw, args, dumpAll);
10801            pw.println();
10802            if (dumpAll) {
10803                pw.println("-------------------------------------------------------------------------------");
10804            }
10805            dumpAnimatorLocked(pw, args, dumpAll);
10806            pw.println();
10807            if (dumpAll) {
10808                pw.println("-------------------------------------------------------------------------------");
10809            }
10810            dumpSessionsLocked(pw, dumpAll);
10811            pw.println();
10812            if (dumpAll) {
10813                pw.println("-------------------------------------------------------------------------------");
10814            }
10815            dumpDisplayContentsLocked(pw, dumpAll);
10816            pw.println();
10817            if (dumpAll) {
10818                pw.println("-------------------------------------------------------------------------------");
10819            }
10820            dumpTokensLocked(pw, dumpAll);
10821            pw.println();
10822            if (dumpAll) {
10823                pw.println("-------------------------------------------------------------------------------");
10824            }
10825            dumpWindowsLocked(pw, dumpAll, null);
10826        }
10827    }
10828
10829    // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
10830    @Override
10831    public void monitor() {
10832        synchronized (mWindowMap) { }
10833    }
10834
10835    public interface OnHardKeyboardStatusChangeListener {
10836        public void onHardKeyboardStatusChange(boolean available, boolean enabled);
10837    }
10838
10839    void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
10840        if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
10841            Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
10842                    Integer.toHexString(pendingLayoutChanges));
10843        }
10844    }
10845
10846    private DisplayContent newDisplayContentLocked(final Display display) {
10847        DisplayContent displayContent = new DisplayContent(display, this);
10848        final int displayId = display.getDisplayId();
10849        if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display);
10850        mDisplayContents.put(displayId, displayContent);
10851
10852        DisplayInfo displayInfo = displayContent.getDisplayInfo();
10853        final Rect rect = new Rect();
10854        mDisplaySettings.getOverscanLocked(displayInfo.name, rect);
10855        synchronized (displayContent.mDisplaySizeLock) {
10856            displayInfo.overscanLeft = rect.left;
10857            displayInfo.overscanTop = rect.top;
10858            displayInfo.overscanRight = rect.right;
10859            displayInfo.overscanBottom = rect.bottom;
10860            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
10861                    displayId, displayInfo);
10862        }
10863        configureDisplayPolicyLocked(displayContent);
10864
10865        // TODO: Create an input channel for each display with touch capability.
10866        if (displayId == Display.DEFAULT_DISPLAY) {
10867            displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent);
10868            registerPointerEventListener(displayContent.mTapDetector);
10869        }
10870
10871        return displayContent;
10872    }
10873
10874    public void createDisplayContentLocked(final Display display) {
10875        if (display == null) {
10876            throw new IllegalArgumentException("getDisplayContent: display must not be null");
10877        }
10878        getDisplayContentLocked(display.getDisplayId());
10879    }
10880
10881    /**
10882     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
10883     * there is a Display for the displayId.
10884     * @param displayId The display the caller is interested in.
10885     * @return The DisplayContent associated with displayId or null if there is no Display for it.
10886     */
10887    public DisplayContent getDisplayContentLocked(final int displayId) {
10888        DisplayContent displayContent = mDisplayContents.get(displayId);
10889        if (displayContent == null) {
10890            final Display display = mDisplayManager.getDisplay(displayId);
10891            if (display != null) {
10892                displayContent = newDisplayContentLocked(display);
10893            }
10894        }
10895        return displayContent;
10896    }
10897
10898    // There is an inherent assumption that this will never return null.
10899    public DisplayContent getDefaultDisplayContentLocked() {
10900        return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
10901    }
10902
10903    public WindowList getDefaultWindowListLocked() {
10904        return getDefaultDisplayContentLocked().getWindowList();
10905    }
10906
10907    public DisplayInfo getDefaultDisplayInfoLocked() {
10908        return getDefaultDisplayContentLocked().getDisplayInfo();
10909    }
10910
10911    /**
10912     * Return the list of WindowStates associated on the passed display.
10913     * @param display The screen to return windows from.
10914     * @return The list of WindowStates on the screen, or null if the there is no screen.
10915     */
10916    public WindowList getWindowListLocked(final Display display) {
10917        return getWindowListLocked(display.getDisplayId());
10918    }
10919
10920    /**
10921     * Return the list of WindowStates associated on the passed display.
10922     * @param displayId The screen to return windows from.
10923     * @return The list of WindowStates on the screen, or null if the there is no screen.
10924     */
10925    public WindowList getWindowListLocked(final int displayId) {
10926        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10927        return displayContent != null ? displayContent.getWindowList() : null;
10928    }
10929
10930    public void onDisplayAdded(int displayId) {
10931        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
10932    }
10933
10934    public void handleDisplayAdded(int displayId) {
10935        synchronized (mWindowMap) {
10936            final Display display = mDisplayManager.getDisplay(displayId);
10937            if (display != null) {
10938                createDisplayContentLocked(display);
10939                displayReady(displayId);
10940            }
10941        }
10942    }
10943
10944    public void onDisplayRemoved(int displayId) {
10945        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
10946    }
10947
10948    private void handleDisplayRemovedLocked(int displayId) {
10949        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10950        if (displayContent != null) {
10951            if (displayContent.isAnimating()) {
10952                displayContent.mDeferredRemoval = true;
10953                return;
10954            }
10955            if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent);
10956            mDisplayContents.delete(displayId);
10957            displayContent.close();
10958            if (displayId == Display.DEFAULT_DISPLAY) {
10959                unregisterPointerEventListener(displayContent.mTapDetector);
10960            }
10961        }
10962        mAnimator.removeDisplayLocked(displayId);
10963    }
10964
10965    public void onDisplayChanged(int displayId) {
10966        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
10967    }
10968
10969    private void handleDisplayChangedLocked(int displayId) {
10970        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10971        if (displayContent != null) {
10972            displayContent.updateDisplayInfo();
10973        }
10974    }
10975
10976    @Override
10977    public Object getWindowManagerLock() {
10978        return mWindowMap;
10979    }
10980
10981    private final class LocalService extends WindowManagerInternal {
10982        @Override
10983        public void requestTraversalFromDisplayManager() {
10984            requestTraversal();
10985        }
10986
10987        @Override
10988        public void waitForAllWindowsDrawn(IRemoteCallback callback, long timeout) {
10989            synchronized (mWindowMap) {
10990                mWaitingForDrawnCallback = callback;
10991                final WindowList windows = getDefaultWindowListLocked();
10992                for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
10993                    final WindowState win = windows.get(winNdx);
10994                    if (win.mHasSurface) {
10995                        win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
10996                        // Force add to mResizingWindows.
10997                        win.mLastContentInsets.set(-1, -1, -1, -1);
10998                        mWaitingForDrawn.add(win);
10999                    }
11000                }
11001                requestTraversalLocked();
11002                mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
11003                mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
11004            }
11005            checkDrawnWindowsLocked();
11006        }
11007    }
11008}
11009