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